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_label.h"
43 #include "bgpd/bgp_packet.h"
44 #include "bgpd/bgp_ecommunity.h"
45 #include "bgpd/bgp_lcommunity.h"
46 #include "bgpd/bgp_updgrp.h"
47 #include "bgpd/bgp_encap_types.h"
49 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
50 #include "bgp_encap_types.h"
51 #include "bgp_vnc_types.h"
53 #include "bgp_encap_types.h"
55 #include "bgp_flowspec_private.h"
57 /* Attribute strings for logging. */
58 static const struct message attr_str
[] = {
59 {BGP_ATTR_ORIGIN
, "ORIGIN"},
60 {BGP_ATTR_AS_PATH
, "AS_PATH"},
61 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
62 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
63 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
64 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
65 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
66 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
67 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
68 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
69 {BGP_ATTR_DPA
, "DPA"},
70 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
71 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
72 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
73 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
74 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
75 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
76 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
77 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
78 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
79 {BGP_ATTR_ENCAP
, "ENCAP"},
81 {BGP_ATTR_VNC
, "VNC"},
83 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
84 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
87 static const struct message attr_flag_str
[] = {
88 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
89 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
90 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
91 /* bgp_attr_flags_diagnose() relies on this bit being last in
93 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
96 static struct hash
*cluster_hash
;
98 static void *cluster_hash_alloc(void *p
)
100 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
101 struct cluster_list
*cluster
;
103 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
104 cluster
->length
= val
->length
;
106 if (cluster
->length
) {
107 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
108 memcpy(cluster
->list
, val
->list
, val
->length
);
110 cluster
->list
= NULL
;
117 /* Cluster list related functions. */
118 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
120 struct cluster_list tmp
;
121 struct cluster_list
*cluster
;
126 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
131 int cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
135 for (i
= 0; i
< cluster
->length
/ 4; i
++)
136 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
141 static unsigned int cluster_hash_key_make(void *p
)
143 const struct cluster_list
*cluster
= p
;
145 return jhash(cluster
->list
, cluster
->length
, 0);
148 static int cluster_hash_cmp(const void *p1
, const void *p2
)
150 const struct cluster_list
*cluster1
= p1
;
151 const struct cluster_list
*cluster2
= p2
;
153 return (cluster1
->length
== cluster2
->length
154 && memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
)
158 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(struct bgp_attr_encap_subtlv
*h1
,
263 struct bgp_attr_encap_subtlv
*h2
)
265 struct bgp_attr_encap_subtlv
*p
;
266 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(void *p
)
352 const struct bgp_attr_encap_subtlv
*encap
= p
;
354 return jhash(encap
->value
, encap
->length
, 0);
357 static int encap_hash_cmp(const void *p1
, const void *p2
)
359 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
360 (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 overlay_index
));
397 /* Unknown transit attribute. */
398 static struct hash
*transit_hash
;
400 static void transit_free(struct transit
*transit
)
403 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
404 XFREE(MTYPE_TRANSIT
, transit
);
407 static void *transit_hash_alloc(void *p
)
409 /* Transit structure is already allocated. */
413 static struct transit
*transit_intern(struct transit
*transit
)
415 struct transit
*find
;
417 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
419 transit_free(transit
);
425 void transit_unintern(struct transit
*transit
)
430 if (transit
->refcnt
== 0) {
431 hash_release(transit_hash
, transit
);
432 transit_free(transit
);
436 static unsigned int transit_hash_key_make(void *p
)
438 const struct transit
*transit
= p
;
440 return jhash(transit
->val
, transit
->length
, 0);
443 static int transit_hash_cmp(const void *p1
, const void *p2
)
445 const struct transit
*transit1
= p1
;
446 const struct transit
*transit2
= p2
;
448 return (transit1
->length
== transit2
->length
449 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
452 static void transit_init(void)
454 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
458 static void transit_finish(void)
460 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
461 hash_free(transit_hash
);
465 /* Attribute hash routines. */
466 static struct hash
*attrhash
;
468 /* Shallow copy of an attribute
469 * Though, not so shallow that it doesn't copy the contents
470 * of the attr_extra pointed to by 'extra'
472 void bgp_attr_dup(struct attr
*new, struct attr
*orig
)
477 unsigned long int attr_count(void)
479 return attrhash
->count
;
482 unsigned long int attr_unknown_count(void)
484 return transit_hash
->count
;
487 unsigned int attrhash_key_make(void *p
)
489 const struct attr
*attr
= (struct attr
*)p
;
491 #define MIX(val) key = jhash_1word(val, key)
492 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
494 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
495 MIX3(attr
->local_pref
, attr
->aggregator_as
,
496 attr
->aggregator_addr
.s_addr
);
497 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
498 attr
->originator_id
.s_addr
);
499 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
502 MIX(aspath_key_make(attr
->aspath
));
504 MIX(community_hash_make(attr
->community
));
506 if (attr
->lcommunity
)
507 MIX(lcommunity_hash_make(attr
->lcommunity
));
508 if (attr
->ecommunity
)
509 MIX(ecommunity_hash_make(attr
->ecommunity
));
511 MIX(cluster_hash_key_make(attr
->cluster
));
513 MIX(transit_hash_key_make(attr
->transit
));
514 if (attr
->encap_subtlvs
)
515 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
517 if (attr
->vnc_subtlvs
)
518 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
520 MIX(attr
->mp_nexthop_len
);
521 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
522 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
527 int attrhash_cmp(const void *p1
, const void *p2
)
529 const struct attr
*attr1
= p1
;
530 const struct attr
*attr2
= p2
;
532 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
533 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
534 && attr1
->aspath
== attr2
->aspath
535 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
536 && attr1
->local_pref
== attr2
->local_pref
537 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
538 if (attr1
->aggregator_as
== attr2
->aggregator_as
539 && attr1
->aggregator_addr
.s_addr
540 == attr2
->aggregator_addr
.s_addr
541 && attr1
->weight
== attr2
->weight
542 && attr1
->tag
== attr2
->tag
543 && attr1
->label_index
== attr2
->label_index
544 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
545 && attr1
->ecommunity
== attr2
->ecommunity
546 && attr1
->lcommunity
== attr2
->lcommunity
547 && attr1
->cluster
== attr2
->cluster
548 && attr1
->transit
== attr2
->transit
549 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
550 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
552 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
554 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
555 &attr2
->mp_nexthop_global
)
556 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
557 &attr2
->mp_nexthop_local
)
558 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
559 &attr2
->mp_nexthop_global_in
)
560 && IPV4_ADDR_SAME(&attr1
->originator_id
,
561 &attr2
->originator_id
)
562 && overlay_index_same(attr1
, attr2
))
569 static void attrhash_init(void)
572 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
576 * special for hash_clean below
578 static void attr_vfree(void *attr
)
580 XFREE(MTYPE_ATTR
, attr
);
583 static void attrhash_finish(void)
585 hash_clean(attrhash
, attr_vfree
);
590 static void attr_show_all_iterator(struct hash_backet
*backet
, struct vty
*vty
)
592 struct attr
*attr
= backet
->data
;
594 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
595 inet_ntoa(attr
->nexthop
));
598 void attr_show_all(struct vty
*vty
)
600 hash_iterate(attrhash
, (void (*)(struct hash_backet
*,
601 void *))attr_show_all_iterator
,
605 static void *bgp_attr_hash_alloc(void *p
)
607 struct attr
*val
= (struct attr
*)p
;
610 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
612 if (val
->encap_subtlvs
) {
613 val
->encap_subtlvs
= NULL
;
616 if (val
->vnc_subtlvs
) {
617 val
->vnc_subtlvs
= NULL
;
624 /* Internet argument attribute. */
625 struct attr
*bgp_attr_intern(struct attr
*attr
)
629 /* Intern referenced strucutre. */
631 if (!attr
->aspath
->refcnt
)
632 attr
->aspath
= aspath_intern(attr
->aspath
);
634 attr
->aspath
->refcnt
++;
636 if (attr
->community
) {
637 if (!attr
->community
->refcnt
)
638 attr
->community
= community_intern(attr
->community
);
640 attr
->community
->refcnt
++;
643 if (attr
->ecommunity
) {
644 if (!attr
->ecommunity
->refcnt
)
645 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
647 attr
->ecommunity
->refcnt
++;
649 if (attr
->lcommunity
) {
650 if (!attr
->lcommunity
->refcnt
)
651 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
653 attr
->lcommunity
->refcnt
++;
656 if (!attr
->cluster
->refcnt
)
657 attr
->cluster
= cluster_intern(attr
->cluster
);
659 attr
->cluster
->refcnt
++;
662 if (!attr
->transit
->refcnt
)
663 attr
->transit
= transit_intern(attr
->transit
);
665 attr
->transit
->refcnt
++;
667 if (attr
->encap_subtlvs
) {
668 if (!attr
->encap_subtlvs
->refcnt
)
669 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
672 attr
->encap_subtlvs
->refcnt
++;
675 if (attr
->vnc_subtlvs
) {
676 if (!attr
->vnc_subtlvs
->refcnt
)
677 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
680 attr
->vnc_subtlvs
->refcnt
++;
684 /* At this point, attr only contains intern'd pointers. that means
685 * if we find it in attrhash, it has all the same pointers and we
686 * correctly updated the refcounts on these.
687 * If we don't find it, we need to allocate a one because in all
688 * cases this returns a new reference to a hashed attr, but the input
690 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
696 /* Make network statement's attribute. */
697 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
699 memset(attr
, 0, sizeof(struct attr
));
701 attr
->origin
= origin
;
702 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
703 attr
->aspath
= aspath_empty();
704 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
705 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
707 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
708 attr
->label
= MPLS_INVALID_LABEL
;
709 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
710 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
715 /* Create the attributes for an aggregate */
716 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, uint8_t origin
,
717 struct aspath
*aspath
,
718 struct community
*community
, int as_set
,
719 uint8_t atomic_aggregate
)
724 memset(&attr
, 0, sizeof(struct attr
));
726 /* Origin attribute. */
727 attr
.origin
= origin
;
728 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
730 /* AS path attribute. */
732 attr
.aspath
= aspath_intern(aspath
);
734 attr
.aspath
= aspath_empty();
735 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
737 /* Next hop attribute. */
738 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
741 uint32_t gshut
= COMMUNITY_GSHUT
;
743 /* If we are not shutting down ourselves and we are
744 * aggregating a route that contains the GSHUT community we
745 * need to remove that community when creating the aggregate */
746 if (!bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)
747 && community_include(community
, gshut
)) {
748 community_del_val(community
, &gshut
);
751 attr
.community
= community
;
752 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
755 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
756 bgp_attr_add_gshut_community(&attr
);
759 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
760 attr
.label
= MPLS_INVALID_LABEL
;
761 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
762 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
763 if (!as_set
|| atomic_aggregate
)
764 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
765 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
766 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
767 attr
.aggregator_as
= bgp
->confed_id
;
769 attr
.aggregator_as
= bgp
->as
;
770 attr
.aggregator_addr
= bgp
->router_id
;
771 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
772 attr
.label
= MPLS_INVALID_LABEL
;
774 new = bgp_attr_intern(&attr
);
776 aspath_unintern(&new->aspath
);
780 /* Unintern just the sub-components of the attr, but not the attr */
781 void bgp_attr_unintern_sub(struct attr
*attr
)
783 /* aspath refcount shoud be decrement. */
785 aspath_unintern(&attr
->aspath
);
786 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
789 community_unintern(&attr
->community
);
790 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
792 if (attr
->ecommunity
)
793 ecommunity_unintern(&attr
->ecommunity
);
794 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
796 if (attr
->lcommunity
)
797 lcommunity_unintern(&attr
->lcommunity
);
798 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
801 cluster_unintern(attr
->cluster
);
802 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
805 transit_unintern(attr
->transit
);
807 if (attr
->encap_subtlvs
)
808 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
811 if (attr
->vnc_subtlvs
)
812 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
817 * We have some show commands that let you experimentally
818 * apply a route-map. When we apply the route-map
819 * we are reseting values but not saving them for
820 * posterity via intern'ing( because route-maps don't
821 * do that) but at this point in time we need
822 * to compare the new attr to the old and if the
823 * routemap has changed it we need to, as Snoop Dog says,
824 * Drop it like it's hot
826 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
828 if (new->aspath
!= old
->aspath
)
829 aspath_free(new->aspath
);
831 if (new->community
!= old
->community
)
832 community_free(new->community
);
834 if (new->ecommunity
!= old
->ecommunity
)
835 ecommunity_free(&new->ecommunity
);
837 if (new->lcommunity
!= old
->lcommunity
)
838 lcommunity_free(&new->lcommunity
);
841 /* Free bgp attribute and aspath. */
842 void bgp_attr_unintern(struct attr
**pattr
)
844 struct attr
*attr
= *pattr
;
848 /* Decrement attribute reference. */
853 /* If reference becomes zero then free attribute object. */
854 if (attr
->refcnt
== 0) {
855 ret
= hash_release(attrhash
, attr
);
857 XFREE(MTYPE_ATTR
, attr
);
861 bgp_attr_unintern_sub(&tmp
);
864 void bgp_attr_flush(struct attr
*attr
)
866 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
867 aspath_free(attr
->aspath
);
870 if (attr
->community
&& !attr
->community
->refcnt
) {
871 community_free(attr
->community
);
872 attr
->community
= NULL
;
875 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
876 ecommunity_free(&attr
->ecommunity
);
877 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
878 lcommunity_free(&attr
->lcommunity
);
879 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
880 cluster_free(attr
->cluster
);
881 attr
->cluster
= NULL
;
883 if (attr
->transit
&& !attr
->transit
->refcnt
) {
884 transit_free(attr
->transit
);
885 attr
->transit
= NULL
;
887 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
888 encap_free(attr
->encap_subtlvs
);
889 attr
->encap_subtlvs
= NULL
;
892 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
893 encap_free(attr
->vnc_subtlvs
);
894 attr
->vnc_subtlvs
= NULL
;
899 /* Implement draft-scudder-idr-optional-transitive behaviour and
900 * avoid resetting sessions for malformed attributes which are
901 * are partial/optional and hence where the error likely was not
902 * introduced by the sending neighbour.
904 static bgp_attr_parse_ret_t
905 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
908 struct peer
*const peer
= args
->peer
;
909 const uint8_t flags
= args
->flags
;
910 /* startp and length must be special-cased, as whether or not to
911 * send the attribute data with the NOTIFY depends on the error,
912 * the caller therefore signals this with the seperate length argument
914 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
916 /* Only relax error handling for eBGP peers */
917 if (peer
->sort
!= BGP_PEER_EBGP
) {
918 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
919 notify_datap
, length
);
920 return BGP_ATTR_PARSE_ERROR
;
923 /* Adjust the stream getp to the end of the attribute, in case we can
924 * still proceed but the caller hasn't read all the attribute.
926 stream_set_getp(BGP_INPUT(peer
),
927 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
930 switch (args
->type
) {
931 /* where an attribute is relatively inconsequential, e.g. it does not
932 * affect route selection, and can be safely ignored, then any such
933 * attributes which are malformed should just be ignored and the route
934 * processed as normal.
936 case BGP_ATTR_AS4_AGGREGATOR
:
937 case BGP_ATTR_AGGREGATOR
:
938 case BGP_ATTR_ATOMIC_AGGREGATE
:
939 return BGP_ATTR_PARSE_PROCEED
;
941 /* Core attributes, particularly ones which may influence route
942 * selection, should always cause session resets
944 case BGP_ATTR_ORIGIN
:
945 case BGP_ATTR_AS_PATH
:
946 case BGP_ATTR_NEXT_HOP
:
947 case BGP_ATTR_MULTI_EXIT_DISC
:
948 case BGP_ATTR_LOCAL_PREF
:
949 case BGP_ATTR_COMMUNITIES
:
950 case BGP_ATTR_ORIGINATOR_ID
:
951 case BGP_ATTR_CLUSTER_LIST
:
952 case BGP_ATTR_MP_REACH_NLRI
:
953 case BGP_ATTR_MP_UNREACH_NLRI
:
954 case BGP_ATTR_EXT_COMMUNITIES
:
955 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
956 notify_datap
, length
);
957 return BGP_ATTR_PARSE_ERROR
;
960 /* Partial optional attributes that are malformed should not cause
961 * the whole session to be reset. Instead treat it as a withdrawal
962 * of the routes, if possible.
964 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
965 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
966 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
967 return BGP_ATTR_PARSE_WITHDRAW
;
969 /* default to reset */
970 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
973 /* Find out what is wrong with the path attribute flag bits and log the error.
974 "Flag bits" here stand for Optional, Transitive and Partial, but not for
975 Extended Length. Checking O/T/P bits at once implies, that the attribute
976 being diagnosed is defined by RFC as either a "well-known" or an "optional,
977 non-transitive" attribute. */
979 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
980 uint8_t desired_flags
/* how RFC says it must be */
984 uint8_t real_flags
= args
->flags
;
985 const uint8_t attr_code
= args
->type
;
987 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
988 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
989 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
990 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
991 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
992 zlog_err("%s attribute must%s be flagged as \"%s\"",
993 lookup_msg(attr_str
, attr_code
, NULL
),
994 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
997 attr_flag_str
[i
].str
);
1002 "Strange, %s called for attr %s, but no problem found with flags"
1003 " (real flags 0x%x, desired 0x%x)",
1004 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1005 real_flags
, desired_flags
);
1009 /* Required flags for attributes. EXTLEN will be masked off when testing,
1010 * as will PARTIAL for optional+transitive attributes.
1012 const uint8_t attr_flags_values
[] = {
1013 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1014 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1015 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1016 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1017 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1018 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1019 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1020 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1021 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1022 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1023 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1024 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1025 [BGP_ATTR_EXT_COMMUNITIES
] =
1026 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1027 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1028 [BGP_ATTR_AS4_AGGREGATOR
] =
1029 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1030 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1031 [BGP_ATTR_LARGE_COMMUNITIES
] =
1032 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1033 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1035 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1037 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1039 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1040 const uint8_t flags
= args
->flags
;
1041 const uint8_t attr_code
= args
->type
;
1043 /* there may be attributes we don't know about */
1044 if (attr_code
> attr_flags_values_max
)
1046 if (attr_flags_values
[attr_code
] == 0)
1049 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1053 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1054 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1056 "%s well-known attributes must have transitive flag set (%x)",
1057 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1061 /* "For well-known attributes and for optional non-transitive
1063 * the Partial bit MUST be set to 0."
1065 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1066 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1068 "%s well-known attribute "
1069 "must NOT have the partial flag set (%x)",
1070 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1073 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1074 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1076 "%s optional + transitive attribute "
1077 "must NOT have the partial flag set (%x)",
1078 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1083 /* Optional transitive attributes may go through speakers that don't
1084 * reocgnise them and set the Partial bit.
1086 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1087 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1088 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1090 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1093 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1097 /* Get origin attribute of the update message. */
1098 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1100 struct peer
*const peer
= args
->peer
;
1101 struct attr
*const attr
= args
->attr
;
1102 const bgp_size_t length
= args
->length
;
1104 /* If any recognized attribute has Attribute Length that conflicts
1105 with the expected length (based on the attribute type code), then
1106 the Error Subcode is set to Attribute Length Error. The Data
1107 field contains the erroneous attribute (type, length and
1110 zlog_err("Origin attribute length is not one %d", length
);
1111 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1115 /* Fetch origin attribute. */
1116 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1118 /* If the ORIGIN attribute has an undefined value, then the Error
1119 Subcode is set to Invalid Origin Attribute. The Data field
1120 contains the unrecognized attribute (type, length and value). */
1121 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1122 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1123 zlog_err("Origin attribute value is invalid %d", attr
->origin
);
1124 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1128 /* Set oring attribute flag. */
1129 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1134 /* Parse AS path information. This function is wrapper of
1136 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1138 struct attr
*const attr
= args
->attr
;
1139 struct peer
*const peer
= args
->peer
;
1140 const bgp_size_t length
= args
->length
;
1143 * peer with AS4 => will get 4Byte ASnums
1144 * otherwise, will get 16 Bit
1146 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1147 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1149 /* In case of IBGP, length will be zero. */
1150 if (!attr
->aspath
) {
1151 zlog_err("Malformed AS path from %s, length is %d", peer
->host
,
1153 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1157 /* Set aspath attribute flag. */
1158 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1160 return BGP_ATTR_PARSE_PROCEED
;
1163 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1164 struct attr
*const attr
)
1166 /* These checks were part of bgp_attr_aspath, but with
1167 * as4 we should to check aspath things when
1168 * aspath synthesizing with as4_path has already taken place.
1169 * Otherwise we check ASPATH and use the synthesized thing, and that is
1171 * So do the checks later, i.e. here
1173 struct bgp
*bgp
= peer
->bgp
;
1174 struct aspath
*aspath
;
1176 /* Confederation sanity check. */
1177 if ((peer
->sort
== BGP_PEER_CONFED
1178 && !aspath_left_confed_check(attr
->aspath
))
1179 || (peer
->sort
== BGP_PEER_EBGP
1180 && aspath_confed_check(attr
->aspath
))) {
1181 zlog_err("Malformed AS path from %s", peer
->host
);
1182 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1183 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1184 return BGP_ATTR_PARSE_ERROR
;
1187 /* First AS check for EBGP. */
1188 if (bgp
!= NULL
&& bgp_flag_check(bgp
, BGP_FLAG_ENFORCE_FIRST_AS
)) {
1189 if (peer
->sort
== BGP_PEER_EBGP
1190 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1191 zlog_err("%s incorrect first AS (must be %u)",
1192 peer
->host
, peer
->as
);
1193 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1194 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1195 return BGP_ATTR_PARSE_ERROR
;
1199 /* local-as prepend */
1200 if (peer
->change_local_as
1201 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1202 aspath
= aspath_dup(attr
->aspath
);
1203 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1204 aspath_unintern(&attr
->aspath
);
1205 attr
->aspath
= aspath_intern(aspath
);
1208 return BGP_ATTR_PARSE_PROCEED
;
1211 /* Parse AS4 path information. This function is another wrapper of
1213 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1214 struct aspath
**as4_path
)
1216 struct peer
*const peer
= args
->peer
;
1217 struct attr
*const attr
= args
->attr
;
1218 const bgp_size_t length
= args
->length
;
1220 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1222 /* In case of IBGP, length will be zero. */
1224 zlog_err("Malformed AS4 path from %s, length is %d", peer
->host
,
1226 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1230 /* Set aspath attribute flag. */
1231 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1233 return BGP_ATTR_PARSE_PROCEED
;
1236 /* Nexthop attribute. */
1237 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1239 struct peer
*const peer
= args
->peer
;
1240 struct attr
*const attr
= args
->attr
;
1241 const bgp_size_t length
= args
->length
;
1243 in_addr_t nexthop_h
, nexthop_n
;
1245 /* Check nexthop attribute length. */
1247 zlog_err("Nexthop attribute length isn't four [%d]", length
);
1249 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1253 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1254 attribute must result in a NOTIFICATION message (this is implemented
1256 At the same time, semantically incorrect NEXT_HOP is more likely to
1258 logged locally (this is implemented somewhere else). The UPDATE
1260 gets ignored in any of these cases. */
1261 nexthop_n
= stream_get_ipv4(peer
->curr
);
1262 nexthop_h
= ntohl(nexthop_n
);
1263 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1264 || IPV4_CLASS_DE(nexthop_h
))
1267 ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1269 char buf
[INET_ADDRSTRLEN
];
1270 inet_ntop(AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1271 zlog_err("Martian nexthop %s", buf
);
1272 return bgp_attr_malformed(
1273 args
, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
, args
->total
);
1276 attr
->nexthop
.s_addr
= nexthop_n
;
1277 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1279 return BGP_ATTR_PARSE_PROCEED
;
1282 /* MED atrribute. */
1283 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1285 struct peer
*const peer
= args
->peer
;
1286 struct attr
*const attr
= args
->attr
;
1287 const bgp_size_t length
= args
->length
;
1291 zlog_err("MED attribute length isn't four [%d]", length
);
1293 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1297 attr
->med
= stream_getl(peer
->curr
);
1299 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1301 return BGP_ATTR_PARSE_PROCEED
;
1304 /* Local preference attribute. */
1305 static bgp_attr_parse_ret_t
1306 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1308 struct peer
*const peer
= args
->peer
;
1309 struct attr
*const attr
= args
->attr
;
1310 const bgp_size_t length
= args
->length
;
1314 zlog_err("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1315 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1319 /* If it is contained in an UPDATE message that is received from an
1320 external peer, then this attribute MUST be ignored by the
1321 receiving speaker. */
1322 if (peer
->sort
== BGP_PEER_EBGP
) {
1323 stream_forward_getp(peer
->curr
, length
);
1324 return BGP_ATTR_PARSE_PROCEED
;
1327 attr
->local_pref
= stream_getl(peer
->curr
);
1329 /* Set the local-pref flag. */
1330 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1332 return BGP_ATTR_PARSE_PROCEED
;
1335 /* Atomic aggregate. */
1336 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1338 struct attr
*const attr
= args
->attr
;
1339 const bgp_size_t length
= args
->length
;
1343 zlog_err("ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1345 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1349 /* Set atomic aggregate flag. */
1350 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1352 return BGP_ATTR_PARSE_PROCEED
;
1355 /* Aggregator attribute */
1356 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1358 struct peer
*const peer
= args
->peer
;
1359 struct attr
*const attr
= args
->attr
;
1360 const bgp_size_t length
= args
->length
;
1364 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1365 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1368 if (length
!= wantedlen
) {
1369 zlog_err("AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1371 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1375 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1376 attr
->aggregator_as
= stream_getl(peer
->curr
);
1378 attr
->aggregator_as
= stream_getw(peer
->curr
);
1379 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1381 /* Set atomic aggregate flag. */
1382 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1384 return BGP_ATTR_PARSE_PROCEED
;
1387 /* New Aggregator attribute */
1388 static bgp_attr_parse_ret_t
1389 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1390 as_t
*as4_aggregator_as
,
1391 struct in_addr
*as4_aggregator_addr
)
1393 struct peer
*const peer
= args
->peer
;
1394 struct attr
*const attr
= args
->attr
;
1395 const bgp_size_t length
= args
->length
;
1398 zlog_err("New Aggregator length is not 8 [%d]", length
);
1399 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1403 *as4_aggregator_as
= stream_getl(peer
->curr
);
1404 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1406 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1408 return BGP_ATTR_PARSE_PROCEED
;
1411 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1413 static bgp_attr_parse_ret_t
1414 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1415 struct aspath
*as4_path
, as_t as4_aggregator
,
1416 struct in_addr
*as4_aggregator_addr
)
1418 int ignore_as4_path
= 0;
1419 struct aspath
*newpath
;
1421 if (!attr
->aspath
) {
1422 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1424 * checked that all well-known, mandatory attributes were
1427 * Can only be a problem with peer itself - hard error
1429 return BGP_ATTR_PARSE_ERROR
;
1432 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1433 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1435 * It is worth a warning though, because the peer really
1436 * should not send them
1438 if (BGP_DEBUG(as4
, AS4
)) {
1439 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1440 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1441 "AS4 capable peer, yet it sent");
1444 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1445 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1447 "AS4 capable peer, yet it sent");
1450 return BGP_ATTR_PARSE_PROCEED
;
1453 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1454 * because that may override AS4_PATH
1456 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1457 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1459 * if the as_number in aggregator is not AS_TRANS,
1460 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1461 * and the Aggregator shall be taken as
1462 * info on the aggregating node, and the AS_PATH
1463 * shall be taken as the AS_PATH
1465 * the Aggregator shall be ignored and the
1466 * AS4_AGGREGATOR shall be taken as the
1467 * Aggregating node and the AS_PATH is to be
1468 * constructed "as in all other cases"
1470 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1472 if (BGP_DEBUG(as4
, AS4
))
1474 "[AS4] %s BGP not AS4 capable peer"
1475 " send AGGREGATOR != AS_TRANS and"
1476 " AS4_AGGREGATOR, so ignore"
1477 " AS4_AGGREGATOR and AS4_PATH",
1479 ignore_as4_path
= 1;
1481 /* "New_aggregator shall be taken as aggregator"
1483 attr
->aggregator_as
= as4_aggregator
;
1484 attr
->aggregator_addr
.s_addr
=
1485 as4_aggregator_addr
->s_addr
;
1488 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1489 * That is bogus - but reading the conditions
1490 * we have to handle AS4_AGGREGATOR as if it were
1491 * AGGREGATOR in that case
1493 if (BGP_DEBUG(as4
, AS4
))
1495 "[AS4] %s BGP not AS4 capable peer send"
1496 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1497 " it as if AGGREGATOR with AS_TRANS had been there",
1499 attr
->aggregator_as
= as4_aggregator
;
1500 /* sweep it under the carpet and simulate a "good"
1502 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1506 /* need to reconcile NEW_AS_PATH and AS_PATH */
1507 if (!ignore_as4_path
1508 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1509 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1510 aspath_unintern(&attr
->aspath
);
1511 attr
->aspath
= aspath_intern(newpath
);
1513 return BGP_ATTR_PARSE_PROCEED
;
1516 /* Community attribute. */
1517 static bgp_attr_parse_ret_t
1518 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1520 struct peer
*const peer
= args
->peer
;
1521 struct attr
*const attr
= args
->attr
;
1522 const bgp_size_t length
= args
->length
;
1525 attr
->community
= NULL
;
1526 return BGP_ATTR_PARSE_PROCEED
;
1530 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1532 /* XXX: fix community_parse to use stream API and remove this */
1533 stream_forward_getp(peer
->curr
, length
);
1535 if (!attr
->community
)
1536 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1539 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1541 return BGP_ATTR_PARSE_PROCEED
;
1544 /* Originator ID attribute. */
1545 static bgp_attr_parse_ret_t
1546 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1548 struct peer
*const peer
= args
->peer
;
1549 struct attr
*const attr
= args
->attr
;
1550 const bgp_size_t length
= args
->length
;
1554 zlog_err("Bad originator ID length %d", length
);
1556 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1560 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1562 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1564 return BGP_ATTR_PARSE_PROCEED
;
1567 /* Cluster list attribute. */
1568 static bgp_attr_parse_ret_t
1569 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1571 struct peer
*const peer
= args
->peer
;
1572 struct attr
*const attr
= args
->attr
;
1573 const bgp_size_t length
= args
->length
;
1577 zlog_err("Bad cluster list length %d", length
);
1579 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1584 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1586 /* XXX: Fix cluster_parse to use stream API and then remove this */
1587 stream_forward_getp(peer
->curr
, length
);
1589 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1591 return BGP_ATTR_PARSE_PROCEED
;
1594 /* Multiprotocol reachability information parse. */
1595 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1596 struct bgp_nlri
*mp_update
)
1600 iana_safi_t pkt_safi
;
1602 bgp_size_t nlri_len
;
1605 struct peer
*const peer
= args
->peer
;
1606 struct attr
*const attr
= args
->attr
;
1607 const bgp_size_t length
= args
->length
;
1609 /* Set end of packet. */
1610 s
= BGP_INPUT(peer
);
1611 start
= stream_get_getp(s
);
1613 /* safe to read statically sized header? */
1614 #define BGP_MP_REACH_MIN_SIZE 5
1615 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1616 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1617 zlog_info("%s: %s sent invalid length, %lu", __func__
,
1618 peer
->host
, (unsigned long)length
);
1619 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1622 /* Load AFI, SAFI. */
1623 pkt_afi
= stream_getw(s
);
1624 pkt_safi
= stream_getc(s
);
1626 /* Convert AFI, SAFI to internal values, check. */
1627 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1628 /* Log if AFI or SAFI is unrecognized. This is not an error
1630 * the attribute is otherwise malformed.
1632 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1634 "%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1635 peer
->host
, pkt_afi
, pkt_safi
);
1636 return BGP_ATTR_PARSE_ERROR
;
1639 /* Get nexthop length. */
1640 attr
->mp_nexthop_len
= stream_getc(s
);
1642 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1644 "%s: %s, MP nexthop length, %u, goes past end of attribute",
1645 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1646 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1649 /* Nexthop length check. */
1650 switch (attr
->mp_nexthop_len
) {
1652 if (safi
!= SAFI_FLOWSPEC
) {
1653 zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
1654 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1655 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1658 case BGP_ATTR_NHLEN_VPNV4
:
1659 stream_getl(s
); /* RD high */
1660 stream_getl(s
); /* RD low */
1662 * NOTE: intentional fall through
1663 * - for consistency in rx processing
1665 * The following comment is to signal GCC this intention
1666 * and supress the warning
1669 case BGP_ATTR_NHLEN_IPV4
:
1670 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1671 /* Probably needed for RFC 2283 */
1672 if (attr
->nexthop
.s_addr
== 0)
1673 memcpy(&attr
->nexthop
.s_addr
,
1674 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1676 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1677 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1678 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1679 stream_getl(s
); /* RD high */
1680 stream_getl(s
); /* RD low */
1682 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1684 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1685 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1686 if (attr
->mp_nexthop_len
1687 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1688 stream_getl(s
); /* RD high */
1689 stream_getl(s
); /* RD low */
1691 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1692 if (attr
->mp_nexthop_len
1693 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1694 stream_getl(s
); /* RD high */
1695 stream_getl(s
); /* RD low */
1697 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1698 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1699 char buf1
[INET6_ADDRSTRLEN
];
1700 char buf2
[INET6_ADDRSTRLEN
];
1702 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1704 "%s rcvd nexthops %s, %s -- ignoring non-LL value",
1707 &attr
->mp_nexthop_global
,
1708 buf1
, INET6_ADDRSTRLEN
),
1710 &attr
->mp_nexthop_local
, buf2
,
1713 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1717 zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
1718 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1719 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1723 zlog_info("%s: (%s) Failed to read SNPA and NLRI(s)", __func__
,
1725 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1730 if ((val
= stream_getc(s
)))
1732 "%s sent non-zero value, %u, for defunct SNPA-length field",
1736 /* must have nrli_len, what is left of the attribute */
1737 nlri_len
= LEN_LEFT
;
1738 if (nlri_len
> STREAM_READABLE(s
)) {
1739 zlog_info("%s: (%s) Failed to read NLRI", __func__
, peer
->host
);
1740 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1744 zlog_info("%s: (%s) No Reachability, Treating as a EOR marker",
1745 __func__
, peer
->host
);
1747 mp_update
->afi
= afi
;
1748 mp_update
->safi
= safi
;
1749 return BGP_ATTR_PARSE_EOR
;
1752 mp_update
->afi
= afi
;
1753 mp_update
->safi
= safi
;
1754 mp_update
->nlri
= stream_pnt(s
);
1755 mp_update
->length
= nlri_len
;
1757 stream_forward_getp(s
, nlri_len
);
1759 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
1761 return BGP_ATTR_PARSE_PROCEED
;
1765 /* Multiprotocol unreachable parse */
1766 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
1767 struct bgp_nlri
*mp_withdraw
)
1772 iana_safi_t pkt_safi
;
1774 uint16_t withdraw_len
;
1775 struct peer
*const peer
= args
->peer
;
1776 struct attr
*const attr
= args
->attr
;
1777 const bgp_size_t length
= args
->length
;
1781 #define BGP_MP_UNREACH_MIN_SIZE 3
1782 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1783 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1785 pkt_afi
= stream_getw(s
);
1786 pkt_safi
= stream_getc(s
);
1788 /* Convert AFI, SAFI to internal values, check. */
1789 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1790 /* Log if AFI or SAFI is unrecognized. This is not an error
1792 * the attribute is otherwise malformed.
1794 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1796 "%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
1797 peer
->host
, pkt_afi
, pkt_safi
);
1798 return BGP_ATTR_PARSE_ERROR
;
1801 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1803 mp_withdraw
->afi
= afi
;
1804 mp_withdraw
->safi
= safi
;
1805 mp_withdraw
->nlri
= stream_pnt(s
);
1806 mp_withdraw
->length
= withdraw_len
;
1808 stream_forward_getp(s
, withdraw_len
);
1810 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
1812 return BGP_ATTR_PARSE_PROCEED
;
1815 /* Large Community attribute. */
1816 static bgp_attr_parse_ret_t
1817 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
1819 struct peer
*const peer
= args
->peer
;
1820 struct attr
*const attr
= args
->attr
;
1821 const bgp_size_t length
= args
->length
;
1824 * Large community follows new attribute format.
1827 attr
->lcommunity
= NULL
;
1828 /* Empty extcomm doesn't seem to be invalid per se */
1829 return BGP_ATTR_PARSE_PROCEED
;
1833 lcommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1834 /* XXX: fix ecommunity_parse to use stream API */
1835 stream_forward_getp(peer
->curr
, length
);
1837 if (!attr
->lcommunity
)
1838 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1841 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1843 return BGP_ATTR_PARSE_PROCEED
;
1846 /* Extended Community attribute. */
1847 static bgp_attr_parse_ret_t
1848 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
1850 struct peer
*const peer
= args
->peer
;
1851 struct attr
*const attr
= args
->attr
;
1852 const bgp_size_t length
= args
->length
;
1856 attr
->ecommunity
= NULL
;
1857 /* Empty extcomm doesn't seem to be invalid per se */
1858 return BGP_ATTR_PARSE_PROCEED
;
1862 ecommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1863 /* XXX: fix ecommunity_parse to use stream API */
1864 stream_forward_getp(peer
->curr
, length
);
1866 if (!attr
->ecommunity
)
1867 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1870 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1872 /* Extract MAC mobility sequence number, if any. */
1873 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
1874 attr
->sticky
= sticky
;
1876 /* Check if this is a Gateway MAC-IP advertisement */
1877 attr
->default_gw
= bgp_attr_default_gw(attr
);
1879 /* Extract the Rmac, if any */
1880 bgp_attr_rmac(attr
, &attr
->rmac
);
1882 return BGP_ATTR_PARSE_PROCEED
;
1885 /* Parse Tunnel Encap attribute in an UPDATE */
1886 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
1887 bgp_size_t length
, /* IN: attr's length field */
1888 struct attr
*attr
, /* IN: caller already allocated */
1889 uint8_t flag
, /* IN: attr's flags field */
1893 uint16_t tunneltype
= 0;
1895 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
1897 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
1898 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
1900 "Tunnel Encap attribute flag isn't optional and transitive %d",
1902 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1903 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
1908 if (BGP_ATTR_ENCAP
== type
) {
1909 /* read outer TLV type and length */
1910 uint16_t tlv_length
;
1914 "Tunnel Encap attribute not long enough to contain outer T,L");
1915 bgp_notify_send_with_data(
1916 peer
, BGP_NOTIFY_UPDATE_ERR
,
1917 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
1920 tunneltype
= stream_getw(BGP_INPUT(peer
));
1921 tlv_length
= stream_getw(BGP_INPUT(peer
));
1924 if (tlv_length
!= length
) {
1925 zlog_info("%s: tlv_length(%d) != length(%d)", __func__
,
1926 tlv_length
, length
);
1930 while (length
>= 4) {
1931 uint16_t subtype
= 0;
1932 uint16_t sublength
= 0;
1933 struct bgp_attr_encap_subtlv
*tlv
;
1935 if (BGP_ATTR_ENCAP
== type
) {
1936 subtype
= stream_getc(BGP_INPUT(peer
));
1937 sublength
= stream_getc(BGP_INPUT(peer
));
1941 subtype
= stream_getw(BGP_INPUT(peer
));
1942 sublength
= stream_getw(BGP_INPUT(peer
));
1947 if (sublength
> length
) {
1949 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1951 bgp_notify_send_with_data(
1952 peer
, BGP_NOTIFY_UPDATE_ERR
,
1953 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
1957 /* alloc and copy sub-tlv */
1958 /* TBD make sure these are freed when attributes are released */
1959 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
1960 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
1961 tlv
->type
= subtype
;
1962 tlv
->length
= sublength
;
1963 stream_get(tlv
->value
, peer
->curr
, sublength
);
1964 length
-= sublength
;
1966 /* attach tlv to encap chain */
1967 if (BGP_ATTR_ENCAP
== type
) {
1968 struct bgp_attr_encap_subtlv
*stlv_last
;
1969 for (stlv_last
= attr
->encap_subtlvs
;
1970 stlv_last
&& stlv_last
->next
;
1971 stlv_last
= stlv_last
->next
)
1974 stlv_last
->next
= tlv
;
1976 attr
->encap_subtlvs
= tlv
;
1980 struct bgp_attr_encap_subtlv
*stlv_last
;
1981 for (stlv_last
= attr
->vnc_subtlvs
;
1982 stlv_last
&& stlv_last
->next
;
1983 stlv_last
= stlv_last
->next
)
1986 stlv_last
->next
= tlv
;
1988 attr
->vnc_subtlvs
= tlv
;
1994 if (BGP_ATTR_ENCAP
== type
) {
1995 attr
->encap_tunneltype
= tunneltype
;
1999 /* spurious leftover data */
2001 "Tunnel Encap attribute length is bad: %d leftover octets",
2003 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2004 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2012 /* Prefix SID attribute
2013 * draft-ietf-idr-bgp-prefix-sid-05
2015 static bgp_attr_parse_ret_t
2016 bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
,
2017 struct bgp_nlri
*mp_update
)
2019 struct peer
*const peer
= args
->peer
;
2020 struct attr
*const attr
= args
->attr
;
2023 uint32_t label_index
;
2024 struct in6_addr ipv6_sid
;
2026 uint32_t srgb_range
;
2029 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2031 type
= stream_getc(peer
->curr
);
2032 length
= stream_getw(peer
->curr
);
2034 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2035 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2037 "Prefix SID label index length is %d instead of %d",
2038 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2039 return bgp_attr_malformed(
2040 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2044 /* Ignore flags and reserved */
2045 stream_getc(peer
->curr
);
2046 stream_getw(peer
->curr
);
2048 /* Fetch the label index and see if it is valid. */
2049 label_index
= stream_getl(peer
->curr
);
2050 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2051 return bgp_attr_malformed(
2052 args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2055 /* Store label index; subsequently, we'll check on
2057 attr
->label_index
= label_index
;
2060 * Ignore the Label index attribute unless received for
2064 if (!mp_update
->length
2065 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2066 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2069 /* Placeholder code for the IPv6 SID type */
2070 else if (type
== BGP_PREFIX_SID_IPV6
) {
2071 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2072 zlog_err("Prefix SID IPv6 length is %d instead of %d",
2073 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2074 return bgp_attr_malformed(
2075 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2079 /* Ignore reserved */
2080 stream_getc(peer
->curr
);
2081 stream_getw(peer
->curr
);
2083 stream_get(&ipv6_sid
, peer
->curr
, 16);
2086 /* Placeholder code for the Originator SRGB type */
2087 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2089 stream_getw(peer
->curr
);
2093 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2095 "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2096 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2097 return bgp_attr_malformed(
2098 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2102 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2104 for (int i
= 0; i
< srgb_count
; i
++) {
2105 stream_get(&srgb_base
, peer
->curr
, 3);
2106 stream_get(&srgb_range
, peer
->curr
, 3);
2110 return BGP_ATTR_PARSE_PROCEED
;
2113 /* PMSI tunnel attribute (RFC 6514)
2114 * Basic validation checks done here.
2116 static bgp_attr_parse_ret_t
2117 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2119 struct peer
*const peer
= args
->peer
;
2120 struct attr
*const attr
= args
->attr
;
2121 const bgp_size_t length
= args
->length
;
2124 /* Verify that the receiver is expecting "ingress replication" as we
2125 * can only support that.
2128 zlog_err("Bad PMSI tunnel attribute length %d", length
);
2129 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2132 stream_getc(peer
->curr
); /* Flags */
2133 tnl_type
= stream_getc(peer
->curr
);
2134 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2135 zlog_err("Invalid PMSI tunnel attribute type %d", tnl_type
);
2136 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2139 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2141 zlog_err("Bad PMSI tunnel attribute length %d for IR",
2143 return bgp_attr_malformed(
2144 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2149 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2150 attr
->pmsi_tnl_type
= tnl_type
;
2152 /* Forward read pointer of input stream. */
2153 stream_forward_getp(peer
->curr
, length
- 2);
2155 return BGP_ATTR_PARSE_PROCEED
;
2158 /* BGP unknown attribute treatment. */
2159 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2161 bgp_size_t total
= args
->total
;
2162 struct transit
*transit
;
2163 struct peer
*const peer
= args
->peer
;
2164 struct attr
*const attr
= args
->attr
;
2165 uint8_t *const startp
= args
->startp
;
2166 const uint8_t type
= args
->type
;
2167 const uint8_t flag
= args
->flags
;
2168 const bgp_size_t length
= args
->length
;
2170 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2172 "%s Unknown attribute is received (type %d, length %d)",
2173 peer
->host
, type
, length
);
2175 /* Forward read pointer of input stream. */
2176 stream_forward_getp(peer
->curr
, length
);
2178 /* If any of the mandatory well-known attributes are not recognized,
2179 then the Error Subcode is set to Unrecognized Well-known
2180 Attribute. The Data field contains the unrecognized attribute
2181 (type, length and value). */
2182 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2183 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2187 /* Unrecognized non-transitive optional attributes must be quietly
2188 ignored and not passed along to other BGP peers. */
2189 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2190 return BGP_ATTR_PARSE_PROCEED
;
2192 /* If a path with recognized transitive optional attribute is
2193 accepted and passed along to other BGP peers and the Partial bit
2194 in the Attribute Flags octet is set to 1 by some previous AS, it
2195 is not set back to 0 by the current AS. */
2196 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2198 /* Store transitive attribute to the end of attr->transit. */
2200 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2202 transit
= attr
->transit
;
2205 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2206 transit
->length
+ total
);
2208 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2210 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2211 transit
->length
+= total
;
2213 return BGP_ATTR_PARSE_PROCEED
;
2216 /* Well-known attribute check. */
2217 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2221 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2223 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2224 return BGP_ATTR_PARSE_PROCEED
;
2226 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2227 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2228 are present, it should. Check for any other attribute being present
2231 if (attr
->flag
== ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))
2232 return BGP_ATTR_PARSE_PROCEED
;
2234 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2235 type
= BGP_ATTR_ORIGIN
;
2237 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2238 type
= BGP_ATTR_AS_PATH
;
2240 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2242 * NLRI is empty. We can't easily check NLRI empty here though.
2244 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2245 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2246 type
= BGP_ATTR_NEXT_HOP
;
2248 if (peer
->sort
== BGP_PEER_IBGP
2249 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2250 type
= BGP_ATTR_LOCAL_PREF
;
2253 zlog_warn("%s Missing well-known attribute %s.", peer
->host
,
2254 lookup_msg(attr_str
, type
, NULL
));
2255 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2256 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2258 return BGP_ATTR_PARSE_ERROR
;
2260 return BGP_ATTR_PARSE_PROCEED
;
2263 /* Read attribute of update packet. This function is called from
2264 bgp_update_receive() in bgp_packet.c. */
2265 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2266 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2267 struct bgp_nlri
*mp_withdraw
)
2273 uint8_t *startp
, *endp
;
2275 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2276 /* we need the as4_path only until we have synthesized the as_path with
2278 /* same goes for as4_aggregator */
2279 struct aspath
*as4_path
= NULL
;
2280 as_t as4_aggregator
= 0;
2281 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2283 /* Initialize bitmap. */
2284 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2286 /* End pointer of BGP attribute. */
2287 endp
= BGP_INPUT_PNT(peer
) + size
;
2289 /* Get attributes to the end of attribute length. */
2290 while (BGP_INPUT_PNT(peer
) < endp
) {
2291 /* Check remaining length check.*/
2292 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2293 /* XXX warning: long int format, int arg (arg 5) */
2295 "%s: error BGP attribute length %lu is smaller than min len",
2297 (unsigned long)(endp
2298 - stream_pnt(BGP_INPUT(peer
))));
2300 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2301 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2302 return BGP_ATTR_PARSE_ERROR
;
2305 /* Fetch attribute flag and type. */
2306 startp
= BGP_INPUT_PNT(peer
);
2307 /* "The lower-order four bits of the Attribute Flags octet are
2308 unused. They MUST be zero when sent and MUST be ignored when
2310 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2311 type
= stream_getc(BGP_INPUT(peer
));
2313 /* Check whether Extended-Length applies and is in bounds */
2314 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2315 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2317 "%s: Extended length set, but just %lu bytes of attr header",
2319 (unsigned long)(endp
2320 - stream_pnt(BGP_INPUT(peer
))));
2322 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2323 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2324 return BGP_ATTR_PARSE_ERROR
;
2327 /* Check extended attribue length bit. */
2328 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2329 length
= stream_getw(BGP_INPUT(peer
));
2331 length
= stream_getc(BGP_INPUT(peer
));
2333 /* If any attribute appears more than once in the UPDATE
2334 message, then the Error Subcode is set to Malformed Attribute
2337 if (CHECK_BITMAP(seen
, type
)) {
2339 "%s: error BGP attribute type %d appears twice in a message",
2342 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2343 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2344 return BGP_ATTR_PARSE_ERROR
;
2347 /* Set type to bitmap to check duplicate attribute. `type' is
2348 unsigned char so it never overflow bitmap range. */
2350 SET_BITMAP(seen
, type
);
2352 /* Overflow check. */
2353 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2355 if (attr_endp
> endp
) {
2357 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2358 peer
->host
, type
, length
, size
, attr_endp
,
2362 * If any recognized attribute has an Attribute
2363 * Length that conflicts with the expected length
2364 * (based on the attribute type code), then the
2365 * Error Subcode MUST be set to Attribute Length
2366 * Error. The Data field MUST contain the erroneous
2367 * attribute (type, length, and value).
2369 * We do not currently have a good way to determine the
2370 * length of the attribute independent of the length
2371 * received in the message. Instead we send the
2372 * minimum between the amount of data we have and the
2373 * amount specified by the attribute length field.
2375 * Instead of directly passing in the packet buffer and
2376 * offset we use the stream_get* functions to read into
2377 * a stack buffer, since they perform bounds checking
2378 * and we are working with untrusted data.
2380 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
2381 memset(ndata
, 0x00, sizeof(ndata
));
2383 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
2384 /* Rewind to end of flag field */
2385 stream_forward_getp(BGP_INPUT(peer
), -(1 + lfl
));
2387 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
2389 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
2391 size_t atl
= attr_endp
- startp
;
2392 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
2393 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
2395 bgp_notify_send_with_data(
2396 peer
, BGP_NOTIFY_UPDATE_ERR
,
2397 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
2400 return BGP_ATTR_PARSE_ERROR
;
2403 struct bgp_attr_parser_args attr_args
= {
2410 .total
= attr_endp
- startp
,
2414 /* If any recognized attribute has Attribute Flags that conflict
2415 with the Attribute Type Code, then the Error Subcode is set
2417 Attribute Flags Error. The Data field contains the erroneous
2418 attribute (type, length and value). */
2419 if (bgp_attr_flag_invalid(&attr_args
)) {
2420 bgp_attr_parse_ret_t ret
;
2421 ret
= bgp_attr_malformed(
2422 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2424 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2429 /* OK check attribute and store it's value. */
2431 case BGP_ATTR_ORIGIN
:
2432 ret
= bgp_attr_origin(&attr_args
);
2434 case BGP_ATTR_AS_PATH
:
2435 ret
= bgp_attr_aspath(&attr_args
);
2437 case BGP_ATTR_AS4_PATH
:
2438 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2440 case BGP_ATTR_NEXT_HOP
:
2441 ret
= bgp_attr_nexthop(&attr_args
);
2443 case BGP_ATTR_MULTI_EXIT_DISC
:
2444 ret
= bgp_attr_med(&attr_args
);
2446 case BGP_ATTR_LOCAL_PREF
:
2447 ret
= bgp_attr_local_pref(&attr_args
);
2449 case BGP_ATTR_ATOMIC_AGGREGATE
:
2450 ret
= bgp_attr_atomic(&attr_args
);
2452 case BGP_ATTR_AGGREGATOR
:
2453 ret
= bgp_attr_aggregator(&attr_args
);
2455 case BGP_ATTR_AS4_AGGREGATOR
:
2456 ret
= bgp_attr_as4_aggregator(&attr_args
,
2458 &as4_aggregator_addr
);
2460 case BGP_ATTR_COMMUNITIES
:
2461 ret
= bgp_attr_community(&attr_args
);
2463 case BGP_ATTR_LARGE_COMMUNITIES
:
2464 ret
= bgp_attr_large_community(&attr_args
);
2466 case BGP_ATTR_ORIGINATOR_ID
:
2467 ret
= bgp_attr_originator_id(&attr_args
);
2469 case BGP_ATTR_CLUSTER_LIST
:
2470 ret
= bgp_attr_cluster_list(&attr_args
);
2472 case BGP_ATTR_MP_REACH_NLRI
:
2473 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2475 case BGP_ATTR_MP_UNREACH_NLRI
:
2476 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2478 case BGP_ATTR_EXT_COMMUNITIES
:
2479 ret
= bgp_attr_ext_communities(&attr_args
);
2484 case BGP_ATTR_ENCAP
:
2485 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
2488 case BGP_ATTR_PREFIX_SID
:
2489 ret
= bgp_attr_prefix_sid(&attr_args
, mp_update
);
2491 case BGP_ATTR_PMSI_TUNNEL
:
2492 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
2495 ret
= bgp_attr_unknown(&attr_args
);
2499 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
2500 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2501 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2502 ret
= BGP_ATTR_PARSE_ERROR
;
2505 if (ret
== BGP_ATTR_PARSE_EOR
) {
2507 aspath_unintern(&as4_path
);
2511 /* If hard error occured immediately return to the caller. */
2512 if (ret
== BGP_ATTR_PARSE_ERROR
) {
2513 zlog_warn("%s: Attribute %s, parse error", peer
->host
,
2514 lookup_msg(attr_str
, type
, NULL
));
2516 aspath_unintern(&as4_path
);
2519 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
2522 "%s: Attribute %s, parse error - treating as withdrawal",
2523 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2525 aspath_unintern(&as4_path
);
2529 /* Check the fetched length. */
2530 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
2531 zlog_warn("%s: BGP attribute %s, fetch error",
2532 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2533 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2534 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2536 aspath_unintern(&as4_path
);
2537 return BGP_ATTR_PARSE_ERROR
;
2541 /* Check final read pointer is same as end pointer. */
2542 if (BGP_INPUT_PNT(peer
) != endp
) {
2543 zlog_warn("%s: BGP attribute %s, length mismatch", peer
->host
,
2544 lookup_msg(attr_str
, type
, NULL
));
2545 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2546 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2548 aspath_unintern(&as4_path
);
2549 return BGP_ATTR_PARSE_ERROR
;
2552 /* Check all mandatory well-known attributes are present */
2554 bgp_attr_parse_ret_t ret
;
2555 if ((ret
= bgp_attr_check(peer
, attr
)) < 0) {
2557 aspath_unintern(&as4_path
);
2563 * At this place we can see whether we got AS4_PATH and/or
2564 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2565 * We can not do this before we've read all attributes because
2566 * the as4 handling does not say whether AS4_PATH has to be sent
2567 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2568 * in relationship to AGGREGATOR.
2569 * So, to be defensive, we are not relying on any order and read
2570 * all attributes first, including these 32bit ones, and now,
2571 * afterwards, we look what and if something is to be done for as4.
2573 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2576 /* actually... this doesn't ever return failure currently, but
2577 * better safe than sorry */
2578 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
2579 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
2580 &as4_aggregator_addr
)) {
2581 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2582 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2584 aspath_unintern(&as4_path
);
2585 return BGP_ATTR_PARSE_ERROR
;
2588 /* At this stage, we have done all fiddling with as4, and the
2589 * resulting info is in attr->aggregator resp. attr->aspath
2590 * so we can chuck as4_aggregator and as4_path alltogether in
2591 * order to save memory
2594 aspath_unintern(&as4_path
); /* unintern - it is in the hash */
2595 /* The flag that we got this is still there, but that does not
2600 * The "rest" of the code does nothing with as4_aggregator.
2601 * there is no memory attached specifically which is not part
2603 * so ignoring just means do nothing.
2606 * Finally do the checks on the aspath we did not do yet
2607 * because we waited for a potentially synthesized aspath.
2609 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
2610 ret
= bgp_attr_aspath_check(peer
, attr
);
2611 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2614 /* Finally intern unknown attribute. */
2616 attr
->transit
= transit_intern(attr
->transit
);
2617 if (attr
->encap_subtlvs
)
2618 attr
->encap_subtlvs
=
2619 encap_intern(attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2621 if (attr
->vnc_subtlvs
)
2623 encap_intern(attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2626 return BGP_ATTR_PARSE_PROCEED
;
2629 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
2630 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
2635 iana_safi_t pkt_safi
;
2638 /* Set extended bit always to encode the attribute length as 2 bytes */
2639 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
2640 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2641 sizep
= stream_get_endp(s
);
2642 stream_putw(s
, 0); /* Marker: Attribute length. */
2645 /* Convert AFI, SAFI to values for packet. */
2646 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
2648 stream_putw(s
, pkt_afi
); /* AFI */
2649 stream_putc(s
, pkt_safi
); /* SAFI */
2653 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
2654 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
2656 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
2659 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2664 case SAFI_MULTICAST
:
2665 case SAFI_LABELED_UNICAST
:
2667 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2671 stream_putl(s
, 0); /* RD = 0, per RFC */
2673 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2678 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2681 stream_putc(s
, 0); /* no nexthop for flowspec */
2689 case SAFI_MULTICAST
:
2690 case SAFI_LABELED_UNICAST
:
2692 if (attr
->mp_nexthop_len
2693 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2695 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2696 stream_put(s
, &attr
->mp_nexthop_global
,
2698 stream_put(s
, &attr
->mp_nexthop_local
,
2701 stream_putc(s
, IPV6_MAX_BYTELEN
);
2702 stream_put(s
, &attr
->mp_nexthop_global
,
2706 case SAFI_MPLS_VPN
: {
2707 if (attr
->mp_nexthop_len
2708 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2710 stream_putl(s
, 0); /* RD = 0, per RFC */
2712 stream_put(s
, &attr
->mp_nexthop_global
,
2714 } else if (attr
->mp_nexthop_len
2715 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2717 stream_putl(s
, 0); /* RD = 0, per RFC */
2719 stream_put(s
, &attr
->mp_nexthop_global
,
2721 stream_putl(s
, 0); /* RD = 0, per RFC */
2723 stream_put(s
, &attr
->mp_nexthop_local
,
2728 stream_putc(s
, IPV6_MAX_BYTELEN
);
2729 stream_put(s
, &attr
->mp_nexthop_global
,
2733 stream_putc(s
, 0); /* no nexthop for flowspec */
2740 "Bad nexthop when sening to %s, AFI %u SAFI %u nhlen %d",
2741 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
2750 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
2751 struct prefix
*p
, struct prefix_rd
*prd
,
2752 mpls_label_t
*label
, uint32_t num_labels
,
2753 int addpath_encode
, uint32_t addpath_tx_id
,
2756 if (safi
== SAFI_MPLS_VPN
) {
2758 stream_putl(s
, addpath_tx_id
);
2759 /* Label, RD, Prefix write. */
2760 stream_putc(s
, p
->prefixlen
+ 88);
2761 stream_put(s
, label
, BGP_LABEL_BYTES
);
2762 stream_put(s
, prd
->val
, 8);
2763 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
2764 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
2765 /* EVPN prefix - contents depend on type */
2766 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
2767 addpath_encode
, addpath_tx_id
);
2768 } else if (safi
== SAFI_LABELED_UNICAST
) {
2769 /* Prefix write with label. */
2770 stream_put_labeled_prefix(s
, p
, label
);
2771 } else if (safi
== SAFI_FLOWSPEC
) {
2772 if (PSIZE (p
->prefixlen
)+2 < FLOWSPEC_NLRI_SIZELIMIT
)
2773 stream_putc(s
, PSIZE (p
->prefixlen
)+2);
2775 stream_putw(s
, (PSIZE (p
->prefixlen
)+2)|(0xf<<12));
2776 stream_putc(s
, 2);/* Filter type */
2777 stream_putc(s
, p
->prefixlen
);/* Prefix length */
2778 stream_put(s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2780 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
2783 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
2785 int size
= PSIZE(p
->prefixlen
);
2786 if (safi
== SAFI_MPLS_VPN
)
2788 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2789 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
2795 * Encodes the tunnel encapsulation attribute,
2796 * and with ENABLE_BGP_VNC the VNC attribute which uses
2797 * almost the same TLV format
2799 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
2800 struct stream
*s
, struct attr
*attr
,
2803 unsigned int attrlenfield
= 0;
2804 unsigned int attrhdrlen
= 0;
2805 struct bgp_attr_encap_subtlv
*subtlvs
;
2806 struct bgp_attr_encap_subtlv
*st
;
2807 const char *attrname
;
2809 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
2810 && (!attr
->encap_tunneltype
2811 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
2815 case BGP_ATTR_ENCAP
:
2816 attrname
= "Tunnel Encap";
2817 subtlvs
= attr
->encap_subtlvs
;
2818 if (subtlvs
== NULL
) /* nothing to do */
2821 * The tunnel encap attr has an "outer" tlv.
2823 * L = total length of subtlvs,
2824 * V = concatenated subtlvs.
2826 attrlenfield
= 2 + 2; /* T + L */
2827 attrhdrlen
= 1 + 1; /* subTLV T + L */
2833 subtlvs
= attr
->vnc_subtlvs
;
2834 if (subtlvs
== NULL
) /* nothing to do */
2836 attrlenfield
= 0; /* no outer T + L */
2837 attrhdrlen
= 2 + 2; /* subTLV T + L */
2845 /* compute attr length */
2846 for (st
= subtlvs
; st
; st
= st
->next
) {
2847 attrlenfield
+= (attrhdrlen
+ st
->length
);
2850 if (attrlenfield
> 0xffff) {
2851 zlog_info("%s attribute is too long (length=%d), can't send it",
2852 attrname
, attrlenfield
);
2856 if (attrlenfield
> 0xff) {
2857 /* 2-octet length field */
2859 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
2860 | BGP_ATTR_FLAG_EXTLEN
);
2861 stream_putc(s
, attrtype
);
2862 stream_putw(s
, attrlenfield
& 0xffff);
2864 /* 1-octet length field */
2865 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
2866 stream_putc(s
, attrtype
);
2867 stream_putc(s
, attrlenfield
& 0xff);
2870 if (attrtype
== BGP_ATTR_ENCAP
) {
2871 /* write outer T+L */
2872 stream_putw(s
, attr
->encap_tunneltype
);
2873 stream_putw(s
, attrlenfield
- 4);
2876 /* write each sub-tlv */
2877 for (st
= subtlvs
; st
; st
= st
->next
) {
2878 if (attrtype
== BGP_ATTR_ENCAP
) {
2879 stream_putc(s
, st
->type
);
2880 stream_putc(s
, st
->length
);
2883 stream_putw(s
, st
->type
);
2884 stream_putw(s
, st
->length
);
2887 stream_put(s
, st
->value
, st
->length
);
2891 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
2893 /* Set MP attribute length. Don't count the (2) bytes used to encode
2895 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
2898 /* Make attribute packet. */
2899 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
2900 struct stream
*s
, struct attr
*attr
,
2901 struct bpacket_attr_vec_arr
*vecarr
,
2902 struct prefix
*p
, afi_t afi
, safi_t safi
,
2903 struct peer
*from
, struct prefix_rd
*prd
,
2904 mpls_label_t
*label
, uint32_t num_labels
,
2905 int addpath_encode
, uint32_t addpath_tx_id
)
2908 size_t aspath_sizep
;
2909 struct aspath
*aspath
;
2910 int send_as4_path
= 0;
2911 int send_as4_aggregator
= 0;
2912 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2917 /* Remember current pointer. */
2918 cp
= stream_get_endp(s
);
2921 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
2922 && !peer_cap_enhe(peer
, afi
, safi
))) {
2923 size_t mpattrlen_pos
= 0;
2925 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
2927 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
2928 num_labels
, addpath_encode
,
2929 addpath_tx_id
, attr
);
2930 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2933 /* Origin attribute. */
2934 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
2935 stream_putc(s
, BGP_ATTR_ORIGIN
);
2937 stream_putc(s
, attr
->origin
);
2939 /* AS path attribute. */
2941 /* If remote-peer is EBGP */
2942 if (peer
->sort
== BGP_PEER_EBGP
2943 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2944 PEER_FLAG_AS_PATH_UNCHANGED
)
2945 || attr
->aspath
->segments
== NULL
)
2946 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2947 PEER_FLAG_RSERVER_CLIENT
))) {
2948 aspath
= aspath_dup(attr
->aspath
);
2950 /* Even though we may not be configured for confederations we
2952 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2953 aspath
= aspath_delete_confed_seq(aspath
);
2955 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2956 /* Stuff our path CONFED_ID on the front */
2957 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
2959 if (peer
->change_local_as
) {
2960 /* If replace-as is specified, we only use the
2961 change_local_as when
2962 advertising routes. */
2965 PEER_FLAG_LOCAL_AS_REPLACE_AS
)) {
2966 aspath
= aspath_add_seq(aspath
,
2969 aspath
= aspath_add_seq(aspath
,
2970 peer
->change_local_as
);
2972 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
2975 } else if (peer
->sort
== BGP_PEER_CONFED
) {
2976 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
2978 aspath
= aspath_dup(attr
->aspath
);
2979 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
2981 aspath
= attr
->aspath
;
2983 /* If peer is not AS4 capable, then:
2984 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2985 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
2987 * types are in it (i.e. exclude them if they are there)
2988 * AND do this only if there is at least one asnum > 65535 in the
2990 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
2992 * all ASnums > 65535 to BGP_AS_TRANS
2995 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
2996 stream_putc(s
, BGP_ATTR_AS_PATH
);
2997 aspath_sizep
= stream_get_endp(s
);
2999 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3001 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3004 if (!use32bit
&& aspath_has_as4(aspath
))
3006 1; /* we'll do this later, at the correct place */
3008 /* Nexthop attribute. */
3009 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3010 && !peer_cap_enhe(peer
, afi
, safi
)) {
3011 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3012 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3013 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3014 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3017 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3018 } else if (peer_cap_enhe(from
, afi
, safi
)) {
3020 * Likely this is the case when an IPv4 prefix was
3022 * Extended Next-hop capability and now being advertised
3025 * Setting the mandatory (ipv4) next-hop attribute here
3027 * implicit next-hop self with correct (ipv4 address
3030 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3031 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3032 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3035 stream_put_ipv4(s
, 0);
3039 /* MED attribute. */
3040 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3041 || bgp
->maxmed_active
) {
3042 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3043 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3045 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3049 /* Local preference. */
3050 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3051 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3052 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3054 stream_putl(s
, attr
->local_pref
);
3057 /* Atomic aggregate. */
3058 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3059 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3060 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3065 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3066 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3067 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3068 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3071 /* AS4 capable peer */
3073 stream_putl(s
, attr
->aggregator_as
);
3075 /* 2-byte AS peer */
3078 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3080 if (attr
->aggregator_as
> 65535) {
3081 stream_putw(s
, BGP_AS_TRANS
);
3083 /* we have to send AS4_AGGREGATOR, too.
3084 * we'll do that later in order to send
3085 * attributes in ascending
3088 send_as4_aggregator
= 1;
3090 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3092 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3095 /* Community attribute. */
3096 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3097 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3098 if (attr
->community
->size
* 4 > 255) {
3100 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3101 | BGP_ATTR_FLAG_EXTLEN
);
3102 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3103 stream_putw(s
, attr
->community
->size
* 4);
3106 BGP_ATTR_FLAG_OPTIONAL
3107 | BGP_ATTR_FLAG_TRANS
);
3108 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3109 stream_putc(s
, attr
->community
->size
* 4);
3111 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3115 * Large Community attribute.
3117 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3118 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3119 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3120 if (lcom_length(attr
->lcommunity
) > 255) {
3122 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3123 | BGP_ATTR_FLAG_EXTLEN
);
3124 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3125 stream_putw(s
, lcom_length(attr
->lcommunity
));
3128 BGP_ATTR_FLAG_OPTIONAL
3129 | BGP_ATTR_FLAG_TRANS
);
3130 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3131 stream_putc(s
, lcom_length(attr
->lcommunity
));
3133 stream_put(s
, attr
->lcommunity
->val
,
3134 lcom_length(attr
->lcommunity
));
3137 /* Route Reflector. */
3138 if (peer
->sort
== BGP_PEER_IBGP
&& from
3139 && from
->sort
== BGP_PEER_IBGP
) {
3140 /* Originator ID. */
3141 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3142 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3145 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3146 stream_put_in_addr(s
, &attr
->originator_id
);
3148 stream_put_in_addr(s
, &from
->remote_id
);
3151 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3152 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3154 if (attr
->cluster
) {
3155 stream_putc(s
, attr
->cluster
->length
+ 4);
3156 /* If this peer configuration's parent BGP has
3158 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3159 stream_put_in_addr(s
, &bgp
->cluster_id
);
3161 stream_put_in_addr(s
, &bgp
->router_id
);
3162 stream_put(s
, attr
->cluster
->list
,
3163 attr
->cluster
->length
);
3166 /* If this peer configuration's parent BGP has
3168 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3169 stream_put_in_addr(s
, &bgp
->cluster_id
);
3171 stream_put_in_addr(s
, &bgp
->router_id
);
3175 /* Extended Communities attribute. */
3176 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3177 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3178 if (peer
->sort
== BGP_PEER_IBGP
3179 || peer
->sort
== BGP_PEER_CONFED
) {
3180 if (attr
->ecommunity
->size
* 8 > 255) {
3182 BGP_ATTR_FLAG_OPTIONAL
3183 | BGP_ATTR_FLAG_TRANS
3184 | BGP_ATTR_FLAG_EXTLEN
);
3185 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3186 stream_putw(s
, attr
->ecommunity
->size
* 8);
3189 BGP_ATTR_FLAG_OPTIONAL
3190 | BGP_ATTR_FLAG_TRANS
);
3191 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3192 stream_putc(s
, attr
->ecommunity
->size
* 8);
3194 stream_put(s
, attr
->ecommunity
->val
,
3195 attr
->ecommunity
->size
* 8);
3199 int ecom_tr_size
= 0;
3202 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3203 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3206 if (CHECK_FLAG(tbit
,
3207 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3214 if (ecom_tr_size
* 8 > 255) {
3217 BGP_ATTR_FLAG_OPTIONAL
3218 | BGP_ATTR_FLAG_TRANS
3219 | BGP_ATTR_FLAG_EXTLEN
);
3221 BGP_ATTR_EXT_COMMUNITIES
);
3222 stream_putw(s
, ecom_tr_size
* 8);
3226 BGP_ATTR_FLAG_OPTIONAL
3227 | BGP_ATTR_FLAG_TRANS
);
3229 BGP_ATTR_EXT_COMMUNITIES
);
3230 stream_putc(s
, ecom_tr_size
* 8);
3233 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3234 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3239 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3242 stream_put(s
, pnt
, 8);
3248 /* Label index attribute. */
3249 if (safi
== SAFI_LABELED_UNICAST
) {
3250 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3251 uint32_t label_index
;
3253 label_index
= attr
->label_index
;
3255 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3257 BGP_ATTR_FLAG_OPTIONAL
3258 | BGP_ATTR_FLAG_TRANS
);
3259 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3261 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3263 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3264 stream_putc(s
, 0); // reserved
3265 stream_putw(s
, 0); // flags
3266 stream_putl(s
, label_index
);
3271 if (send_as4_path
) {
3272 /* If the peer is NOT As4 capable, AND */
3273 /* there are ASnums > 65535 in path THEN
3274 * give out AS4_PATH */
3276 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3278 * Hm, I wonder... confederation things *should* only be at
3279 * the beginning of an aspath, right? Then we should use
3280 * aspath_delete_confed_seq for this, because it is already
3282 * Folks, talk to me: what is reasonable here!?
3284 aspath
= aspath_delete_confed_seq(aspath
);
3287 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3288 | BGP_ATTR_FLAG_EXTLEN
);
3289 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3290 aspath_sizep
= stream_get_endp(s
);
3292 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3295 if (aspath
!= attr
->aspath
)
3296 aspath_free(aspath
);
3298 if (send_as4_aggregator
) {
3299 /* send AS4_AGGREGATOR, at this place */
3300 /* this section of code moved here in order to ensure the
3302 * *ascending* order of attributes
3304 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3305 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3307 stream_putl(s
, attr
->aggregator_as
);
3308 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3311 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3312 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3313 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3314 /* Tunnel Encap attribute */
3315 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3319 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3324 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
3325 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3326 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
3327 stream_putc(s
, 9); // Length
3328 stream_putc(s
, 0); // Flags
3329 stream_putc(s
, PMSI_TNLTYPE_INGR_REPL
); // IR (6)
3330 stream_put(s
, &(attr
->label
),
3331 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
3332 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3333 // Unicast tunnel endpoint IP address
3336 /* Unknown transit attribute. */
3338 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
3340 /* Return total size of attribute. */
3341 return stream_get_endp(s
) - cp
;
3344 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3346 unsigned long attrlen_pnt
;
3348 iana_safi_t pkt_safi
;
3350 /* Set extended bit always to encode the attribute length as 2 bytes */
3351 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3352 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3354 attrlen_pnt
= stream_get_endp(s
);
3355 stream_putw(s
, 0); /* Length of this attribute. */
3357 /* Convert AFI, SAFI to values for packet. */
3358 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3360 stream_putw(s
, pkt_afi
);
3361 stream_putc(s
, pkt_safi
);
3366 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
3367 safi_t safi
, struct prefix_rd
*prd
,
3368 mpls_label_t
*label
, uint32_t num_labels
,
3369 int addpath_encode
, uint32_t addpath_tx_id
,
3372 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
3374 if (safi
== SAFI_LABELED_UNICAST
) {
3375 label
= (mpls_label_t
*)wlabel
;
3379 return bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
3380 addpath_encode
, addpath_tx_id
, attr
);
3383 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
3385 bgp_packet_mpattr_end(s
, attrlen_pnt
);
3388 /* Initialization of attribute. */
3389 void bgp_attr_init(void)
3401 void bgp_attr_finish(void)
3406 ecommunity_finish();
3407 lcommunity_finish();
3413 /* Make attribute packet. */
3414 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
3415 struct prefix
*prefix
)
3420 struct aspath
*aspath
;
3421 int addpath_encode
= 0;
3422 uint32_t addpath_tx_id
= 0;
3424 /* Remember current pointer. */
3425 cp
= stream_get_endp(s
);
3427 /* Place holder of length. */
3430 /* Origin attribute. */
3431 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3432 stream_putc(s
, BGP_ATTR_ORIGIN
);
3434 stream_putc(s
, attr
->origin
);
3436 aspath
= attr
->aspath
;
3438 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3439 stream_putc(s
, BGP_ATTR_AS_PATH
);
3440 aspath_lenp
= stream_get_endp(s
);
3443 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
3445 /* Nexthop attribute. */
3446 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3447 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
3448 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3449 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3451 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3454 /* MED attribute. */
3455 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
3456 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3457 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3459 stream_putl(s
, attr
->med
);
3462 /* Local preference. */
3463 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
3464 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3465 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3467 stream_putl(s
, attr
->local_pref
);
3470 /* Atomic aggregate. */
3471 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3472 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3473 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3478 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3479 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3480 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3482 stream_putl(s
, attr
->aggregator_as
);
3483 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3486 /* Community attribute. */
3487 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3488 if (attr
->community
->size
* 4 > 255) {
3490 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3491 | BGP_ATTR_FLAG_EXTLEN
);
3492 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3493 stream_putw(s
, attr
->community
->size
* 4);
3496 BGP_ATTR_FLAG_OPTIONAL
3497 | BGP_ATTR_FLAG_TRANS
);
3498 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3499 stream_putc(s
, attr
->community
->size
* 4);
3501 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3504 /* Large Community attribute. */
3505 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
3506 if (lcom_length(attr
->lcommunity
) > 255) {
3508 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3509 | BGP_ATTR_FLAG_EXTLEN
);
3510 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3511 stream_putw(s
, lcom_length(attr
->lcommunity
));
3514 BGP_ATTR_FLAG_OPTIONAL
3515 | BGP_ATTR_FLAG_TRANS
);
3516 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3517 stream_putc(s
, lcom_length(attr
->lcommunity
));
3520 stream_put(s
, attr
->lcommunity
->val
,
3521 lcom_length(attr
->lcommunity
));
3524 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3525 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
3526 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
3527 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
3530 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3531 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3532 sizep
= stream_get_endp(s
);
3535 stream_putc(s
, 0); /* Marker: Attribute length. */
3536 stream_putw(s
, AFI_IP6
); /* AFI */
3537 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3540 stream_putc(s
, attr
->mp_nexthop_len
);
3541 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3542 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3543 stream_put(s
, &attr
->mp_nexthop_local
,
3550 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
3553 /* Set MP attribute length. */
3554 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
3558 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3559 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3561 BGP_ATTR_FLAG_OPTIONAL
3562 | BGP_ATTR_FLAG_TRANS
);
3563 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3565 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3566 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3567 stream_putc(s
, 0); // reserved
3568 stream_putw(s
, 0); // flags
3569 stream_putl(s
, attr
->label_index
);
3573 /* Return total size of attribute. */
3574 len
= stream_get_endp(s
) - cp
- 2;
3575 stream_putw_at(s
, cp
, len
);