1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_errors.h"
43 #include "bgpd/bgp_label.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_ecommunity.h"
46 #include "bgpd/bgp_lcommunity.h"
47 #include "bgpd/bgp_updgrp.h"
48 #include "bgpd/bgp_encap_types.h"
50 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
51 #include "bgp_encap_types.h"
52 #include "bgp_vnc_types.h"
55 #include "bgp_flowspec_private.h"
58 /* Attribute strings for logging. */
59 static const struct message attr_str
[] = {
60 {BGP_ATTR_ORIGIN
, "ORIGIN"},
61 {BGP_ATTR_AS_PATH
, "AS_PATH"},
62 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
63 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
64 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
65 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
66 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
67 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
68 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
69 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
70 {BGP_ATTR_DPA
, "DPA"},
71 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
72 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
73 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
74 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
75 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
76 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
77 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
78 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
79 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
80 {BGP_ATTR_ENCAP
, "ENCAP"},
81 #if ENABLE_BGP_VNC_ATTR
82 {BGP_ATTR_VNC
, "VNC"},
84 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
85 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
88 static const struct message attr_flag_str
[] = {
89 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
90 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
91 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
92 /* bgp_attr_flags_diagnose() relies on this bit being last in
94 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
97 static struct hash
*cluster_hash
;
99 static void *cluster_hash_alloc(void *p
)
101 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
102 struct cluster_list
*cluster
;
104 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
105 cluster
->length
= val
->length
;
107 if (cluster
->length
) {
108 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
109 memcpy(cluster
->list
, val
->list
, val
->length
);
111 cluster
->list
= NULL
;
118 /* Cluster list related functions. */
119 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
121 struct cluster_list tmp
;
122 struct cluster_list
*cluster
;
127 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
132 int cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
136 for (i
= 0; i
< cluster
->length
/ 4; i
++)
137 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
142 static unsigned int cluster_hash_key_make(const void *p
)
144 const struct cluster_list
*cluster
= p
;
146 return jhash(cluster
->list
, cluster
->length
, 0);
149 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
151 const struct cluster_list
*cluster1
= p1
;
152 const struct cluster_list
*cluster2
= p2
;
154 return (cluster1
->length
== cluster2
->length
155 && memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
)
159 static void cluster_free(struct cluster_list
*cluster
)
161 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
162 XFREE(MTYPE_CLUSTER
, cluster
);
165 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
167 struct cluster_list
*find
;
169 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
175 void cluster_unintern(struct cluster_list
*cluster
)
180 if (cluster
->refcnt
== 0) {
181 hash_release(cluster_hash
, cluster
);
182 cluster_free(cluster
);
186 static void cluster_init(void)
188 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
192 static void cluster_finish(void)
194 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
195 hash_free(cluster_hash
);
199 static struct hash
*encap_hash
= NULL
;
201 static struct hash
*vnc_hash
= NULL
;
204 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
206 struct bgp_attr_encap_subtlv
*new;
207 struct bgp_attr_encap_subtlv
*tail
;
208 struct bgp_attr_encap_subtlv
*p
;
210 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
211 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
213 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
216 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
219 memcpy(tail
, p
, size
);
226 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
228 struct bgp_attr_encap_subtlv
*next
;
232 XFREE(MTYPE_ENCAP_TLV
, p
);
237 void bgp_attr_flush_encap(struct attr
*attr
)
242 if (attr
->encap_subtlvs
) {
243 encap_free(attr
->encap_subtlvs
);
244 attr
->encap_subtlvs
= NULL
;
247 if (attr
->vnc_subtlvs
) {
248 encap_free(attr
->vnc_subtlvs
);
249 attr
->vnc_subtlvs
= NULL
;
255 * Compare encap sub-tlv chains
260 * This algorithm could be made faster if needed
262 static int encap_same(const struct bgp_attr_encap_subtlv
*h1
,
263 const struct bgp_attr_encap_subtlv
*h2
)
265 const struct bgp_attr_encap_subtlv
*p
;
266 const struct bgp_attr_encap_subtlv
*q
;
270 if (h1
== NULL
|| h2
== NULL
)
273 for (p
= h1
; p
; p
= p
->next
) {
274 for (q
= h2
; q
; q
= q
->next
) {
275 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
276 && !memcmp(p
->value
, q
->value
, p
->length
)) {
285 for (p
= h2
; p
; p
= p
->next
) {
286 for (q
= h1
; q
; q
= q
->next
) {
287 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
288 && !memcmp(p
->value
, q
->value
, p
->length
)) {
300 static void *encap_hash_alloc(void *p
)
302 /* Encap structure is already allocated. */
313 static struct bgp_attr_encap_subtlv
*
314 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
316 struct bgp_attr_encap_subtlv
*find
;
317 struct hash
*hash
= encap_hash
;
319 if (type
== VNC_SUBTLV_TYPE
)
323 find
= hash_get(hash
, encap
, encap_hash_alloc
);
331 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
332 encap_subtlv_type type
)
334 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
338 if (encap
->refcnt
== 0) {
339 struct hash
*hash
= encap_hash
;
341 if (type
== VNC_SUBTLV_TYPE
)
344 hash_release(hash
, encap
);
350 static unsigned int encap_hash_key_make(const void *p
)
352 const struct bgp_attr_encap_subtlv
*encap
= p
;
354 return jhash(encap
->value
, encap
->length
, 0);
357 static bool encap_hash_cmp(const void *p1
, const void *p2
)
359 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
360 (const struct bgp_attr_encap_subtlv
*)p2
);
363 static void encap_init(void)
365 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
368 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
373 static void encap_finish(void)
375 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
376 hash_free(encap_hash
);
379 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
385 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
393 return !memcmp(&(a1
->evpn_overlay
), &(a2
->evpn_overlay
),
394 sizeof(struct bgp_route_evpn
));
397 /* Unknown transit attribute. */
398 static struct hash
*transit_hash
;
400 static void transit_free(struct transit
*transit
)
402 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
403 XFREE(MTYPE_TRANSIT
, transit
);
406 static void *transit_hash_alloc(void *p
)
408 /* Transit structure is already allocated. */
412 static struct transit
*transit_intern(struct transit
*transit
)
414 struct transit
*find
;
416 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
418 transit_free(transit
);
424 void transit_unintern(struct transit
*transit
)
429 if (transit
->refcnt
== 0) {
430 hash_release(transit_hash
, transit
);
431 transit_free(transit
);
435 static unsigned int transit_hash_key_make(const void *p
)
437 const struct transit
*transit
= p
;
439 return jhash(transit
->val
, transit
->length
, 0);
442 static bool transit_hash_cmp(const void *p1
, const void *p2
)
444 const struct transit
*transit1
= p1
;
445 const struct transit
*transit2
= p2
;
447 return (transit1
->length
== transit2
->length
448 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
451 static void transit_init(void)
453 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
457 static void transit_finish(void)
459 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
460 hash_free(transit_hash
);
464 /* Attribute hash routines. */
465 static struct hash
*attrhash
;
467 /* Shallow copy of an attribute
468 * Though, not so shallow that it doesn't copy the contents
469 * of the attr_extra pointed to by 'extra'
471 void bgp_attr_dup(struct attr
*new, struct attr
*orig
)
476 unsigned long int attr_count(void)
478 return attrhash
->count
;
481 unsigned long int attr_unknown_count(void)
483 return transit_hash
->count
;
486 unsigned int attrhash_key_make(const void *p
)
488 const struct attr
*attr
= (struct attr
*)p
;
490 #define MIX(val) key = jhash_1word(val, key)
491 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
493 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
494 MIX3(attr
->local_pref
, attr
->aggregator_as
,
495 attr
->aggregator_addr
.s_addr
);
496 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
497 attr
->originator_id
.s_addr
);
498 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
501 MIX(aspath_key_make(attr
->aspath
));
503 MIX(community_hash_make(attr
->community
));
505 if (attr
->lcommunity
)
506 MIX(lcommunity_hash_make(attr
->lcommunity
));
507 if (attr
->ecommunity
)
508 MIX(ecommunity_hash_make(attr
->ecommunity
));
510 MIX(cluster_hash_key_make(attr
->cluster
));
512 MIX(transit_hash_key_make(attr
->transit
));
513 if (attr
->encap_subtlvs
)
514 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
516 if (attr
->vnc_subtlvs
)
517 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
519 MIX(attr
->mp_nexthop_len
);
520 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
521 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
522 MIX(attr
->nh_ifindex
);
523 MIX(attr
->nh_lla_ifindex
);
528 bool attrhash_cmp(const void *p1
, const void *p2
)
530 const struct attr
*attr1
= p1
;
531 const struct attr
*attr2
= p2
;
533 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
534 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
535 && attr1
->aspath
== attr2
->aspath
536 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
537 && attr1
->local_pref
== attr2
->local_pref
538 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
539 if (attr1
->aggregator_as
== attr2
->aggregator_as
540 && attr1
->aggregator_addr
.s_addr
541 == attr2
->aggregator_addr
.s_addr
542 && attr1
->weight
== attr2
->weight
543 && attr1
->tag
== attr2
->tag
544 && attr1
->label_index
== attr2
->label_index
545 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
546 && attr1
->ecommunity
== attr2
->ecommunity
547 && attr1
->lcommunity
== attr2
->lcommunity
548 && attr1
->cluster
== attr2
->cluster
549 && attr1
->transit
== attr2
->transit
550 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
551 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
553 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
555 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
556 &attr2
->mp_nexthop_global
)
557 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
558 &attr2
->mp_nexthop_local
)
559 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
560 &attr2
->mp_nexthop_global_in
)
561 && IPV4_ADDR_SAME(&attr1
->originator_id
,
562 &attr2
->originator_id
)
563 && overlay_index_same(attr1
, attr2
)
564 && attr1
->nh_ifindex
== attr2
->nh_ifindex
565 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
)
572 static void attrhash_init(void)
575 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
579 * special for hash_clean below
581 static void attr_vfree(void *attr
)
583 XFREE(MTYPE_ATTR
, attr
);
586 static void attrhash_finish(void)
588 hash_clean(attrhash
, attr_vfree
);
593 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
595 struct attr
*attr
= bucket
->data
;
597 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
598 inet_ntoa(attr
->nexthop
));
599 vty_out(vty
, "\tflags: %" PRIu64
" med: %u local_pref: %u origin: %u weight: %u label: %u\n",
600 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
601 attr
->weight
, attr
->label
);
604 void attr_show_all(struct vty
*vty
)
606 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
607 void *))attr_show_all_iterator
,
611 static void *bgp_attr_hash_alloc(void *p
)
613 struct attr
*val
= (struct attr
*)p
;
616 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
618 if (val
->encap_subtlvs
) {
619 val
->encap_subtlvs
= NULL
;
622 if (val
->vnc_subtlvs
) {
623 val
->vnc_subtlvs
= NULL
;
630 /* Internet argument attribute. */
631 struct attr
*bgp_attr_intern(struct attr
*attr
)
635 /* Intern referenced strucutre. */
637 if (!attr
->aspath
->refcnt
)
638 attr
->aspath
= aspath_intern(attr
->aspath
);
640 attr
->aspath
->refcnt
++;
642 if (attr
->community
) {
643 if (!attr
->community
->refcnt
)
644 attr
->community
= community_intern(attr
->community
);
646 attr
->community
->refcnt
++;
649 if (attr
->ecommunity
) {
650 if (!attr
->ecommunity
->refcnt
)
651 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
653 attr
->ecommunity
->refcnt
++;
655 if (attr
->lcommunity
) {
656 if (!attr
->lcommunity
->refcnt
)
657 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
659 attr
->lcommunity
->refcnt
++;
662 if (!attr
->cluster
->refcnt
)
663 attr
->cluster
= cluster_intern(attr
->cluster
);
665 attr
->cluster
->refcnt
++;
668 if (!attr
->transit
->refcnt
)
669 attr
->transit
= transit_intern(attr
->transit
);
671 attr
->transit
->refcnt
++;
673 if (attr
->encap_subtlvs
) {
674 if (!attr
->encap_subtlvs
->refcnt
)
675 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
678 attr
->encap_subtlvs
->refcnt
++;
681 if (attr
->vnc_subtlvs
) {
682 if (!attr
->vnc_subtlvs
->refcnt
)
683 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
686 attr
->vnc_subtlvs
->refcnt
++;
690 /* At this point, attr only contains intern'd pointers. that means
691 * if we find it in attrhash, it has all the same pointers and we
692 * correctly updated the refcounts on these.
693 * If we don't find it, we need to allocate a one because in all
694 * cases this returns a new reference to a hashed attr, but the input
696 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
702 /* Make network statement's attribute. */
703 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
705 memset(attr
, 0, sizeof(struct attr
));
707 attr
->origin
= origin
;
708 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
709 attr
->aspath
= aspath_empty();
710 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
711 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
713 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
714 attr
->label
= MPLS_INVALID_LABEL
;
715 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
716 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
721 /* Create the attributes for an aggregate */
722 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, uint8_t origin
,
723 struct aspath
*aspath
,
724 struct community
*community
,
725 struct ecommunity
*ecommunity
,
726 struct lcommunity
*lcommunity
,
727 int as_set
, uint8_t atomic_aggregate
)
732 memset(&attr
, 0, sizeof(struct attr
));
734 /* Origin attribute. */
735 attr
.origin
= origin
;
736 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
738 /* AS path attribute. */
740 attr
.aspath
= aspath_intern(aspath
);
742 attr
.aspath
= aspath_empty();
743 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
745 /* Next hop attribute. */
746 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
749 uint32_t gshut
= COMMUNITY_GSHUT
;
751 /* If we are not shutting down ourselves and we are
752 * aggregating a route that contains the GSHUT community we
753 * need to remove that community when creating the aggregate */
754 if (!bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)
755 && community_include(community
, gshut
)) {
756 community_del_val(community
, &gshut
);
759 attr
.community
= community
;
760 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
764 attr
.ecommunity
= ecommunity
;
765 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
769 attr
.lcommunity
= lcommunity
;
770 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
773 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
774 bgp_attr_add_gshut_community(&attr
);
777 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
778 attr
.label
= MPLS_INVALID_LABEL
;
779 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
780 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
781 if (!as_set
|| atomic_aggregate
)
782 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
783 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
784 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
785 attr
.aggregator_as
= bgp
->confed_id
;
787 attr
.aggregator_as
= bgp
->as
;
788 attr
.aggregator_addr
= bgp
->router_id
;
789 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
790 attr
.label
= MPLS_INVALID_LABEL
;
792 new = bgp_attr_intern(&attr
);
794 aspath_unintern(&new->aspath
);
798 /* Unintern just the sub-components of the attr, but not the attr */
799 void bgp_attr_unintern_sub(struct attr
*attr
)
801 /* aspath refcount shoud be decrement. */
803 aspath_unintern(&attr
->aspath
);
804 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
807 community_unintern(&attr
->community
);
808 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
810 if (attr
->ecommunity
)
811 ecommunity_unintern(&attr
->ecommunity
);
812 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
814 if (attr
->lcommunity
)
815 lcommunity_unintern(&attr
->lcommunity
);
816 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
819 cluster_unintern(attr
->cluster
);
820 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
823 transit_unintern(attr
->transit
);
825 if (attr
->encap_subtlvs
)
826 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
829 if (attr
->vnc_subtlvs
)
830 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
835 * We have some show commands that let you experimentally
836 * apply a route-map. When we apply the route-map
837 * we are reseting values but not saving them for
838 * posterity via intern'ing( because route-maps don't
839 * do that) but at this point in time we need
840 * to compare the new attr to the old and if the
841 * routemap has changed it we need to, as Snoop Dog says,
842 * Drop it like it's hot
844 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
846 if (new->aspath
!= old
->aspath
)
847 aspath_free(new->aspath
);
849 if (new->community
!= old
->community
)
850 community_free(&new->community
);
852 if (new->ecommunity
!= old
->ecommunity
)
853 ecommunity_free(&new->ecommunity
);
855 if (new->lcommunity
!= old
->lcommunity
)
856 lcommunity_free(&new->lcommunity
);
859 /* Free bgp attribute and aspath. */
860 void bgp_attr_unintern(struct attr
**pattr
)
862 struct attr
*attr
= *pattr
;
866 /* Decrement attribute reference. */
871 /* If reference becomes zero then free attribute object. */
872 if (attr
->refcnt
== 0) {
873 ret
= hash_release(attrhash
, attr
);
875 XFREE(MTYPE_ATTR
, attr
);
879 bgp_attr_unintern_sub(&tmp
);
882 void bgp_attr_flush(struct attr
*attr
)
884 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
885 aspath_free(attr
->aspath
);
888 if (attr
->community
&& !attr
->community
->refcnt
)
889 community_free(&attr
->community
);
890 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
891 ecommunity_free(&attr
->ecommunity
);
892 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
893 lcommunity_free(&attr
->lcommunity
);
894 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
895 cluster_free(attr
->cluster
);
896 attr
->cluster
= NULL
;
898 if (attr
->transit
&& !attr
->transit
->refcnt
) {
899 transit_free(attr
->transit
);
900 attr
->transit
= NULL
;
902 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
903 encap_free(attr
->encap_subtlvs
);
904 attr
->encap_subtlvs
= NULL
;
907 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
908 encap_free(attr
->vnc_subtlvs
);
909 attr
->vnc_subtlvs
= NULL
;
914 /* Implement draft-scudder-idr-optional-transitive behaviour and
915 * avoid resetting sessions for malformed attributes which are
916 * are partial/optional and hence where the error likely was not
917 * introduced by the sending neighbour.
919 static bgp_attr_parse_ret_t
920 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
923 struct peer
*const peer
= args
->peer
;
924 const uint8_t flags
= args
->flags
;
925 /* startp and length must be special-cased, as whether or not to
926 * send the attribute data with the NOTIFY depends on the error,
927 * the caller therefore signals this with the seperate length argument
929 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
931 /* Only relax error handling for eBGP peers */
932 if (peer
->sort
!= BGP_PEER_EBGP
) {
933 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
934 notify_datap
, length
);
935 return BGP_ATTR_PARSE_ERROR
;
938 /* Adjust the stream getp to the end of the attribute, in case we can
939 * still proceed but the caller hasn't read all the attribute.
941 stream_set_getp(BGP_INPUT(peer
),
942 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
945 switch (args
->type
) {
946 /* where an attribute is relatively inconsequential, e.g. it does not
947 * affect route selection, and can be safely ignored, then any such
948 * attributes which are malformed should just be ignored and the route
949 * processed as normal.
951 case BGP_ATTR_AS4_AGGREGATOR
:
952 case BGP_ATTR_AGGREGATOR
:
953 case BGP_ATTR_ATOMIC_AGGREGATE
:
954 return BGP_ATTR_PARSE_PROCEED
;
956 /* Core attributes, particularly ones which may influence route
957 * selection, should always cause session resets
959 case BGP_ATTR_ORIGIN
:
960 case BGP_ATTR_AS_PATH
:
961 case BGP_ATTR_NEXT_HOP
:
962 case BGP_ATTR_MULTI_EXIT_DISC
:
963 case BGP_ATTR_LOCAL_PREF
:
964 case BGP_ATTR_COMMUNITIES
:
965 case BGP_ATTR_ORIGINATOR_ID
:
966 case BGP_ATTR_CLUSTER_LIST
:
967 case BGP_ATTR_MP_REACH_NLRI
:
968 case BGP_ATTR_MP_UNREACH_NLRI
:
969 case BGP_ATTR_EXT_COMMUNITIES
:
970 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
971 notify_datap
, length
);
972 return BGP_ATTR_PARSE_ERROR
;
975 /* Partial optional attributes that are malformed should not cause
976 * the whole session to be reset. Instead treat it as a withdrawal
977 * of the routes, if possible.
979 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
980 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
981 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
982 return BGP_ATTR_PARSE_WITHDRAW
;
984 /* default to reset */
985 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
988 /* Find out what is wrong with the path attribute flag bits and log the error.
989 "Flag bits" here stand for Optional, Transitive and Partial, but not for
990 Extended Length. Checking O/T/P bits at once implies, that the attribute
991 being diagnosed is defined by RFC as either a "well-known" or an "optional,
992 non-transitive" attribute. */
994 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
995 uint8_t desired_flags
/* how RFC says it must be */
999 uint8_t real_flags
= args
->flags
;
1000 const uint8_t attr_code
= args
->type
;
1002 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1003 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1004 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1005 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1006 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1007 flog_err(EC_BGP_ATTR_FLAG
,
1008 "%s attribute must%s be flagged as \"%s\"",
1009 lookup_msg(attr_str
, attr_code
, NULL
),
1010 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1013 attr_flag_str
[i
].str
);
1018 "Strange, %s called for attr %s, but no problem found with flags"
1019 " (real flags 0x%x, desired 0x%x)",
1020 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1021 real_flags
, desired_flags
);
1025 /* Required flags for attributes. EXTLEN will be masked off when testing,
1026 * as will PARTIAL for optional+transitive attributes.
1028 const uint8_t attr_flags_values
[] = {
1029 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1030 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1031 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1032 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1033 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1034 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1035 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1036 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1037 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1038 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1039 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1040 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1041 [BGP_ATTR_EXT_COMMUNITIES
] =
1042 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1043 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1044 [BGP_ATTR_AS4_AGGREGATOR
] =
1045 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1046 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1047 [BGP_ATTR_LARGE_COMMUNITIES
] =
1048 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1049 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1051 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1053 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1055 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1056 const uint8_t flags
= args
->flags
;
1057 const uint8_t attr_code
= args
->type
;
1059 /* there may be attributes we don't know about */
1060 if (attr_code
> attr_flags_values_max
)
1062 if (attr_flags_values
[attr_code
] == 0)
1065 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1069 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1070 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1073 "%s well-known attributes must have transitive flag set (%x)",
1074 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1078 /* "For well-known attributes and for optional non-transitive
1080 * the Partial bit MUST be set to 0."
1082 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1083 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1084 flog_err(EC_BGP_ATTR_FLAG
,
1085 "%s well-known attribute "
1086 "must NOT have the partial flag set (%x)",
1087 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1090 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1091 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1092 flog_err(EC_BGP_ATTR_FLAG
,
1093 "%s optional + transitive attribute "
1094 "must NOT have the partial flag set (%x)",
1095 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1100 /* Optional transitive attributes may go through speakers that don't
1101 * reocgnise them and set the Partial bit.
1103 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1104 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1105 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1107 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1110 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1114 /* Get origin attribute of the update message. */
1115 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1117 struct peer
*const peer
= args
->peer
;
1118 struct attr
*const attr
= args
->attr
;
1119 const bgp_size_t length
= args
->length
;
1121 /* If any recognized attribute has Attribute Length that conflicts
1122 with the expected length (based on the attribute type code), then
1123 the Error Subcode is set to Attribute Length Error. The Data
1124 field contains the erroneous attribute (type, length and
1127 flog_err(EC_BGP_ATTR_LEN
,
1128 "Origin attribute length is not one %d", length
);
1129 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1133 /* Fetch origin attribute. */
1134 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1136 /* If the ORIGIN attribute has an undefined value, then the Error
1137 Subcode is set to Invalid Origin Attribute. The Data field
1138 contains the unrecognized attribute (type, length and value). */
1139 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1140 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1141 flog_err(EC_BGP_ATTR_ORIGIN
,
1142 "Origin attribute value is invalid %d", attr
->origin
);
1143 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1147 /* Set oring attribute flag. */
1148 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1153 /* Parse AS path information. This function is wrapper of
1155 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1157 struct attr
*const attr
= args
->attr
;
1158 struct peer
*const peer
= args
->peer
;
1159 const bgp_size_t length
= args
->length
;
1162 * peer with AS4 => will get 4Byte ASnums
1163 * otherwise, will get 16 Bit
1165 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1166 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1168 /* In case of IBGP, length will be zero. */
1169 if (!attr
->aspath
) {
1170 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1171 "Malformed AS path from %s, length is %d", peer
->host
,
1173 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1177 /* Set aspath attribute flag. */
1178 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1180 return BGP_ATTR_PARSE_PROCEED
;
1183 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1184 struct attr
*const attr
)
1186 /* These checks were part of bgp_attr_aspath, but with
1187 * as4 we should to check aspath things when
1188 * aspath synthesizing with as4_path has already taken place.
1189 * Otherwise we check ASPATH and use the synthesized thing, and that is
1191 * So do the checks later, i.e. here
1193 struct aspath
*aspath
;
1195 /* Confederation sanity check. */
1196 if ((peer
->sort
== BGP_PEER_CONFED
1197 && !aspath_left_confed_check(attr
->aspath
))
1198 || (peer
->sort
== BGP_PEER_EBGP
1199 && aspath_confed_check(attr
->aspath
))) {
1200 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1202 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1203 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1204 return BGP_ATTR_PARSE_ERROR
;
1207 /* First AS check for EBGP. */
1208 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1209 if (peer
->sort
== BGP_PEER_EBGP
1210 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1211 flog_err(EC_BGP_ATTR_FIRST_AS
,
1212 "%s incorrect first AS (must be %u)",
1213 peer
->host
, peer
->as
);
1214 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1215 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1216 return BGP_ATTR_PARSE_ERROR
;
1220 /* local-as prepend */
1221 if (peer
->change_local_as
1222 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1223 aspath
= aspath_dup(attr
->aspath
);
1224 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1225 aspath_unintern(&attr
->aspath
);
1226 attr
->aspath
= aspath_intern(aspath
);
1229 return BGP_ATTR_PARSE_PROCEED
;
1232 /* Parse AS4 path information. This function is another wrapper of
1234 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1235 struct aspath
**as4_path
)
1237 struct peer
*const peer
= args
->peer
;
1238 struct attr
*const attr
= args
->attr
;
1239 const bgp_size_t length
= args
->length
;
1241 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1243 /* In case of IBGP, length will be zero. */
1245 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1246 "Malformed AS4 path from %s, length is %d", peer
->host
,
1248 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1252 /* Set aspath attribute flag. */
1253 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1255 return BGP_ATTR_PARSE_PROCEED
;
1259 * Check that the nexthop attribute is valid.
1261 bgp_attr_parse_ret_t
1262 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1264 in_addr_t nexthop_h
;
1266 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1267 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1268 || IPV4_CLASS_DE(nexthop_h
))
1269 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1270 char buf
[INET_ADDRSTRLEN
];
1272 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1274 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1276 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1277 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
);
1278 return BGP_ATTR_PARSE_ERROR
;
1281 return BGP_ATTR_PARSE_PROCEED
;
1284 /* Nexthop attribute. */
1285 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1287 struct peer
*const peer
= args
->peer
;
1288 struct attr
*const attr
= args
->attr
;
1289 const bgp_size_t length
= args
->length
;
1291 /* Check nexthop attribute length. */
1293 flog_err(EC_BGP_ATTR_LEN
,
1294 "Nexthop attribute length isn't four [%d]", length
);
1296 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1300 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1301 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1303 return BGP_ATTR_PARSE_PROCEED
;
1306 /* MED atrribute. */
1307 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1309 struct peer
*const peer
= args
->peer
;
1310 struct attr
*const attr
= args
->attr
;
1311 const bgp_size_t length
= args
->length
;
1315 flog_err(EC_BGP_ATTR_LEN
,
1316 "MED attribute length isn't four [%d]", length
);
1318 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1322 attr
->med
= stream_getl(peer
->curr
);
1324 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1326 return BGP_ATTR_PARSE_PROCEED
;
1329 /* Local preference attribute. */
1330 static bgp_attr_parse_ret_t
1331 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1333 struct peer
*const peer
= args
->peer
;
1334 struct attr
*const attr
= args
->attr
;
1335 const bgp_size_t length
= args
->length
;
1339 flog_err(EC_BGP_ATTR_LEN
,
1340 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1341 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1345 /* If it is contained in an UPDATE message that is received from an
1346 external peer, then this attribute MUST be ignored by the
1347 receiving speaker. */
1348 if (peer
->sort
== BGP_PEER_EBGP
) {
1349 stream_forward_getp(peer
->curr
, length
);
1350 return BGP_ATTR_PARSE_PROCEED
;
1353 attr
->local_pref
= stream_getl(peer
->curr
);
1355 /* Set the local-pref flag. */
1356 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1358 return BGP_ATTR_PARSE_PROCEED
;
1361 /* Atomic aggregate. */
1362 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1364 struct attr
*const attr
= args
->attr
;
1365 const bgp_size_t length
= args
->length
;
1369 flog_err(EC_BGP_ATTR_LEN
,
1370 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1372 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1376 /* Set atomic aggregate flag. */
1377 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1379 return BGP_ATTR_PARSE_PROCEED
;
1382 /* Aggregator attribute */
1383 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1385 struct peer
*const peer
= args
->peer
;
1386 struct attr
*const attr
= args
->attr
;
1387 const bgp_size_t length
= args
->length
;
1391 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1392 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1395 if (length
!= wantedlen
) {
1396 flog_err(EC_BGP_ATTR_LEN
,
1397 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1399 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1403 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1404 attr
->aggregator_as
= stream_getl(peer
->curr
);
1406 attr
->aggregator_as
= stream_getw(peer
->curr
);
1407 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1409 /* Set atomic aggregate flag. */
1410 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1412 return BGP_ATTR_PARSE_PROCEED
;
1415 /* New Aggregator attribute */
1416 static bgp_attr_parse_ret_t
1417 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1418 as_t
*as4_aggregator_as
,
1419 struct in_addr
*as4_aggregator_addr
)
1421 struct peer
*const peer
= args
->peer
;
1422 struct attr
*const attr
= args
->attr
;
1423 const bgp_size_t length
= args
->length
;
1426 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1428 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1432 *as4_aggregator_as
= stream_getl(peer
->curr
);
1433 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1435 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1437 return BGP_ATTR_PARSE_PROCEED
;
1440 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1442 static bgp_attr_parse_ret_t
1443 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1444 struct aspath
*as4_path
, as_t as4_aggregator
,
1445 struct in_addr
*as4_aggregator_addr
)
1447 int ignore_as4_path
= 0;
1448 struct aspath
*newpath
;
1450 if (!attr
->aspath
) {
1451 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1453 * checked that all well-known, mandatory attributes were
1456 * Can only be a problem with peer itself - hard error
1458 return BGP_ATTR_PARSE_ERROR
;
1461 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1462 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1464 * It is worth a warning though, because the peer really
1465 * should not send them
1467 if (BGP_DEBUG(as4
, AS4
)) {
1468 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1469 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1470 "AS4 capable peer, yet it sent");
1473 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1474 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1476 "AS4 capable peer, yet it sent");
1479 return BGP_ATTR_PARSE_PROCEED
;
1482 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1483 * because that may override AS4_PATH
1485 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1486 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1488 * if the as_number in aggregator is not AS_TRANS,
1489 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1490 * and the Aggregator shall be taken as
1491 * info on the aggregating node, and the AS_PATH
1492 * shall be taken as the AS_PATH
1494 * the Aggregator shall be ignored and the
1495 * AS4_AGGREGATOR shall be taken as the
1496 * Aggregating node and the AS_PATH is to be
1497 * constructed "as in all other cases"
1499 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1501 if (BGP_DEBUG(as4
, AS4
))
1503 "[AS4] %s BGP not AS4 capable peer"
1504 " send AGGREGATOR != AS_TRANS and"
1505 " AS4_AGGREGATOR, so ignore"
1506 " AS4_AGGREGATOR and AS4_PATH",
1508 ignore_as4_path
= 1;
1510 /* "New_aggregator shall be taken as aggregator"
1512 attr
->aggregator_as
= as4_aggregator
;
1513 attr
->aggregator_addr
.s_addr
=
1514 as4_aggregator_addr
->s_addr
;
1517 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1518 * That is bogus - but reading the conditions
1519 * we have to handle AS4_AGGREGATOR as if it were
1520 * AGGREGATOR in that case
1522 if (BGP_DEBUG(as4
, AS4
))
1524 "[AS4] %s BGP not AS4 capable peer send"
1525 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1526 " it as if AGGREGATOR with AS_TRANS had been there",
1528 attr
->aggregator_as
= as4_aggregator
;
1529 /* sweep it under the carpet and simulate a "good"
1531 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1535 /* need to reconcile NEW_AS_PATH and AS_PATH */
1536 if (!ignore_as4_path
1537 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1538 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1540 return BGP_ATTR_PARSE_ERROR
;
1542 aspath_unintern(&attr
->aspath
);
1543 attr
->aspath
= aspath_intern(newpath
);
1545 return BGP_ATTR_PARSE_PROCEED
;
1548 /* Community attribute. */
1549 static bgp_attr_parse_ret_t
1550 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1552 struct peer
*const peer
= args
->peer
;
1553 struct attr
*const attr
= args
->attr
;
1554 const bgp_size_t length
= args
->length
;
1557 attr
->community
= NULL
;
1558 return BGP_ATTR_PARSE_PROCEED
;
1562 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1564 /* XXX: fix community_parse to use stream API and remove this */
1565 stream_forward_getp(peer
->curr
, length
);
1567 if (!attr
->community
)
1568 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1571 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1573 return BGP_ATTR_PARSE_PROCEED
;
1576 /* Originator ID attribute. */
1577 static bgp_attr_parse_ret_t
1578 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1580 struct peer
*const peer
= args
->peer
;
1581 struct attr
*const attr
= args
->attr
;
1582 const bgp_size_t length
= args
->length
;
1586 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1589 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1593 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1595 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1597 return BGP_ATTR_PARSE_PROCEED
;
1600 /* Cluster list attribute. */
1601 static bgp_attr_parse_ret_t
1602 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1604 struct peer
*const peer
= args
->peer
;
1605 struct attr
*const attr
= args
->attr
;
1606 const bgp_size_t length
= args
->length
;
1610 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
1612 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1617 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1619 /* XXX: Fix cluster_parse to use stream API and then remove this */
1620 stream_forward_getp(peer
->curr
, length
);
1622 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1624 return BGP_ATTR_PARSE_PROCEED
;
1627 /* Multiprotocol reachability information parse. */
1628 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1629 struct bgp_nlri
*mp_update
)
1633 iana_safi_t pkt_safi
;
1635 bgp_size_t nlri_len
;
1638 struct peer
*const peer
= args
->peer
;
1639 struct attr
*const attr
= args
->attr
;
1640 const bgp_size_t length
= args
->length
;
1642 /* Set end of packet. */
1643 s
= BGP_INPUT(peer
);
1644 start
= stream_get_getp(s
);
1646 /* safe to read statically sized header? */
1647 #define BGP_MP_REACH_MIN_SIZE 5
1648 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1649 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1650 zlog_info("%s: %s sent invalid length, %lu", __func__
,
1651 peer
->host
, (unsigned long)length
);
1652 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1655 /* Load AFI, SAFI. */
1656 pkt_afi
= stream_getw(s
);
1657 pkt_safi
= stream_getc(s
);
1659 /* Convert AFI, SAFI to internal values, check. */
1660 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1661 /* Log if AFI or SAFI is unrecognized. This is not an error
1663 * the attribute is otherwise malformed.
1665 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1667 "%s: MP_REACH received AFI %s or SAFI %s is unrecognized",
1668 peer
->host
, iana_afi2str(pkt_afi
),
1669 iana_safi2str(pkt_safi
));
1670 return BGP_ATTR_PARSE_ERROR
;
1673 /* Get nexthop length. */
1674 attr
->mp_nexthop_len
= stream_getc(s
);
1676 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1678 "%s: %s, MP nexthop length, %u, goes past end of attribute",
1679 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1680 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1683 /* Nexthop length check. */
1684 switch (attr
->mp_nexthop_len
) {
1686 if (safi
!= SAFI_FLOWSPEC
) {
1687 zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
1688 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1689 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1692 case BGP_ATTR_NHLEN_VPNV4
:
1693 stream_getl(s
); /* RD high */
1694 stream_getl(s
); /* RD low */
1696 * NOTE: intentional fall through
1697 * - for consistency in rx processing
1699 * The following comment is to signal GCC this intention
1700 * and suppress the warning
1703 case BGP_ATTR_NHLEN_IPV4
:
1704 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1705 /* Probably needed for RFC 2283 */
1706 if (attr
->nexthop
.s_addr
== 0)
1707 memcpy(&attr
->nexthop
.s_addr
,
1708 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1710 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1711 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1712 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1713 stream_getl(s
); /* RD high */
1714 stream_getl(s
); /* RD low */
1716 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1717 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1718 if (!peer
->nexthop
.ifp
) {
1719 zlog_warn("%s: Received a V6/VPNV6 Global attribute but address is a V6 LL and we have no peer interface information, withdrawing",
1721 return BGP_ATTR_PARSE_WITHDRAW
;
1723 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1726 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1727 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1728 if (attr
->mp_nexthop_len
1729 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1730 stream_getl(s
); /* RD high */
1731 stream_getl(s
); /* RD low */
1733 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1734 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1735 if (!peer
->nexthop
.ifp
) {
1736 zlog_warn("%s: Received V6/VPNV6 Global and LL attribute but global address is a V6 LL and we have no peer interface information, withdrawing",
1738 return BGP_ATTR_PARSE_WITHDRAW
;
1740 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1742 if (attr
->mp_nexthop_len
1743 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1744 stream_getl(s
); /* RD high */
1745 stream_getl(s
); /* RD low */
1747 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1748 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1749 char buf1
[INET6_ADDRSTRLEN
];
1750 char buf2
[INET6_ADDRSTRLEN
];
1752 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1754 "%s rcvd nexthops %s, %s -- ignoring non-LL value",
1757 &attr
->mp_nexthop_global
,
1758 buf1
, INET6_ADDRSTRLEN
),
1760 &attr
->mp_nexthop_local
, buf2
,
1763 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1765 if (!peer
->nexthop
.ifp
) {
1766 zlog_warn("%s: Received a V6 LL nexthop and we have no peer interface information, withdrawing",
1768 return BGP_ATTR_PARSE_WITHDRAW
;
1770 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1773 zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
1774 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1775 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1779 zlog_info("%s: (%s) Failed to read SNPA and NLRI(s)", __func__
,
1781 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1786 if ((val
= stream_getc(s
)))
1788 EC_BGP_DEFUNCT_SNPA_LEN
,
1789 "%s sent non-zero value, %u, for defunct SNPA-length field",
1793 /* must have nrli_len, what is left of the attribute */
1794 nlri_len
= LEN_LEFT
;
1795 if (nlri_len
> STREAM_READABLE(s
)) {
1796 zlog_info("%s: (%s) Failed to read NLRI", __func__
, peer
->host
);
1797 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1801 zlog_info("%s: (%s) No Reachability, Treating as a EOR marker",
1802 __func__
, peer
->host
);
1804 mp_update
->afi
= afi
;
1805 mp_update
->safi
= safi
;
1806 return BGP_ATTR_PARSE_EOR
;
1809 mp_update
->afi
= afi
;
1810 mp_update
->safi
= safi
;
1811 mp_update
->nlri
= stream_pnt(s
);
1812 mp_update
->length
= nlri_len
;
1814 stream_forward_getp(s
, nlri_len
);
1816 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
1818 return BGP_ATTR_PARSE_PROCEED
;
1822 /* Multiprotocol unreachable parse */
1823 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
1824 struct bgp_nlri
*mp_withdraw
)
1829 iana_safi_t pkt_safi
;
1831 uint16_t withdraw_len
;
1832 struct peer
*const peer
= args
->peer
;
1833 struct attr
*const attr
= args
->attr
;
1834 const bgp_size_t length
= args
->length
;
1838 #define BGP_MP_UNREACH_MIN_SIZE 3
1839 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1840 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1842 pkt_afi
= stream_getw(s
);
1843 pkt_safi
= stream_getc(s
);
1845 /* Convert AFI, SAFI to internal values, check. */
1846 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1847 /* Log if AFI or SAFI is unrecognized. This is not an error
1849 * the attribute is otherwise malformed.
1851 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1853 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
1854 peer
->host
, iana_afi2str(pkt_afi
),
1855 iana_safi2str(pkt_safi
));
1856 return BGP_ATTR_PARSE_ERROR
;
1859 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1861 mp_withdraw
->afi
= afi
;
1862 mp_withdraw
->safi
= safi
;
1863 mp_withdraw
->nlri
= stream_pnt(s
);
1864 mp_withdraw
->length
= withdraw_len
;
1866 stream_forward_getp(s
, withdraw_len
);
1868 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
1870 return BGP_ATTR_PARSE_PROCEED
;
1873 /* Large Community attribute. */
1874 static bgp_attr_parse_ret_t
1875 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
1877 struct peer
*const peer
= args
->peer
;
1878 struct attr
*const attr
= args
->attr
;
1879 const bgp_size_t length
= args
->length
;
1882 * Large community follows new attribute format.
1885 attr
->lcommunity
= NULL
;
1886 /* Empty extcomm doesn't seem to be invalid per se */
1887 return BGP_ATTR_PARSE_PROCEED
;
1891 lcommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1892 /* XXX: fix ecommunity_parse to use stream API */
1893 stream_forward_getp(peer
->curr
, length
);
1895 if (!attr
->lcommunity
)
1896 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1899 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1901 return BGP_ATTR_PARSE_PROCEED
;
1904 /* Extended Community attribute. */
1905 static bgp_attr_parse_ret_t
1906 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
1908 struct peer
*const peer
= args
->peer
;
1909 struct attr
*const attr
= args
->attr
;
1910 const bgp_size_t length
= args
->length
;
1914 attr
->ecommunity
= NULL
;
1915 /* Empty extcomm doesn't seem to be invalid per se */
1916 return BGP_ATTR_PARSE_PROCEED
;
1920 ecommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1921 /* XXX: fix ecommunity_parse to use stream API */
1922 stream_forward_getp(peer
->curr
, length
);
1924 if (!attr
->ecommunity
)
1925 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1928 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1930 /* Extract MAC mobility sequence number, if any. */
1931 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
1932 attr
->sticky
= sticky
;
1934 /* Check if this is a Gateway MAC-IP advertisement */
1935 attr
->default_gw
= bgp_attr_default_gw(attr
);
1937 /* Handle scenario where router flag ecommunity is not
1938 * set but default gw ext community is present.
1939 * Use default gateway, set and propogate R-bit.
1941 if (attr
->default_gw
)
1942 attr
->router_flag
= 1;
1944 /* Check EVPN Neighbor advertisement flags, R-bit */
1945 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
);
1947 /* Extract the Rmac, if any */
1948 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
1949 if (bgp_debug_update(peer
, NULL
, NULL
, 1) &&
1950 bgp_mac_exist(&attr
->rmac
)) {
1951 char buf1
[ETHER_ADDR_STRLEN
];
1953 zlog_debug("%s: router mac %s is self mac",
1955 prefix_mac2str(&attr
->rmac
, buf1
,
1961 /* Get the tunnel type from encap extended community */
1962 bgp_attr_extcom_tunnel_type(attr
,
1963 (bgp_encap_types
*)&attr
->encap_tunneltype
);
1965 return BGP_ATTR_PARSE_PROCEED
;
1968 /* Parse Tunnel Encap attribute in an UPDATE */
1969 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
1970 bgp_size_t length
, /* IN: attr's length field */
1971 struct attr
*attr
, /* IN: caller already allocated */
1972 uint8_t flag
, /* IN: attr's flags field */
1976 uint16_t tunneltype
= 0;
1978 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
1980 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
1981 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
1983 "Tunnel Encap attribute flag isn't optional and transitive %d",
1985 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1986 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
1991 if (BGP_ATTR_ENCAP
== type
) {
1992 /* read outer TLV type and length */
1993 uint16_t tlv_length
;
1997 "Tunnel Encap attribute not long enough to contain outer T,L");
1998 bgp_notify_send_with_data(
1999 peer
, BGP_NOTIFY_UPDATE_ERR
,
2000 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2003 tunneltype
= stream_getw(BGP_INPUT(peer
));
2004 tlv_length
= stream_getw(BGP_INPUT(peer
));
2007 if (tlv_length
!= length
) {
2008 zlog_info("%s: tlv_length(%d) != length(%d)", __func__
,
2009 tlv_length
, length
);
2013 while (length
>= 4) {
2014 uint16_t subtype
= 0;
2015 uint16_t sublength
= 0;
2016 struct bgp_attr_encap_subtlv
*tlv
;
2018 if (BGP_ATTR_ENCAP
== type
) {
2019 subtype
= stream_getc(BGP_INPUT(peer
));
2020 sublength
= stream_getc(BGP_INPUT(peer
));
2024 subtype
= stream_getw(BGP_INPUT(peer
));
2025 sublength
= stream_getw(BGP_INPUT(peer
));
2030 if (sublength
> length
) {
2032 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2034 bgp_notify_send_with_data(
2035 peer
, BGP_NOTIFY_UPDATE_ERR
,
2036 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2040 /* alloc and copy sub-tlv */
2041 /* TBD make sure these are freed when attributes are released */
2042 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2043 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2044 tlv
->type
= subtype
;
2045 tlv
->length
= sublength
;
2046 stream_get(tlv
->value
, peer
->curr
, sublength
);
2047 length
-= sublength
;
2049 /* attach tlv to encap chain */
2050 if (BGP_ATTR_ENCAP
== type
) {
2051 struct bgp_attr_encap_subtlv
*stlv_last
;
2052 for (stlv_last
= attr
->encap_subtlvs
;
2053 stlv_last
&& stlv_last
->next
;
2054 stlv_last
= stlv_last
->next
)
2057 stlv_last
->next
= tlv
;
2059 attr
->encap_subtlvs
= tlv
;
2063 struct bgp_attr_encap_subtlv
*stlv_last
;
2064 for (stlv_last
= attr
->vnc_subtlvs
;
2065 stlv_last
&& stlv_last
->next
;
2066 stlv_last
= stlv_last
->next
)
2069 stlv_last
->next
= tlv
;
2071 attr
->vnc_subtlvs
= tlv
;
2077 if (BGP_ATTR_ENCAP
== type
) {
2078 attr
->encap_tunneltype
= tunneltype
;
2082 /* spurious leftover data */
2084 "Tunnel Encap attribute length is bad: %d leftover octets",
2086 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2087 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2096 * Read an individual SID value returning how much data we have read
2097 * Returns 0 if there was an error that needs to be passed up the stack
2099 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(int32_t type
,
2101 struct bgp_attr_parser_args
*args
,
2102 struct bgp_nlri
*mp_update
)
2104 struct peer
*const peer
= args
->peer
;
2105 struct attr
*const attr
= args
->attr
;
2106 uint32_t label_index
;
2107 struct in6_addr ipv6_sid
;
2109 uint32_t srgb_range
;
2112 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2113 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2116 "Prefix SID label index length is %d instead of %d",
2117 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2118 return bgp_attr_malformed(args
,
2119 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2123 /* Ignore flags and reserved */
2124 stream_getc(peer
->curr
);
2125 stream_getw(peer
->curr
);
2127 /* Fetch the label index and see if it is valid. */
2128 label_index
= stream_getl(peer
->curr
);
2129 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2130 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2133 /* Store label index; subsequently, we'll check on
2135 attr
->label_index
= label_index
;
2138 * Ignore the Label index attribute unless received for
2142 if (!mp_update
->length
2143 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2144 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2147 /* Placeholder code for the IPv6 SID type */
2148 else if (type
== BGP_PREFIX_SID_IPV6
) {
2149 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2150 flog_err(EC_BGP_ATTR_LEN
,
2151 "Prefix SID IPv6 length is %d instead of %d",
2152 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2153 return bgp_attr_malformed(args
,
2154 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2158 /* Ignore reserved */
2159 stream_getc(peer
->curr
);
2160 stream_getw(peer
->curr
);
2162 stream_get(&ipv6_sid
, peer
->curr
, 16);
2165 /* Placeholder code for the Originator SRGB type */
2166 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2168 stream_getw(peer
->curr
);
2172 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2175 "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2176 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2177 return bgp_attr_malformed(
2178 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2182 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2184 for (int i
= 0; i
< srgb_count
; i
++) {
2185 stream_get(&srgb_base
, peer
->curr
, 3);
2186 stream_get(&srgb_range
, peer
->curr
, 3);
2190 return BGP_ATTR_PARSE_PROCEED
;
2193 /* Prefix SID attribute
2194 * draft-ietf-idr-bgp-prefix-sid-05
2196 bgp_attr_parse_ret_t
2197 bgp_attr_prefix_sid(int32_t tlength
, struct bgp_attr_parser_args
*args
,
2198 struct bgp_nlri
*mp_update
)
2200 struct peer
*const peer
= args
->peer
;
2201 struct attr
*const attr
= args
->attr
;
2202 bgp_attr_parse_ret_t ret
;
2204 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2207 int32_t type
, length
;
2209 type
= stream_getc(peer
->curr
);
2210 length
= stream_getw(peer
->curr
);
2212 ret
= bgp_attr_psid_sub(type
, length
, args
, mp_update
);
2214 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2217 * Subtract length + the T and the L
2218 * since length is the Vector portion
2220 tlength
-= length
+ 3;
2225 "Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
2227 return bgp_attr_malformed(args
,
2228 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2233 return BGP_ATTR_PARSE_PROCEED
;
2236 /* PMSI tunnel attribute (RFC 6514)
2237 * Basic validation checks done here.
2239 static bgp_attr_parse_ret_t
2240 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2242 struct peer
*const peer
= args
->peer
;
2243 struct attr
*const attr
= args
->attr
;
2244 const bgp_size_t length
= args
->length
;
2246 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2248 /* Verify that the receiver is expecting "ingress replication" as we
2249 * can only support that.
2251 if (length
< attr_parse_len
) {
2252 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2254 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2257 stream_getc(peer
->curr
); /* Flags */
2258 tnl_type
= stream_getc(peer
->curr
);
2259 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2260 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2261 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2262 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2265 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2267 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2268 "Bad PMSI tunnel attribute length %d for IR",
2270 return bgp_attr_malformed(
2271 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2276 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2277 attr
->pmsi_tnl_type
= tnl_type
;
2278 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2280 /* Forward read pointer of input stream. */
2281 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2283 return BGP_ATTR_PARSE_PROCEED
;
2286 /* BGP unknown attribute treatment. */
2287 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2289 bgp_size_t total
= args
->total
;
2290 struct transit
*transit
;
2291 struct peer
*const peer
= args
->peer
;
2292 struct attr
*const attr
= args
->attr
;
2293 uint8_t *const startp
= args
->startp
;
2294 const uint8_t type
= args
->type
;
2295 const uint8_t flag
= args
->flags
;
2296 const bgp_size_t length
= args
->length
;
2298 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2300 "%s Unknown attribute is received (type %d, length %d)",
2301 peer
->host
, type
, length
);
2303 /* Forward read pointer of input stream. */
2304 stream_forward_getp(peer
->curr
, length
);
2306 /* If any of the mandatory well-known attributes are not recognized,
2307 then the Error Subcode is set to Unrecognized Well-known
2308 Attribute. The Data field contains the unrecognized attribute
2309 (type, length and value). */
2310 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2311 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2315 /* Unrecognized non-transitive optional attributes must be quietly
2316 ignored and not passed along to other BGP peers. */
2317 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2318 return BGP_ATTR_PARSE_PROCEED
;
2320 /* If a path with recognized transitive optional attribute is
2321 accepted and passed along to other BGP peers and the Partial bit
2322 in the Attribute Flags octet is set to 1 by some previous AS, it
2323 is not set back to 0 by the current AS. */
2324 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2326 /* Store transitive attribute to the end of attr->transit. */
2328 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2330 transit
= attr
->transit
;
2333 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2334 transit
->length
+ total
);
2336 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2338 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2339 transit
->length
+= total
;
2341 return BGP_ATTR_PARSE_PROCEED
;
2344 /* Well-known attribute check. */
2345 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2349 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2351 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2352 return BGP_ATTR_PARSE_PROCEED
;
2354 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2355 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2356 are present, it should. Check for any other attribute being present
2359 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2360 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2361 return BGP_ATTR_PARSE_PROCEED
;
2363 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2364 type
= BGP_ATTR_ORIGIN
;
2366 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2367 type
= BGP_ATTR_AS_PATH
;
2369 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2371 * NLRI is empty. We can't easily check NLRI empty here though.
2373 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2374 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2375 type
= BGP_ATTR_NEXT_HOP
;
2377 if (peer
->sort
== BGP_PEER_IBGP
2378 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2379 type
= BGP_ATTR_LOCAL_PREF
;
2382 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2383 "%s Missing well-known attribute %s.", peer
->host
,
2384 lookup_msg(attr_str
, type
, NULL
));
2385 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2386 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2388 return BGP_ATTR_PARSE_ERROR
;
2390 return BGP_ATTR_PARSE_PROCEED
;
2393 /* Read attribute of update packet. This function is called from
2394 bgp_update_receive() in bgp_packet.c. */
2395 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2396 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2397 struct bgp_nlri
*mp_withdraw
)
2399 bgp_attr_parse_ret_t ret
;
2403 uint8_t *startp
, *endp
;
2405 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2406 /* we need the as4_path only until we have synthesized the as_path with
2408 /* same goes for as4_aggregator */
2409 struct aspath
*as4_path
= NULL
;
2410 as_t as4_aggregator
= 0;
2411 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2413 /* Initialize bitmap. */
2414 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2416 /* End pointer of BGP attribute. */
2417 endp
= BGP_INPUT_PNT(peer
) + size
;
2419 /* Get attributes to the end of attribute length. */
2420 while (BGP_INPUT_PNT(peer
) < endp
) {
2421 /* Check remaining length check.*/
2422 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2423 /* XXX warning: long int format, int arg (arg 5) */
2425 EC_BGP_ATTRIBUTE_TOO_SMALL
,
2426 "%s: error BGP attribute length %lu is smaller than min len",
2428 (unsigned long)(endp
2429 - stream_pnt(BGP_INPUT(peer
))));
2431 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2432 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2433 return BGP_ATTR_PARSE_ERROR
;
2436 /* Fetch attribute flag and type. */
2437 startp
= BGP_INPUT_PNT(peer
);
2438 /* "The lower-order four bits of the Attribute Flags octet are
2439 unused. They MUST be zero when sent and MUST be ignored when
2441 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2442 type
= stream_getc(BGP_INPUT(peer
));
2444 /* Check whether Extended-Length applies and is in bounds */
2445 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2446 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2448 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
2449 "%s: Extended length set, but just %lu bytes of attr header",
2451 (unsigned long)(endp
2452 - stream_pnt(BGP_INPUT(peer
))));
2454 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2455 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2456 return BGP_ATTR_PARSE_ERROR
;
2459 /* Check extended attribue length bit. */
2460 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2461 length
= stream_getw(BGP_INPUT(peer
));
2463 length
= stream_getc(BGP_INPUT(peer
));
2465 /* If any attribute appears more than once in the UPDATE
2466 message, then the Error Subcode is set to Malformed Attribute
2469 if (CHECK_BITMAP(seen
, type
)) {
2471 EC_BGP_ATTRIBUTE_REPEATED
,
2472 "%s: error BGP attribute type %d appears twice in a message",
2475 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2476 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2477 return BGP_ATTR_PARSE_ERROR
;
2480 /* Set type to bitmap to check duplicate attribute. `type' is
2481 unsigned char so it never overflow bitmap range. */
2483 SET_BITMAP(seen
, type
);
2485 /* Overflow check. */
2486 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2488 if (attr_endp
> endp
) {
2490 EC_BGP_ATTRIBUTE_TOO_LARGE
,
2491 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2492 peer
->host
, type
, length
, size
, attr_endp
,
2496 * If any recognized attribute has an Attribute
2497 * Length that conflicts with the expected length
2498 * (based on the attribute type code), then the
2499 * Error Subcode MUST be set to Attribute Length
2500 * Error. The Data field MUST contain the erroneous
2501 * attribute (type, length, and value).
2503 * We do not currently have a good way to determine the
2504 * length of the attribute independent of the length
2505 * received in the message. Instead we send the
2506 * minimum between the amount of data we have and the
2507 * amount specified by the attribute length field.
2509 * Instead of directly passing in the packet buffer and
2510 * offset we use the stream_get* functions to read into
2511 * a stack buffer, since they perform bounds checking
2512 * and we are working with untrusted data.
2514 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
2515 memset(ndata
, 0x00, sizeof(ndata
));
2517 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
2518 /* Rewind to end of flag field */
2519 stream_forward_getp(BGP_INPUT(peer
), -(1 + lfl
));
2521 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
2523 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
2525 size_t atl
= attr_endp
- startp
;
2526 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
2527 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
2529 bgp_notify_send_with_data(
2530 peer
, BGP_NOTIFY_UPDATE_ERR
,
2531 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
2534 return BGP_ATTR_PARSE_ERROR
;
2537 struct bgp_attr_parser_args attr_args
= {
2544 .total
= attr_endp
- startp
,
2548 /* If any recognized attribute has Attribute Flags that conflict
2549 with the Attribute Type Code, then the Error Subcode is set
2551 Attribute Flags Error. The Data field contains the erroneous
2552 attribute (type, length and value). */
2553 if (bgp_attr_flag_invalid(&attr_args
)) {
2554 ret
= bgp_attr_malformed(
2555 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2557 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2562 /* OK check attribute and store it's value. */
2564 case BGP_ATTR_ORIGIN
:
2565 ret
= bgp_attr_origin(&attr_args
);
2567 case BGP_ATTR_AS_PATH
:
2568 ret
= bgp_attr_aspath(&attr_args
);
2570 case BGP_ATTR_AS4_PATH
:
2571 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2573 case BGP_ATTR_NEXT_HOP
:
2574 ret
= bgp_attr_nexthop(&attr_args
);
2576 case BGP_ATTR_MULTI_EXIT_DISC
:
2577 ret
= bgp_attr_med(&attr_args
);
2579 case BGP_ATTR_LOCAL_PREF
:
2580 ret
= bgp_attr_local_pref(&attr_args
);
2582 case BGP_ATTR_ATOMIC_AGGREGATE
:
2583 ret
= bgp_attr_atomic(&attr_args
);
2585 case BGP_ATTR_AGGREGATOR
:
2586 ret
= bgp_attr_aggregator(&attr_args
);
2588 case BGP_ATTR_AS4_AGGREGATOR
:
2589 ret
= bgp_attr_as4_aggregator(&attr_args
,
2591 &as4_aggregator_addr
);
2593 case BGP_ATTR_COMMUNITIES
:
2594 ret
= bgp_attr_community(&attr_args
);
2596 case BGP_ATTR_LARGE_COMMUNITIES
:
2597 ret
= bgp_attr_large_community(&attr_args
);
2599 case BGP_ATTR_ORIGINATOR_ID
:
2600 ret
= bgp_attr_originator_id(&attr_args
);
2602 case BGP_ATTR_CLUSTER_LIST
:
2603 ret
= bgp_attr_cluster_list(&attr_args
);
2605 case BGP_ATTR_MP_REACH_NLRI
:
2606 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2608 case BGP_ATTR_MP_UNREACH_NLRI
:
2609 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2611 case BGP_ATTR_EXT_COMMUNITIES
:
2612 ret
= bgp_attr_ext_communities(&attr_args
);
2614 #if ENABLE_BGP_VNC_ATTR
2617 case BGP_ATTR_ENCAP
:
2618 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
2621 case BGP_ATTR_PREFIX_SID
:
2622 ret
= bgp_attr_prefix_sid(length
,
2623 &attr_args
, mp_update
);
2625 case BGP_ATTR_PMSI_TUNNEL
:
2626 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
2629 ret
= bgp_attr_unknown(&attr_args
);
2633 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
2634 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2635 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2636 ret
= BGP_ATTR_PARSE_ERROR
;
2639 if (ret
== BGP_ATTR_PARSE_EOR
) {
2641 aspath_unintern(&as4_path
);
2645 /* If hard error occurred immediately return to the caller. */
2646 if (ret
== BGP_ATTR_PARSE_ERROR
) {
2647 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
2648 "%s: Attribute %s, parse error", peer
->host
,
2649 lookup_msg(attr_str
, type
, NULL
));
2651 aspath_unintern(&as4_path
);
2654 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
2657 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
2658 "%s: Attribute %s, parse error - treating as withdrawal",
2659 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2661 aspath_unintern(&as4_path
);
2665 /* Check the fetched length. */
2666 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
2667 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
2668 "%s: BGP attribute %s, fetch error",
2669 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2670 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2671 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2673 aspath_unintern(&as4_path
);
2674 return BGP_ATTR_PARSE_ERROR
;
2678 /* Check final read pointer is same as end pointer. */
2679 if (BGP_INPUT_PNT(peer
) != endp
) {
2680 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
2681 "%s: BGP attribute %s, length mismatch", peer
->host
,
2682 lookup_msg(attr_str
, type
, NULL
));
2683 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2684 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2686 aspath_unintern(&as4_path
);
2687 return BGP_ATTR_PARSE_ERROR
;
2691 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
2692 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
2693 * This is implemented below and will result in a NOTIFICATION. If the
2694 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
2695 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
2696 * message SHOULD NOT be sent. This is implemented elsewhere.
2698 * RFC4760: An UPDATE message that carries no NLRI, other than the one
2699 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
2700 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
2701 * speaker that receives the message SHOULD ignore this attribute.
2703 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2704 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
2705 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
2706 return BGP_ATTR_PARSE_ERROR
;
2710 /* Check all mandatory well-known attributes are present */
2711 if ((ret
= bgp_attr_check(peer
, attr
)) < 0) {
2713 aspath_unintern(&as4_path
);
2718 * At this place we can see whether we got AS4_PATH and/or
2719 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2720 * We can not do this before we've read all attributes because
2721 * the as4 handling does not say whether AS4_PATH has to be sent
2722 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2723 * in relationship to AGGREGATOR.
2724 * So, to be defensive, we are not relying on any order and read
2725 * all attributes first, including these 32bit ones, and now,
2726 * afterwards, we look what and if something is to be done for as4.
2728 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2731 /* actually... this doesn't ever return failure currently, but
2732 * better safe than sorry */
2733 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
2734 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
2735 &as4_aggregator_addr
)) {
2736 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2737 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2739 aspath_unintern(&as4_path
);
2740 return BGP_ATTR_PARSE_ERROR
;
2743 /* At this stage, we have done all fiddling with as4, and the
2744 * resulting info is in attr->aggregator resp. attr->aspath
2745 * so we can chuck as4_aggregator and as4_path alltogether in
2746 * order to save memory
2749 aspath_unintern(&as4_path
); /* unintern - it is in the hash */
2750 /* The flag that we got this is still there, but that does not
2755 * The "rest" of the code does nothing with as4_aggregator.
2756 * there is no memory attached specifically which is not part
2758 * so ignoring just means do nothing.
2761 * Finally do the checks on the aspath we did not do yet
2762 * because we waited for a potentially synthesized aspath.
2764 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
2765 ret
= bgp_attr_aspath_check(peer
, attr
);
2766 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2769 /* Finally intern unknown attribute. */
2771 attr
->transit
= transit_intern(attr
->transit
);
2772 if (attr
->encap_subtlvs
)
2773 attr
->encap_subtlvs
=
2774 encap_intern(attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2776 if (attr
->vnc_subtlvs
)
2778 encap_intern(attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2781 return BGP_ATTR_PARSE_PROCEED
;
2785 * Extract the tunnel type from extended community
2787 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
2788 bgp_encap_types
*tunnel_type
)
2790 struct ecommunity
*ecom
;
2795 ecom
= attr
->ecommunity
;
2796 if (!ecom
|| !ecom
->size
)
2799 for (i
= 0; i
< ecom
->size
; i
++) {
2801 uint8_t type
, sub_type
;
2803 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
2806 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
2807 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
2809 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
2816 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
2817 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
2822 iana_safi_t pkt_safi
;
2825 /* Set extended bit always to encode the attribute length as 2 bytes */
2826 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
2827 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2828 sizep
= stream_get_endp(s
);
2829 stream_putw(s
, 0); /* Marker: Attribute length. */
2832 /* Convert AFI, SAFI to values for packet. */
2833 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
2835 stream_putw(s
, pkt_afi
); /* AFI */
2836 stream_putc(s
, pkt_safi
); /* SAFI */
2840 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
2841 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
2843 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
2846 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2851 case SAFI_MULTICAST
:
2852 case SAFI_LABELED_UNICAST
:
2854 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2858 stream_putl(s
, 0); /* RD = 0, per RFC */
2860 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2865 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2868 stream_putc(s
, 0); /* no nexthop for flowspec */
2876 case SAFI_MULTICAST
:
2877 case SAFI_LABELED_UNICAST
:
2879 if (attr
->mp_nexthop_len
2880 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2882 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2883 stream_put(s
, &attr
->mp_nexthop_global
,
2885 stream_put(s
, &attr
->mp_nexthop_local
,
2888 stream_putc(s
, IPV6_MAX_BYTELEN
);
2889 stream_put(s
, &attr
->mp_nexthop_global
,
2893 case SAFI_MPLS_VPN
: {
2894 if (attr
->mp_nexthop_len
2895 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2897 stream_putl(s
, 0); /* RD = 0, per RFC */
2899 stream_put(s
, &attr
->mp_nexthop_global
,
2901 } else if (attr
->mp_nexthop_len
2902 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2904 stream_putl(s
, 0); /* RD = 0, per RFC */
2906 stream_put(s
, &attr
->mp_nexthop_global
,
2908 stream_putl(s
, 0); /* RD = 0, per RFC */
2910 stream_put(s
, &attr
->mp_nexthop_local
,
2915 stream_putc(s
, IPV6_MAX_BYTELEN
);
2916 stream_put(s
, &attr
->mp_nexthop_global
,
2920 stream_putc(s
, 0); /* no nexthop for flowspec */
2926 if (safi
!= SAFI_FLOWSPEC
)
2928 EC_BGP_ATTR_NH_SEND_LEN
,
2929 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
2930 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
2939 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
2940 struct prefix
*p
, struct prefix_rd
*prd
,
2941 mpls_label_t
*label
, uint32_t num_labels
,
2942 int addpath_encode
, uint32_t addpath_tx_id
,
2945 if (safi
== SAFI_MPLS_VPN
) {
2947 stream_putl(s
, addpath_tx_id
);
2948 /* Label, RD, Prefix write. */
2949 stream_putc(s
, p
->prefixlen
+ 88);
2950 stream_put(s
, label
, BGP_LABEL_BYTES
);
2951 stream_put(s
, prd
->val
, 8);
2952 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
2953 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
2954 /* EVPN prefix - contents depend on type */
2955 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
2956 addpath_encode
, addpath_tx_id
);
2957 } else if (safi
== SAFI_LABELED_UNICAST
) {
2958 /* Prefix write with label. */
2959 stream_put_labeled_prefix(s
, p
, label
);
2960 } else if (safi
== SAFI_FLOWSPEC
) {
2961 if (PSIZE (p
->prefixlen
)+2 < FLOWSPEC_NLRI_SIZELIMIT
)
2962 stream_putc(s
, PSIZE (p
->prefixlen
)+2);
2964 stream_putw(s
, (PSIZE (p
->prefixlen
)+2)|(0xf<<12));
2965 stream_putc(s
, 2);/* Filter type */
2966 stream_putc(s
, p
->prefixlen
);/* Prefix length */
2967 stream_put(s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2969 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
2972 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
2974 int size
= PSIZE(p
->prefixlen
);
2975 if (safi
== SAFI_MPLS_VPN
)
2977 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2978 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
2984 * Encodes the tunnel encapsulation attribute,
2985 * and with ENABLE_BGP_VNC the VNC attribute which uses
2986 * almost the same TLV format
2988 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
2989 struct stream
*s
, struct attr
*attr
,
2992 unsigned int attrlenfield
= 0;
2993 unsigned int attrhdrlen
= 0;
2994 struct bgp_attr_encap_subtlv
*subtlvs
;
2995 struct bgp_attr_encap_subtlv
*st
;
2996 const char *attrname
;
2998 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
2999 && (!attr
->encap_tunneltype
3000 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3004 case BGP_ATTR_ENCAP
:
3005 attrname
= "Tunnel Encap";
3006 subtlvs
= attr
->encap_subtlvs
;
3007 if (subtlvs
== NULL
) /* nothing to do */
3010 * The tunnel encap attr has an "outer" tlv.
3012 * L = total length of subtlvs,
3013 * V = concatenated subtlvs.
3015 attrlenfield
= 2 + 2; /* T + L */
3016 attrhdrlen
= 1 + 1; /* subTLV T + L */
3019 #if ENABLE_BGP_VNC_ATTR
3022 subtlvs
= attr
->vnc_subtlvs
;
3023 if (subtlvs
== NULL
) /* nothing to do */
3025 attrlenfield
= 0; /* no outer T + L */
3026 attrhdrlen
= 2 + 2; /* subTLV T + L */
3034 /* compute attr length */
3035 for (st
= subtlvs
; st
; st
= st
->next
) {
3036 attrlenfield
+= (attrhdrlen
+ st
->length
);
3039 if (attrlenfield
> 0xffff) {
3040 zlog_info("%s attribute is too long (length=%d), can't send it",
3041 attrname
, attrlenfield
);
3045 if (attrlenfield
> 0xff) {
3046 /* 2-octet length field */
3048 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3049 | BGP_ATTR_FLAG_EXTLEN
);
3050 stream_putc(s
, attrtype
);
3051 stream_putw(s
, attrlenfield
& 0xffff);
3053 /* 1-octet length field */
3054 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3055 stream_putc(s
, attrtype
);
3056 stream_putc(s
, attrlenfield
& 0xff);
3059 if (attrtype
== BGP_ATTR_ENCAP
) {
3060 /* write outer T+L */
3061 stream_putw(s
, attr
->encap_tunneltype
);
3062 stream_putw(s
, attrlenfield
- 4);
3065 /* write each sub-tlv */
3066 for (st
= subtlvs
; st
; st
= st
->next
) {
3067 if (attrtype
== BGP_ATTR_ENCAP
) {
3068 stream_putc(s
, st
->type
);
3069 stream_putc(s
, st
->length
);
3072 stream_putw(s
, st
->type
);
3073 stream_putw(s
, st
->length
);
3076 stream_put(s
, st
->value
, st
->length
);
3080 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3082 /* Set MP attribute length. Don't count the (2) bytes used to encode
3084 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3087 static int bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3089 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3090 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3091 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3092 PEER_FLAG_REMOVE_PRIVATE_AS
)
3093 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3094 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3095 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3096 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3097 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3098 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3103 /* Make attribute packet. */
3104 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3105 struct stream
*s
, struct attr
*attr
,
3106 struct bpacket_attr_vec_arr
*vecarr
,
3107 struct prefix
*p
, afi_t afi
, safi_t safi
,
3108 struct peer
*from
, struct prefix_rd
*prd
,
3109 mpls_label_t
*label
, uint32_t num_labels
,
3110 int addpath_encode
, uint32_t addpath_tx_id
)
3113 size_t aspath_sizep
;
3114 struct aspath
*aspath
;
3115 int send_as4_path
= 0;
3116 int send_as4_aggregator
= 0;
3117 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3122 /* Remember current pointer. */
3123 cp
= stream_get_endp(s
);
3126 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3127 && !peer_cap_enhe(peer
, afi
, safi
))) {
3128 size_t mpattrlen_pos
= 0;
3130 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3132 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3133 num_labels
, addpath_encode
,
3134 addpath_tx_id
, attr
);
3135 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3138 /* Origin attribute. */
3139 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3140 stream_putc(s
, BGP_ATTR_ORIGIN
);
3142 stream_putc(s
, attr
->origin
);
3144 /* AS path attribute. */
3146 /* If remote-peer is EBGP */
3147 if (peer
->sort
== BGP_PEER_EBGP
3148 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3149 PEER_FLAG_AS_PATH_UNCHANGED
)
3150 || attr
->aspath
->segments
== NULL
)
3151 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3152 PEER_FLAG_RSERVER_CLIENT
))) {
3153 aspath
= aspath_dup(attr
->aspath
);
3155 /* Even though we may not be configured for confederations we
3157 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3158 aspath
= aspath_delete_confed_seq(aspath
);
3160 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3161 /* Stuff our path CONFED_ID on the front */
3162 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3164 if (peer
->change_local_as
) {
3165 /* If replace-as is specified, we only use the
3166 change_local_as when
3167 advertising routes. */
3168 if (!CHECK_FLAG(peer
->flags
,
3169 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3170 if (bgp_append_local_as(peer
, afi
,
3172 aspath
= aspath_add_seq(
3173 aspath
, peer
->local_as
);
3174 aspath
= aspath_add_seq(aspath
,
3175 peer
->change_local_as
);
3177 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3180 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3181 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3183 aspath
= aspath_dup(attr
->aspath
);
3184 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3186 aspath
= attr
->aspath
;
3188 /* If peer is not AS4 capable, then:
3189 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3190 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3192 * types are in it (i.e. exclude them if they are there)
3193 * AND do this only if there is at least one asnum > 65535 in the
3195 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3197 * all ASnums > 65535 to BGP_AS_TRANS
3200 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3201 stream_putc(s
, BGP_ATTR_AS_PATH
);
3202 aspath_sizep
= stream_get_endp(s
);
3204 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3206 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3209 if (!use32bit
&& aspath_has_as4(aspath
))
3211 1; /* we'll do this later, at the correct place */
3213 /* Nexthop attribute. */
3214 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3215 && !peer_cap_enhe(peer
, afi
, safi
)) {
3216 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3217 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3218 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3219 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3222 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3223 } else if (peer_cap_enhe(from
, afi
, safi
)) {
3225 * Likely this is the case when an IPv4 prefix was
3227 * Extended Next-hop capability and now being advertised
3230 * Setting the mandatory (ipv4) next-hop attribute here
3232 * implicit next-hop self with correct (ipv4 address
3235 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3236 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3237 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3240 stream_put_ipv4(s
, 0);
3244 /* MED attribute. */
3245 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3246 || bgp
->maxmed_active
) {
3247 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3248 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3250 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3254 /* Local preference. */
3255 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3256 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3257 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3259 stream_putl(s
, attr
->local_pref
);
3262 /* Atomic aggregate. */
3263 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3264 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3265 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3270 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3271 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3272 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3273 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3276 /* AS4 capable peer */
3278 stream_putl(s
, attr
->aggregator_as
);
3280 /* 2-byte AS peer */
3283 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3285 if (attr
->aggregator_as
> 65535) {
3286 stream_putw(s
, BGP_AS_TRANS
);
3288 /* we have to send AS4_AGGREGATOR, too.
3289 * we'll do that later in order to send
3290 * attributes in ascending
3293 send_as4_aggregator
= 1;
3295 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3297 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3300 /* Community attribute. */
3301 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3302 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3303 if (attr
->community
->size
* 4 > 255) {
3305 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3306 | BGP_ATTR_FLAG_EXTLEN
);
3307 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3308 stream_putw(s
, attr
->community
->size
* 4);
3311 BGP_ATTR_FLAG_OPTIONAL
3312 | BGP_ATTR_FLAG_TRANS
);
3313 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3314 stream_putc(s
, attr
->community
->size
* 4);
3316 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3320 * Large Community attribute.
3322 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3323 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3324 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3325 if (lcom_length(attr
->lcommunity
) > 255) {
3327 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3328 | BGP_ATTR_FLAG_EXTLEN
);
3329 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3330 stream_putw(s
, lcom_length(attr
->lcommunity
));
3333 BGP_ATTR_FLAG_OPTIONAL
3334 | BGP_ATTR_FLAG_TRANS
);
3335 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3336 stream_putc(s
, lcom_length(attr
->lcommunity
));
3338 stream_put(s
, attr
->lcommunity
->val
,
3339 lcom_length(attr
->lcommunity
));
3342 /* Route Reflector. */
3343 if (peer
->sort
== BGP_PEER_IBGP
&& from
3344 && from
->sort
== BGP_PEER_IBGP
) {
3345 /* Originator ID. */
3346 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3347 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3350 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3351 stream_put_in_addr(s
, &attr
->originator_id
);
3353 stream_put_in_addr(s
, &from
->remote_id
);
3356 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3357 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3359 if (attr
->cluster
) {
3360 stream_putc(s
, attr
->cluster
->length
+ 4);
3361 /* If this peer configuration's parent BGP has
3363 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3364 stream_put_in_addr(s
, &bgp
->cluster_id
);
3366 stream_put_in_addr(s
, &bgp
->router_id
);
3367 stream_put(s
, attr
->cluster
->list
,
3368 attr
->cluster
->length
);
3371 /* If this peer configuration's parent BGP has
3373 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3374 stream_put_in_addr(s
, &bgp
->cluster_id
);
3376 stream_put_in_addr(s
, &bgp
->router_id
);
3380 /* Extended Communities attribute. */
3381 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3382 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3383 if (peer
->sort
== BGP_PEER_IBGP
3384 || peer
->sort
== BGP_PEER_CONFED
) {
3385 if (attr
->ecommunity
->size
* 8 > 255) {
3387 BGP_ATTR_FLAG_OPTIONAL
3388 | BGP_ATTR_FLAG_TRANS
3389 | BGP_ATTR_FLAG_EXTLEN
);
3390 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3391 stream_putw(s
, attr
->ecommunity
->size
* 8);
3394 BGP_ATTR_FLAG_OPTIONAL
3395 | BGP_ATTR_FLAG_TRANS
);
3396 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3397 stream_putc(s
, attr
->ecommunity
->size
* 8);
3399 stream_put(s
, attr
->ecommunity
->val
,
3400 attr
->ecommunity
->size
* 8);
3404 int ecom_tr_size
= 0;
3407 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3408 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3411 if (CHECK_FLAG(tbit
,
3412 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3419 if (ecom_tr_size
* 8 > 255) {
3422 BGP_ATTR_FLAG_OPTIONAL
3423 | BGP_ATTR_FLAG_TRANS
3424 | BGP_ATTR_FLAG_EXTLEN
);
3426 BGP_ATTR_EXT_COMMUNITIES
);
3427 stream_putw(s
, ecom_tr_size
* 8);
3431 BGP_ATTR_FLAG_OPTIONAL
3432 | BGP_ATTR_FLAG_TRANS
);
3434 BGP_ATTR_EXT_COMMUNITIES
);
3435 stream_putc(s
, ecom_tr_size
* 8);
3438 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3439 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3444 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3447 stream_put(s
, pnt
, 8);
3453 /* Label index attribute. */
3454 if (safi
== SAFI_LABELED_UNICAST
) {
3455 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3456 uint32_t label_index
;
3458 label_index
= attr
->label_index
;
3460 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3462 BGP_ATTR_FLAG_OPTIONAL
3463 | BGP_ATTR_FLAG_TRANS
);
3464 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3466 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3468 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3469 stream_putc(s
, 0); // reserved
3470 stream_putw(s
, 0); // flags
3471 stream_putl(s
, label_index
);
3476 if (send_as4_path
) {
3477 /* If the peer is NOT As4 capable, AND */
3478 /* there are ASnums > 65535 in path THEN
3479 * give out AS4_PATH */
3481 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3483 * Hm, I wonder... confederation things *should* only be at
3484 * the beginning of an aspath, right? Then we should use
3485 * aspath_delete_confed_seq for this, because it is already
3487 * Folks, talk to me: what is reasonable here!?
3489 aspath
= aspath_delete_confed_seq(aspath
);
3492 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3493 | BGP_ATTR_FLAG_EXTLEN
);
3494 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3495 aspath_sizep
= stream_get_endp(s
);
3497 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3500 if (aspath
!= attr
->aspath
)
3501 aspath_free(aspath
);
3503 if (send_as4_aggregator
) {
3504 /* send AS4_AGGREGATOR, at this place */
3505 /* this section of code moved here in order to ensure the
3507 * *ascending* order of attributes
3509 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3510 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3512 stream_putl(s
, attr
->aggregator_as
);
3513 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3516 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3517 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3518 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3519 /* Tunnel Encap attribute */
3520 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3522 #if ENABLE_BGP_VNC_ATTR
3524 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3529 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
3530 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3531 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
3532 stream_putc(s
, 9); // Length
3533 stream_putc(s
, 0); // Flags
3534 stream_putc(s
, attr
->pmsi_tnl_type
);
3535 stream_put(s
, &(attr
->label
),
3536 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
3537 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3538 // Unicast tunnel endpoint IP address
3541 /* Unknown transit attribute. */
3543 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
3545 /* Return total size of attribute. */
3546 return stream_get_endp(s
) - cp
;
3549 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3551 unsigned long attrlen_pnt
;
3553 iana_safi_t pkt_safi
;
3555 /* Set extended bit always to encode the attribute length as 2 bytes */
3556 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3557 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3559 attrlen_pnt
= stream_get_endp(s
);
3560 stream_putw(s
, 0); /* Length of this attribute. */
3562 /* Convert AFI, SAFI to values for packet. */
3563 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3565 stream_putw(s
, pkt_afi
);
3566 stream_putc(s
, pkt_safi
);
3571 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
3572 safi_t safi
, struct prefix_rd
*prd
,
3573 mpls_label_t
*label
, uint32_t num_labels
,
3574 int addpath_encode
, uint32_t addpath_tx_id
,
3577 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
3579 if (safi
== SAFI_LABELED_UNICAST
) {
3580 label
= (mpls_label_t
*)wlabel
;
3584 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
3585 addpath_encode
, addpath_tx_id
, attr
);
3588 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
3590 bgp_packet_mpattr_end(s
, attrlen_pnt
);
3593 /* Initialization of attribute. */
3594 void bgp_attr_init(void)
3606 void bgp_attr_finish(void)
3611 ecommunity_finish();
3612 lcommunity_finish();
3618 /* Make attribute packet. */
3619 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
3620 struct prefix
*prefix
)
3625 struct aspath
*aspath
;
3626 int addpath_encode
= 0;
3627 uint32_t addpath_tx_id
= 0;
3629 /* Remember current pointer. */
3630 cp
= stream_get_endp(s
);
3632 /* Place holder of length. */
3635 /* Origin attribute. */
3636 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3637 stream_putc(s
, BGP_ATTR_ORIGIN
);
3639 stream_putc(s
, attr
->origin
);
3641 aspath
= attr
->aspath
;
3643 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3644 stream_putc(s
, BGP_ATTR_AS_PATH
);
3645 aspath_lenp
= stream_get_endp(s
);
3648 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
3650 /* Nexthop attribute. */
3651 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3652 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
3653 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3654 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3656 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3659 /* MED attribute. */
3660 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
3661 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3662 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3664 stream_putl(s
, attr
->med
);
3667 /* Local preference. */
3668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
3669 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3670 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3672 stream_putl(s
, attr
->local_pref
);
3675 /* Atomic aggregate. */
3676 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3677 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3678 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3683 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3684 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3685 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3687 stream_putl(s
, attr
->aggregator_as
);
3688 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3691 /* Community attribute. */
3692 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3693 if (attr
->community
->size
* 4 > 255) {
3695 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3696 | BGP_ATTR_FLAG_EXTLEN
);
3697 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3698 stream_putw(s
, attr
->community
->size
* 4);
3701 BGP_ATTR_FLAG_OPTIONAL
3702 | BGP_ATTR_FLAG_TRANS
);
3703 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3704 stream_putc(s
, attr
->community
->size
* 4);
3706 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3709 /* Large Community attribute. */
3710 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
3711 if (lcom_length(attr
->lcommunity
) > 255) {
3713 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3714 | BGP_ATTR_FLAG_EXTLEN
);
3715 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3716 stream_putw(s
, lcom_length(attr
->lcommunity
));
3719 BGP_ATTR_FLAG_OPTIONAL
3720 | BGP_ATTR_FLAG_TRANS
);
3721 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3722 stream_putc(s
, lcom_length(attr
->lcommunity
));
3725 stream_put(s
, attr
->lcommunity
->val
,
3726 lcom_length(attr
->lcommunity
));
3729 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3730 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
3731 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
3732 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
3735 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3736 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3737 sizep
= stream_get_endp(s
);
3740 stream_putc(s
, 0); /* Marker: Attribute length. */
3741 stream_putw(s
, AFI_IP6
); /* AFI */
3742 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3745 stream_putc(s
, attr
->mp_nexthop_len
);
3746 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3747 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3748 stream_put(s
, &attr
->mp_nexthop_local
,
3755 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
3758 /* Set MP attribute length. */
3759 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
3763 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3764 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3766 BGP_ATTR_FLAG_OPTIONAL
3767 | BGP_ATTR_FLAG_TRANS
);
3768 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3770 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3771 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3772 stream_putc(s
, 0); // reserved
3773 stream_putw(s
, 0); // flags
3774 stream_putl(s
, attr
->label_index
);
3778 /* Return total size of attribute. */
3779 len
= stream_get_endp(s
) - cp
- 2;
3780 stream_putw_at(s
, cp
, len
);