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
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_errors.h"
44 #include "bgpd/bgp_label.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_ecommunity.h"
47 #include "bgpd/bgp_lcommunity.h"
48 #include "bgpd/bgp_updgrp.h"
49 #include "bgpd/bgp_encap_types.h"
51 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
52 #include "bgp_encap_types.h"
53 #include "bgp_vnc_types.h"
56 #include "bgp_flowspec_private.h"
59 /* Attribute strings for logging. */
60 static const struct message attr_str
[] = {
61 {BGP_ATTR_ORIGIN
, "ORIGIN"},
62 {BGP_ATTR_AS_PATH
, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
71 {BGP_ATTR_DPA
, "DPA"},
72 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
73 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
74 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
75 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
76 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
77 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
78 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
79 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
80 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
81 {BGP_ATTR_ENCAP
, "ENCAP"},
82 #if ENABLE_BGP_VNC_ATTR
83 {BGP_ATTR_VNC
, "VNC"},
85 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
86 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
89 static const struct message attr_flag_str
[] = {
90 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
91 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
92 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
93 /* bgp_attr_flags_diagnose() relies on this bit being last in
95 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
98 static struct hash
*cluster_hash
;
100 static void *cluster_hash_alloc(void *p
)
102 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
103 struct cluster_list
*cluster
;
105 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
106 cluster
->length
= val
->length
;
108 if (cluster
->length
) {
109 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
110 memcpy(cluster
->list
, val
->list
, val
->length
);
112 cluster
->list
= NULL
;
119 /* Cluster list related functions. */
120 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
122 struct cluster_list tmp
;
123 struct cluster_list
*cluster
;
128 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
133 int cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
137 for (i
= 0; i
< cluster
->length
/ 4; i
++)
138 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
143 static unsigned int cluster_hash_key_make(const void *p
)
145 const struct cluster_list
*cluster
= p
;
147 return jhash(cluster
->list
, cluster
->length
, 0);
150 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
152 const struct cluster_list
*cluster1
= p1
;
153 const struct cluster_list
*cluster2
= p2
;
155 return (cluster1
->length
== cluster2
->length
156 && (cluster1
->list
== cluster2
->list
157 || memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
)
161 static void cluster_free(struct cluster_list
*cluster
)
163 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
164 XFREE(MTYPE_CLUSTER
, cluster
);
167 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
169 struct cluster_list
*find
;
171 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
177 void cluster_unintern(struct cluster_list
*cluster
)
182 if (cluster
->refcnt
== 0) {
183 hash_release(cluster_hash
, cluster
);
184 cluster_free(cluster
);
188 static void cluster_init(void)
190 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
194 static void cluster_finish(void)
196 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
197 hash_free(cluster_hash
);
201 static struct hash
*encap_hash
= NULL
;
203 static struct hash
*vnc_hash
= NULL
;
205 static struct hash
*srv6_l3vpn_hash
;
206 static struct hash
*srv6_vpn_hash
;
208 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
210 struct bgp_attr_encap_subtlv
*new;
211 struct bgp_attr_encap_subtlv
*tail
;
212 struct bgp_attr_encap_subtlv
*p
;
214 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
215 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
217 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
220 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
223 memcpy(tail
, p
, size
);
230 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
232 struct bgp_attr_encap_subtlv
*next
;
236 XFREE(MTYPE_ENCAP_TLV
, p
);
241 void bgp_attr_flush_encap(struct attr
*attr
)
246 if (attr
->encap_subtlvs
) {
247 encap_free(attr
->encap_subtlvs
);
248 attr
->encap_subtlvs
= NULL
;
251 if (attr
->vnc_subtlvs
) {
252 encap_free(attr
->vnc_subtlvs
);
253 attr
->vnc_subtlvs
= NULL
;
259 * Compare encap sub-tlv chains
264 * This algorithm could be made faster if needed
266 static int encap_same(const struct bgp_attr_encap_subtlv
*h1
,
267 const struct bgp_attr_encap_subtlv
*h2
)
269 const struct bgp_attr_encap_subtlv
*p
;
270 const struct bgp_attr_encap_subtlv
*q
;
274 if (h1
== NULL
|| h2
== NULL
)
277 for (p
= h1
; p
; p
= p
->next
) {
278 for (q
= h2
; q
; q
= q
->next
) {
279 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
280 && !memcmp(p
->value
, q
->value
, p
->length
)) {
289 for (p
= h2
; p
; p
= p
->next
) {
290 for (q
= h1
; q
; q
= q
->next
) {
291 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
292 && !memcmp(p
->value
, q
->value
, p
->length
)) {
304 static void *encap_hash_alloc(void *p
)
306 /* Encap structure is already allocated. */
317 static struct bgp_attr_encap_subtlv
*
318 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
320 struct bgp_attr_encap_subtlv
*find
;
321 struct hash
*hash
= encap_hash
;
323 if (type
== VNC_SUBTLV_TYPE
)
327 find
= hash_get(hash
, encap
, encap_hash_alloc
);
335 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
336 encap_subtlv_type type
)
338 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
342 if (encap
->refcnt
== 0) {
343 struct hash
*hash
= encap_hash
;
345 if (type
== VNC_SUBTLV_TYPE
)
348 hash_release(hash
, encap
);
354 static unsigned int encap_hash_key_make(const void *p
)
356 const struct bgp_attr_encap_subtlv
*encap
= p
;
358 return jhash(encap
->value
, encap
->length
, 0);
361 static bool encap_hash_cmp(const void *p1
, const void *p2
)
363 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
364 (const struct bgp_attr_encap_subtlv
*)p2
);
367 static void encap_init(void)
369 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
372 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
377 static void encap_finish(void)
379 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
380 hash_free(encap_hash
);
383 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
389 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
397 return !memcmp(&(a1
->evpn_overlay
), &(a2
->evpn_overlay
),
398 sizeof(struct bgp_route_evpn
));
401 /* Unknown transit attribute. */
402 static struct hash
*transit_hash
;
404 static void transit_free(struct transit
*transit
)
406 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
407 XFREE(MTYPE_TRANSIT
, transit
);
410 static void *transit_hash_alloc(void *p
)
412 /* Transit structure is already allocated. */
416 static struct transit
*transit_intern(struct transit
*transit
)
418 struct transit
*find
;
420 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
422 transit_free(transit
);
428 static void transit_unintern(struct transit
**transit
)
430 if ((*transit
)->refcnt
)
431 (*transit
)->refcnt
--;
433 if ((*transit
)->refcnt
== 0) {
434 hash_release(transit_hash
, *transit
);
435 transit_free(*transit
);
440 static void *srv6_l3vpn_hash_alloc(void *p
)
445 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
447 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
450 static struct bgp_attr_srv6_l3vpn
*
451 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
453 struct bgp_attr_srv6_l3vpn
*find
;
455 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
457 srv6_l3vpn_free(l3vpn
);
462 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
464 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
469 if (l3vpn
->refcnt
== 0) {
470 hash_release(srv6_l3vpn_hash
, l3vpn
);
471 srv6_l3vpn_free(l3vpn
);
476 static void *srv6_vpn_hash_alloc(void *p
)
481 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
483 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
486 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
488 struct bgp_attr_srv6_vpn
*find
;
490 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
497 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
499 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
504 if (vpn
->refcnt
== 0) {
505 hash_release(srv6_vpn_hash
, vpn
);
511 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
513 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
516 key
= jhash(&l3vpn
->sid
, 16, key
);
517 key
= jhash_1word(l3vpn
->sid_flags
, key
);
518 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
522 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
524 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
525 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
527 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
528 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
529 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
;
532 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
533 const struct bgp_attr_srv6_l3vpn
*h2
)
537 else if (h1
== NULL
|| h2
== NULL
)
540 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
543 static unsigned int srv6_vpn_hash_key_make(const void *p
)
545 const struct bgp_attr_srv6_vpn
*vpn
= p
;
548 key
= jhash(&vpn
->sid
, 16, key
);
549 key
= jhash_1word(vpn
->sid_flags
, key
);
553 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
555 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
556 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
558 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
559 && vpn1
->sid_flags
== vpn2
->sid_flags
;
562 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
563 const struct bgp_attr_srv6_vpn
*h2
)
567 else if (h1
== NULL
|| h2
== NULL
)
570 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
573 static void srv6_init(void)
576 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
577 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
578 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
579 "BGP Prefix-SID SRv6-VPN-Service-TLV");
582 static void srv6_finish(void)
584 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
585 hash_free(srv6_l3vpn_hash
);
586 srv6_l3vpn_hash
= NULL
;
587 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
588 hash_free(srv6_vpn_hash
);
589 srv6_vpn_hash
= NULL
;
592 static unsigned int transit_hash_key_make(const void *p
)
594 const struct transit
*transit
= p
;
596 return jhash(transit
->val
, transit
->length
, 0);
599 static bool transit_hash_cmp(const void *p1
, const void *p2
)
601 const struct transit
*transit1
= p1
;
602 const struct transit
*transit2
= p2
;
604 return (transit1
->length
== transit2
->length
605 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
608 static void transit_init(void)
610 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
614 static void transit_finish(void)
616 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
617 hash_free(transit_hash
);
621 /* Attribute hash routines. */
622 static struct hash
*attrhash
;
624 unsigned long int attr_count(void)
626 return attrhash
->count
;
629 unsigned long int attr_unknown_count(void)
631 return transit_hash
->count
;
634 unsigned int attrhash_key_make(const void *p
)
636 const struct attr
*attr
= (struct attr
*)p
;
638 #define MIX(val) key = jhash_1word(val, key)
639 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
641 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
642 MIX3(attr
->local_pref
, attr
->aggregator_as
,
643 attr
->aggregator_addr
.s_addr
);
644 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
645 attr
->originator_id
.s_addr
);
646 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
649 MIX(aspath_key_make(attr
->aspath
));
651 MIX(community_hash_make(attr
->community
));
653 if (attr
->lcommunity
)
654 MIX(lcommunity_hash_make(attr
->lcommunity
));
655 if (attr
->ecommunity
)
656 MIX(ecommunity_hash_make(attr
->ecommunity
));
658 MIX(cluster_hash_key_make(attr
->cluster
));
660 MIX(transit_hash_key_make(attr
->transit
));
661 if (attr
->encap_subtlvs
)
662 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
664 if (attr
->vnc_subtlvs
)
665 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
667 MIX(attr
->mp_nexthop_len
);
668 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
669 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
670 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
671 MIX(attr
->rmap_table_id
);
676 bool attrhash_cmp(const void *p1
, const void *p2
)
678 const struct attr
*attr1
= p1
;
679 const struct attr
*attr2
= p2
;
681 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
682 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
683 && attr1
->aspath
== attr2
->aspath
684 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
685 && attr1
->local_pref
== attr2
->local_pref
686 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
687 if (attr1
->aggregator_as
== attr2
->aggregator_as
688 && attr1
->aggregator_addr
.s_addr
689 == attr2
->aggregator_addr
.s_addr
690 && attr1
->weight
== attr2
->weight
691 && attr1
->tag
== attr2
->tag
692 && attr1
->label_index
== attr2
->label_index
693 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
694 && attr1
->ecommunity
== attr2
->ecommunity
695 && attr1
->lcommunity
== attr2
->lcommunity
696 && attr1
->cluster
== attr2
->cluster
697 && attr1
->transit
== attr2
->transit
698 && attr1
->rmap_table_id
== attr2
->rmap_table_id
699 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
700 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
702 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
704 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
705 &attr2
->mp_nexthop_global
)
706 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
707 &attr2
->mp_nexthop_local
)
708 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
709 &attr2
->mp_nexthop_global_in
)
710 && IPV4_ADDR_SAME(&attr1
->originator_id
,
711 &attr2
->originator_id
)
712 && overlay_index_same(attr1
, attr2
)
713 && attr1
->nh_ifindex
== attr2
->nh_ifindex
714 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
715 && attr1
->distance
== attr2
->distance
716 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
717 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
))
724 static void attrhash_init(void)
727 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
731 * special for hash_clean below
733 static void attr_vfree(void *attr
)
735 XFREE(MTYPE_ATTR
, attr
);
738 static void attrhash_finish(void)
740 hash_clean(attrhash
, attr_vfree
);
745 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
747 struct attr
*attr
= bucket
->data
;
748 char sid_str
[BUFSIZ
];
750 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
751 inet_ntoa(attr
->nexthop
));
754 if (attr
->srv6_l3vpn
)
755 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
756 else if (attr
->srv6_vpn
)
757 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
761 " med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
762 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
763 attr
->weight
, attr
->label
, sid_str
);
766 void attr_show_all(struct vty
*vty
)
768 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
769 void *))attr_show_all_iterator
,
773 static void *bgp_attr_hash_alloc(void *p
)
775 struct attr
*val
= (struct attr
*)p
;
778 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
780 if (val
->encap_subtlvs
) {
781 val
->encap_subtlvs
= NULL
;
784 if (val
->vnc_subtlvs
) {
785 val
->vnc_subtlvs
= NULL
;
789 val
->srv6_l3vpn
= NULL
;
791 val
->srv6_vpn
= NULL
;
797 /* Internet argument attribute. */
798 struct attr
*bgp_attr_intern(struct attr
*attr
)
802 /* Intern referenced strucutre. */
804 if (!attr
->aspath
->refcnt
)
805 attr
->aspath
= aspath_intern(attr
->aspath
);
807 attr
->aspath
->refcnt
++;
809 if (attr
->community
) {
810 if (!attr
->community
->refcnt
)
811 attr
->community
= community_intern(attr
->community
);
813 attr
->community
->refcnt
++;
816 if (attr
->ecommunity
) {
817 if (!attr
->ecommunity
->refcnt
)
818 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
820 attr
->ecommunity
->refcnt
++;
822 if (attr
->lcommunity
) {
823 if (!attr
->lcommunity
->refcnt
)
824 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
826 attr
->lcommunity
->refcnt
++;
829 if (!attr
->cluster
->refcnt
)
830 attr
->cluster
= cluster_intern(attr
->cluster
);
832 attr
->cluster
->refcnt
++;
835 if (!attr
->transit
->refcnt
)
836 attr
->transit
= transit_intern(attr
->transit
);
838 attr
->transit
->refcnt
++;
840 if (attr
->encap_subtlvs
) {
841 if (!attr
->encap_subtlvs
->refcnt
)
842 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
845 attr
->encap_subtlvs
->refcnt
++;
847 if (attr
->srv6_l3vpn
) {
848 if (!attr
->srv6_l3vpn
->refcnt
)
849 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
851 attr
->srv6_l3vpn
->refcnt
++;
853 if (attr
->srv6_vpn
) {
854 if (!attr
->srv6_vpn
->refcnt
)
855 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
857 attr
->srv6_vpn
->refcnt
++;
860 if (attr
->vnc_subtlvs
) {
861 if (!attr
->vnc_subtlvs
->refcnt
)
862 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
865 attr
->vnc_subtlvs
->refcnt
++;
869 /* At this point, attr only contains intern'd pointers. that means
870 * if we find it in attrhash, it has all the same pointers and we
871 * correctly updated the refcounts on these.
872 * If we don't find it, we need to allocate a one because in all
873 * cases this returns a new reference to a hashed attr, but the input
875 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
881 /* Make network statement's attribute. */
882 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
884 memset(attr
, 0, sizeof(struct attr
));
886 attr
->origin
= origin
;
887 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
888 attr
->aspath
= aspath_empty();
889 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
890 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
892 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
893 attr
->label
= MPLS_INVALID_LABEL
;
894 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
895 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
900 /* Create the attributes for an aggregate */
901 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, uint8_t origin
,
902 struct aspath
*aspath
,
903 struct community
*community
,
904 struct ecommunity
*ecommunity
,
905 struct lcommunity
*lcommunity
,
906 struct bgp_aggregate
*aggregate
,
907 uint8_t atomic_aggregate
,
914 memset(&attr
, 0, sizeof(struct attr
));
916 /* Origin attribute. */
917 attr
.origin
= origin
;
918 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
920 /* AS path attribute. */
922 attr
.aspath
= aspath_intern(aspath
);
924 attr
.aspath
= aspath_empty();
925 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
927 /* Next hop attribute. */
928 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
931 uint32_t gshut
= COMMUNITY_GSHUT
;
933 /* If we are not shutting down ourselves and we are
934 * aggregating a route that contains the GSHUT community we
935 * need to remove that community when creating the aggregate */
936 if (!bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)
937 && community_include(community
, gshut
)) {
938 community_del_val(community
, &gshut
);
941 attr
.community
= community
;
942 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
946 attr
.ecommunity
= ecommunity
;
947 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
951 attr
.lcommunity
= lcommunity
;
952 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
955 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
956 bgp_attr_add_gshut_community(&attr
);
959 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
960 attr
.label
= MPLS_INVALID_LABEL
;
961 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
962 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
963 if (!aggregate
->as_set
|| atomic_aggregate
)
964 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
965 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
966 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
967 attr
.aggregator_as
= bgp
->confed_id
;
969 attr
.aggregator_as
= bgp
->as
;
970 attr
.aggregator_addr
= bgp
->router_id
;
971 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
972 attr
.label
= MPLS_INVALID_LABEL
;
974 /* Apply route-map */
975 if (aggregate
->rmap
.name
) {
976 struct attr attr_tmp
= attr
;
977 struct bgp_path_info rmap_path
;
979 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
980 rmap_path
.peer
= bgp
->peer_self
;
981 rmap_path
.attr
= &attr_tmp
;
983 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
985 ret
= route_map_apply(aggregate
->rmap
.map
, p
, RMAP_BGP
,
988 bgp
->peer_self
->rmap_type
= 0;
990 if (ret
== RMAP_DENYMATCH
) {
991 /* Free uninterned attribute. */
992 bgp_attr_flush(&attr_tmp
);
994 /* Unintern original. */
995 aspath_unintern(&attr
.aspath
);
999 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
1000 bgp_attr_add_gshut_community(&attr_tmp
);
1002 new = bgp_attr_intern(&attr_tmp
);
1005 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
1006 bgp_attr_add_gshut_community(&attr
);
1008 new = bgp_attr_intern(&attr
);
1011 aspath_unintern(&new->aspath
);
1015 /* Unintern just the sub-components of the attr, but not the attr */
1016 void bgp_attr_unintern_sub(struct attr
*attr
)
1018 /* aspath refcount shoud be decrement. */
1020 aspath_unintern(&attr
->aspath
);
1021 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1023 if (attr
->community
)
1024 community_unintern(&attr
->community
);
1025 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1027 if (attr
->ecommunity
)
1028 ecommunity_unintern(&attr
->ecommunity
);
1029 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1031 if (attr
->lcommunity
)
1032 lcommunity_unintern(&attr
->lcommunity
);
1033 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1036 cluster_unintern(attr
->cluster
);
1037 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1040 transit_unintern(&attr
->transit
);
1042 if (attr
->encap_subtlvs
)
1043 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1046 if (attr
->vnc_subtlvs
)
1047 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1050 if (attr
->srv6_l3vpn
)
1051 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1054 srv6_vpn_unintern(&attr
->srv6_vpn
);
1058 * We have some show commands that let you experimentally
1059 * apply a route-map. When we apply the route-map
1060 * we are reseting values but not saving them for
1061 * posterity via intern'ing( because route-maps don't
1062 * do that) but at this point in time we need
1063 * to compare the new attr to the old and if the
1064 * routemap has changed it we need to, as Snoop Dog says,
1065 * Drop it like it's hot
1067 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
1069 if (new->aspath
!= old
->aspath
)
1070 aspath_free(new->aspath
);
1072 if (new->community
!= old
->community
)
1073 community_free(&new->community
);
1075 if (new->ecommunity
!= old
->ecommunity
)
1076 ecommunity_free(&new->ecommunity
);
1078 if (new->lcommunity
!= old
->lcommunity
)
1079 lcommunity_free(&new->lcommunity
);
1082 /* Free bgp attribute and aspath. */
1083 void bgp_attr_unintern(struct attr
**pattr
)
1085 struct attr
*attr
= *pattr
;
1089 /* Decrement attribute reference. */
1094 /* If reference becomes zero then free attribute object. */
1095 if (attr
->refcnt
== 0) {
1096 ret
= hash_release(attrhash
, attr
);
1097 assert(ret
!= NULL
);
1098 XFREE(MTYPE_ATTR
, attr
);
1102 bgp_attr_unintern_sub(&tmp
);
1105 void bgp_attr_flush(struct attr
*attr
)
1107 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1108 aspath_free(attr
->aspath
);
1109 attr
->aspath
= NULL
;
1111 if (attr
->community
&& !attr
->community
->refcnt
)
1112 community_free(&attr
->community
);
1113 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
1114 ecommunity_free(&attr
->ecommunity
);
1115 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
1116 lcommunity_free(&attr
->lcommunity
);
1117 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
1118 cluster_free(attr
->cluster
);
1119 attr
->cluster
= NULL
;
1121 if (attr
->transit
&& !attr
->transit
->refcnt
) {
1122 transit_free(attr
->transit
);
1123 attr
->transit
= NULL
;
1125 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1126 encap_free(attr
->encap_subtlvs
);
1127 attr
->encap_subtlvs
= NULL
;
1130 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
1131 encap_free(attr
->vnc_subtlvs
);
1132 attr
->vnc_subtlvs
= NULL
;
1137 /* Implement draft-scudder-idr-optional-transitive behaviour and
1138 * avoid resetting sessions for malformed attributes which are
1139 * are partial/optional and hence where the error likely was not
1140 * introduced by the sending neighbour.
1142 static bgp_attr_parse_ret_t
1143 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1146 struct peer
*const peer
= args
->peer
;
1147 const uint8_t flags
= args
->flags
;
1148 /* startp and length must be special-cased, as whether or not to
1149 * send the attribute data with the NOTIFY depends on the error,
1150 * the caller therefore signals this with the seperate length argument
1152 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1154 /* Only relax error handling for eBGP peers */
1155 if (peer
->sort
!= BGP_PEER_EBGP
) {
1156 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1157 notify_datap
, length
);
1158 return BGP_ATTR_PARSE_ERROR
;
1161 /* Adjust the stream getp to the end of the attribute, in case we can
1162 * still proceed but the caller hasn't read all the attribute.
1164 stream_set_getp(BGP_INPUT(peer
),
1165 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1168 switch (args
->type
) {
1169 /* where an attribute is relatively inconsequential, e.g. it does not
1170 * affect route selection, and can be safely ignored, then any such
1171 * attributes which are malformed should just be ignored and the route
1172 * processed as normal.
1174 case BGP_ATTR_AS4_AGGREGATOR
:
1175 case BGP_ATTR_AGGREGATOR
:
1176 case BGP_ATTR_ATOMIC_AGGREGATE
:
1177 return BGP_ATTR_PARSE_PROCEED
;
1179 /* Core attributes, particularly ones which may influence route
1180 * selection, should always cause session resets
1182 case BGP_ATTR_ORIGIN
:
1183 case BGP_ATTR_AS_PATH
:
1184 case BGP_ATTR_NEXT_HOP
:
1185 case BGP_ATTR_MULTI_EXIT_DISC
:
1186 case BGP_ATTR_LOCAL_PREF
:
1187 case BGP_ATTR_COMMUNITIES
:
1188 case BGP_ATTR_ORIGINATOR_ID
:
1189 case BGP_ATTR_CLUSTER_LIST
:
1190 case BGP_ATTR_MP_REACH_NLRI
:
1191 case BGP_ATTR_MP_UNREACH_NLRI
:
1192 case BGP_ATTR_EXT_COMMUNITIES
:
1193 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1194 notify_datap
, length
);
1195 return BGP_ATTR_PARSE_ERROR
;
1198 /* Partial optional attributes that are malformed should not cause
1199 * the whole session to be reset. Instead treat it as a withdrawal
1200 * of the routes, if possible.
1202 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1203 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1204 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1205 return BGP_ATTR_PARSE_WITHDRAW
;
1207 /* default to reset */
1208 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1211 /* Find out what is wrong with the path attribute flag bits and log the error.
1212 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1213 Extended Length. Checking O/T/P bits at once implies, that the attribute
1214 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1215 non-transitive" attribute. */
1217 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1218 uint8_t desired_flags
/* how RFC says it must be */
1221 uint8_t seen
= 0, i
;
1222 uint8_t real_flags
= args
->flags
;
1223 const uint8_t attr_code
= args
->type
;
1225 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1226 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1227 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1228 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1229 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1230 flog_err(EC_BGP_ATTR_FLAG
,
1231 "%s attribute must%s be flagged as \"%s\"",
1232 lookup_msg(attr_str
, attr_code
, NULL
),
1233 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1236 attr_flag_str
[i
].str
);
1241 "Strange, %s called for attr %s, but no problem found with flags"
1242 " (real flags 0x%x, desired 0x%x)",
1243 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1244 real_flags
, desired_flags
);
1248 /* Required flags for attributes. EXTLEN will be masked off when testing,
1249 * as will PARTIAL for optional+transitive attributes.
1251 const uint8_t attr_flags_values
[] = {
1252 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1253 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1254 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1255 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1256 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1257 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1258 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1259 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1260 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1261 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1262 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1263 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1264 [BGP_ATTR_EXT_COMMUNITIES
] =
1265 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1266 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1267 [BGP_ATTR_AS4_AGGREGATOR
] =
1268 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1269 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1270 [BGP_ATTR_LARGE_COMMUNITIES
] =
1271 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1272 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1274 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1276 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1278 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1279 const uint8_t flags
= args
->flags
;
1280 const uint8_t attr_code
= args
->type
;
1282 /* there may be attributes we don't know about */
1283 if (attr_code
> attr_flags_values_max
)
1285 if (attr_flags_values
[attr_code
] == 0)
1288 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1292 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1293 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1296 "%s well-known attributes must have transitive flag set (%x)",
1297 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1301 /* "For well-known attributes and for optional non-transitive
1303 * the Partial bit MUST be set to 0."
1305 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1306 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1307 flog_err(EC_BGP_ATTR_FLAG
,
1308 "%s well-known attribute "
1309 "must NOT have the partial flag set (%x)",
1310 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1313 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1314 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1315 flog_err(EC_BGP_ATTR_FLAG
,
1316 "%s optional + transitive attribute "
1317 "must NOT have the partial flag set (%x)",
1318 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1323 /* Optional transitive attributes may go through speakers that don't
1324 * reocgnise them and set the Partial bit.
1326 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1327 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1328 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1330 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1333 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1337 /* Get origin attribute of the update message. */
1338 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1340 struct peer
*const peer
= args
->peer
;
1341 struct attr
*const attr
= args
->attr
;
1342 const bgp_size_t length
= args
->length
;
1344 /* If any recognized attribute has Attribute Length that conflicts
1345 with the expected length (based on the attribute type code), then
1346 the Error Subcode is set to Attribute Length Error. The Data
1347 field contains the erroneous attribute (type, length and
1350 flog_err(EC_BGP_ATTR_LEN
,
1351 "Origin attribute length is not one %d", length
);
1352 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1356 /* Fetch origin attribute. */
1357 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1359 /* If the ORIGIN attribute has an undefined value, then the Error
1360 Subcode is set to Invalid Origin Attribute. The Data field
1361 contains the unrecognized attribute (type, length and value). */
1362 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1363 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1364 flog_err(EC_BGP_ATTR_ORIGIN
,
1365 "Origin attribute value is invalid %d", attr
->origin
);
1366 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1370 /* Set oring attribute flag. */
1371 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1376 /* Parse AS path information. This function is wrapper of
1378 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1380 struct attr
*const attr
= args
->attr
;
1381 struct peer
*const peer
= args
->peer
;
1382 const bgp_size_t length
= args
->length
;
1385 * peer with AS4 => will get 4Byte ASnums
1386 * otherwise, will get 16 Bit
1388 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1389 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1391 /* In case of IBGP, length will be zero. */
1392 if (!attr
->aspath
) {
1393 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1394 "Malformed AS path from %s, length is %d", peer
->host
,
1396 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1400 /* Set aspath attribute flag. */
1401 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1403 return BGP_ATTR_PARSE_PROCEED
;
1406 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1407 struct attr
*const attr
)
1409 /* These checks were part of bgp_attr_aspath, but with
1410 * as4 we should to check aspath things when
1411 * aspath synthesizing with as4_path has already taken place.
1412 * Otherwise we check ASPATH and use the synthesized thing, and that is
1414 * So do the checks later, i.e. here
1416 struct aspath
*aspath
;
1418 /* Confederation sanity check. */
1419 if ((peer
->sort
== BGP_PEER_CONFED
1420 && !aspath_left_confed_check(attr
->aspath
))
1421 || (peer
->sort
== BGP_PEER_EBGP
1422 && aspath_confed_check(attr
->aspath
))) {
1423 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1425 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1426 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1427 return BGP_ATTR_PARSE_ERROR
;
1430 /* First AS check for EBGP. */
1431 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1432 if (peer
->sort
== BGP_PEER_EBGP
1433 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1434 flog_err(EC_BGP_ATTR_FIRST_AS
,
1435 "%s incorrect first AS (must be %u)",
1436 peer
->host
, peer
->as
);
1437 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1438 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1439 return BGP_ATTR_PARSE_ERROR
;
1443 /* local-as prepend */
1444 if (peer
->change_local_as
1445 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1446 aspath
= aspath_dup(attr
->aspath
);
1447 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1448 aspath_unintern(&attr
->aspath
);
1449 attr
->aspath
= aspath_intern(aspath
);
1452 return BGP_ATTR_PARSE_PROCEED
;
1455 /* Parse AS4 path information. This function is another wrapper of
1457 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1458 struct aspath
**as4_path
)
1460 struct peer
*const peer
= args
->peer
;
1461 struct attr
*const attr
= args
->attr
;
1462 const bgp_size_t length
= args
->length
;
1464 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1466 /* In case of IBGP, length will be zero. */
1468 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1469 "Malformed AS4 path from %s, length is %d", peer
->host
,
1471 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1475 /* Set aspath attribute flag. */
1476 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1478 return BGP_ATTR_PARSE_PROCEED
;
1482 * Check that the nexthop attribute is valid.
1484 bgp_attr_parse_ret_t
1485 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1487 in_addr_t nexthop_h
;
1489 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1490 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1491 || IPV4_CLASS_DE(nexthop_h
))
1492 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1493 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1494 char buf
[INET_ADDRSTRLEN
];
1496 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1498 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1500 data
[0] = BGP_ATTR_FLAG_TRANS
;
1501 data
[1] = BGP_ATTR_NEXT_HOP
;
1502 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1503 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1504 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1505 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1507 return BGP_ATTR_PARSE_ERROR
;
1510 return BGP_ATTR_PARSE_PROCEED
;
1513 /* Nexthop attribute. */
1514 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1516 struct peer
*const peer
= args
->peer
;
1517 struct attr
*const attr
= args
->attr
;
1518 const bgp_size_t length
= args
->length
;
1520 /* Check nexthop attribute length. */
1522 flog_err(EC_BGP_ATTR_LEN
,
1523 "Nexthop attribute length isn't four [%d]", length
);
1525 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1529 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1530 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1532 return BGP_ATTR_PARSE_PROCEED
;
1535 /* MED atrribute. */
1536 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1538 struct peer
*const peer
= args
->peer
;
1539 struct attr
*const attr
= args
->attr
;
1540 const bgp_size_t length
= args
->length
;
1544 flog_err(EC_BGP_ATTR_LEN
,
1545 "MED attribute length isn't four [%d]", length
);
1547 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1551 attr
->med
= stream_getl(peer
->curr
);
1553 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1555 return BGP_ATTR_PARSE_PROCEED
;
1558 /* Local preference attribute. */
1559 static bgp_attr_parse_ret_t
1560 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1562 struct peer
*const peer
= args
->peer
;
1563 struct attr
*const attr
= args
->attr
;
1564 const bgp_size_t length
= args
->length
;
1568 flog_err(EC_BGP_ATTR_LEN
,
1569 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1570 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1574 /* If it is contained in an UPDATE message that is received from an
1575 external peer, then this attribute MUST be ignored by the
1576 receiving speaker. */
1577 if (peer
->sort
== BGP_PEER_EBGP
) {
1578 stream_forward_getp(peer
->curr
, length
);
1579 return BGP_ATTR_PARSE_PROCEED
;
1582 attr
->local_pref
= stream_getl(peer
->curr
);
1584 /* Set the local-pref flag. */
1585 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1587 return BGP_ATTR_PARSE_PROCEED
;
1590 /* Atomic aggregate. */
1591 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1593 struct attr
*const attr
= args
->attr
;
1594 const bgp_size_t length
= args
->length
;
1598 flog_err(EC_BGP_ATTR_LEN
,
1599 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1601 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1605 /* Set atomic aggregate flag. */
1606 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1608 return BGP_ATTR_PARSE_PROCEED
;
1611 /* Aggregator attribute */
1612 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1614 struct peer
*const peer
= args
->peer
;
1615 struct attr
*const attr
= args
->attr
;
1616 const bgp_size_t length
= args
->length
;
1620 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1621 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1624 if (length
!= wantedlen
) {
1625 flog_err(EC_BGP_ATTR_LEN
,
1626 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1628 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1632 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1633 attr
->aggregator_as
= stream_getl(peer
->curr
);
1635 attr
->aggregator_as
= stream_getw(peer
->curr
);
1636 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1638 /* Set atomic aggregate flag. */
1639 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1641 return BGP_ATTR_PARSE_PROCEED
;
1644 /* New Aggregator attribute */
1645 static bgp_attr_parse_ret_t
1646 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1647 as_t
*as4_aggregator_as
,
1648 struct in_addr
*as4_aggregator_addr
)
1650 struct peer
*const peer
= args
->peer
;
1651 struct attr
*const attr
= args
->attr
;
1652 const bgp_size_t length
= args
->length
;
1655 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1657 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1661 *as4_aggregator_as
= stream_getl(peer
->curr
);
1662 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1664 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1666 return BGP_ATTR_PARSE_PROCEED
;
1669 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1671 static bgp_attr_parse_ret_t
1672 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1673 struct aspath
*as4_path
, as_t as4_aggregator
,
1674 struct in_addr
*as4_aggregator_addr
)
1676 int ignore_as4_path
= 0;
1677 struct aspath
*newpath
;
1679 if (!attr
->aspath
) {
1680 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1682 * checked that all well-known, mandatory attributes were
1685 * Can only be a problem with peer itself - hard error
1687 return BGP_ATTR_PARSE_ERROR
;
1690 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1691 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1693 * It is worth a warning though, because the peer really
1694 * should not send them
1696 if (BGP_DEBUG(as4
, AS4
)) {
1697 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1698 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1699 "AS4 capable peer, yet it sent");
1702 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1703 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1705 "AS4 capable peer, yet it sent");
1708 return BGP_ATTR_PARSE_PROCEED
;
1711 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1712 * because that may override AS4_PATH
1714 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1715 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1717 * if the as_number in aggregator is not AS_TRANS,
1718 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1719 * and the Aggregator shall be taken as
1720 * info on the aggregating node, and the AS_PATH
1721 * shall be taken as the AS_PATH
1723 * the Aggregator shall be ignored and the
1724 * AS4_AGGREGATOR shall be taken as the
1725 * Aggregating node and the AS_PATH is to be
1726 * constructed "as in all other cases"
1728 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1730 if (BGP_DEBUG(as4
, AS4
))
1732 "[AS4] %s BGP not AS4 capable peer"
1733 " send AGGREGATOR != AS_TRANS and"
1734 " AS4_AGGREGATOR, so ignore"
1735 " AS4_AGGREGATOR and AS4_PATH",
1737 ignore_as4_path
= 1;
1739 /* "New_aggregator shall be taken as aggregator"
1741 attr
->aggregator_as
= as4_aggregator
;
1742 attr
->aggregator_addr
.s_addr
=
1743 as4_aggregator_addr
->s_addr
;
1746 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1747 * That is bogus - but reading the conditions
1748 * we have to handle AS4_AGGREGATOR as if it were
1749 * AGGREGATOR in that case
1751 if (BGP_DEBUG(as4
, AS4
))
1753 "[AS4] %s BGP not AS4 capable peer send"
1754 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1755 " it as if AGGREGATOR with AS_TRANS had been there",
1757 attr
->aggregator_as
= as4_aggregator
;
1758 /* sweep it under the carpet and simulate a "good"
1760 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1764 /* need to reconcile NEW_AS_PATH and AS_PATH */
1765 if (!ignore_as4_path
1766 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1767 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1769 return BGP_ATTR_PARSE_ERROR
;
1771 aspath_unintern(&attr
->aspath
);
1772 attr
->aspath
= aspath_intern(newpath
);
1774 return BGP_ATTR_PARSE_PROCEED
;
1777 /* Community attribute. */
1778 static bgp_attr_parse_ret_t
1779 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1781 struct peer
*const peer
= args
->peer
;
1782 struct attr
*const attr
= args
->attr
;
1783 const bgp_size_t length
= args
->length
;
1786 attr
->community
= NULL
;
1787 return BGP_ATTR_PARSE_PROCEED
;
1791 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1793 /* XXX: fix community_parse to use stream API and remove this */
1794 stream_forward_getp(peer
->curr
, length
);
1796 if (!attr
->community
)
1797 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1800 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1802 return BGP_ATTR_PARSE_PROCEED
;
1805 /* Originator ID attribute. */
1806 static bgp_attr_parse_ret_t
1807 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1809 struct peer
*const peer
= args
->peer
;
1810 struct attr
*const attr
= args
->attr
;
1811 const bgp_size_t length
= args
->length
;
1815 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1818 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1822 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1824 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1826 return BGP_ATTR_PARSE_PROCEED
;
1829 /* Cluster list attribute. */
1830 static bgp_attr_parse_ret_t
1831 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1833 struct peer
*const peer
= args
->peer
;
1834 struct attr
*const attr
= args
->attr
;
1835 const bgp_size_t length
= args
->length
;
1839 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
1841 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1846 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1848 /* XXX: Fix cluster_parse to use stream API and then remove this */
1849 stream_forward_getp(peer
->curr
, length
);
1851 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1853 return BGP_ATTR_PARSE_PROCEED
;
1856 /* Multiprotocol reachability information parse. */
1857 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1858 struct bgp_nlri
*mp_update
)
1862 iana_safi_t pkt_safi
;
1864 bgp_size_t nlri_len
;
1867 struct peer
*const peer
= args
->peer
;
1868 struct attr
*const attr
= args
->attr
;
1869 const bgp_size_t length
= args
->length
;
1871 /* Set end of packet. */
1872 s
= BGP_INPUT(peer
);
1873 start
= stream_get_getp(s
);
1875 /* safe to read statically sized header? */
1876 #define BGP_MP_REACH_MIN_SIZE 5
1877 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1878 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1879 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
1880 __func__
, peer
->host
, (unsigned long)length
);
1881 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1884 /* Load AFI, SAFI. */
1885 pkt_afi
= stream_getw(s
);
1886 pkt_safi
= stream_getc(s
);
1888 /* Convert AFI, SAFI to internal values, check. */
1889 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1890 /* Log if AFI or SAFI is unrecognized. This is not an error
1892 * the attribute is otherwise malformed.
1894 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1896 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
1897 peer
->host
, iana_afi2str(pkt_afi
),
1898 iana_safi2str(pkt_safi
));
1899 return BGP_ATTR_PARSE_ERROR
;
1902 /* Get nexthop length. */
1903 attr
->mp_nexthop_len
= stream_getc(s
);
1905 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1907 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
1908 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1909 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1912 /* Nexthop length check. */
1913 switch (attr
->mp_nexthop_len
) {
1915 if (safi
!= SAFI_FLOWSPEC
) {
1916 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
1917 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1918 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1921 case BGP_ATTR_NHLEN_VPNV4
:
1922 stream_getl(s
); /* RD high */
1923 stream_getl(s
); /* RD low */
1925 * NOTE: intentional fall through
1926 * - for consistency in rx processing
1928 * The following comment is to signal GCC this intention
1929 * and suppress the warning
1932 case BGP_ATTR_NHLEN_IPV4
:
1933 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1934 /* Probably needed for RFC 2283 */
1935 if (attr
->nexthop
.s_addr
== 0)
1936 memcpy(&attr
->nexthop
.s_addr
,
1937 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1939 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1940 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1941 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1942 stream_getl(s
); /* RD high */
1943 stream_getl(s
); /* RD low */
1945 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1946 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1947 if (!peer
->nexthop
.ifp
) {
1948 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
1950 return BGP_ATTR_PARSE_WITHDRAW
;
1952 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1955 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1956 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1957 if (attr
->mp_nexthop_len
1958 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1959 stream_getl(s
); /* RD high */
1960 stream_getl(s
); /* RD low */
1962 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1963 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1964 if (!peer
->nexthop
.ifp
) {
1965 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
1967 return BGP_ATTR_PARSE_WITHDRAW
;
1969 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1971 if (attr
->mp_nexthop_len
1972 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1973 stream_getl(s
); /* RD high */
1974 stream_getl(s
); /* RD low */
1976 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1977 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1978 char buf1
[INET6_ADDRSTRLEN
];
1979 char buf2
[INET6_ADDRSTRLEN
];
1981 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1983 "%s sent next-hops %s and %s. Ignoring non-LL value",
1986 &attr
->mp_nexthop_global
,
1987 buf1
, INET6_ADDRSTRLEN
),
1989 &attr
->mp_nexthop_local
, buf2
,
1992 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1994 if (!peer
->nexthop
.ifp
) {
1995 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
1997 return BGP_ATTR_PARSE_WITHDRAW
;
1999 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2002 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2003 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2004 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2008 zlog_info("%s: %s sent SNPA which couldn't be read",
2009 __func__
, peer
->host
);
2010 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2015 if ((val
= stream_getc(s
)))
2017 EC_BGP_DEFUNCT_SNPA_LEN
,
2018 "%s sent non-zero value, %u, for defunct SNPA-length field",
2022 /* must have nrli_len, what is left of the attribute */
2023 nlri_len
= LEN_LEFT
;
2024 if (nlri_len
> STREAM_READABLE(s
)) {
2025 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2026 __func__
, peer
->host
);
2027 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2031 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2032 __func__
, peer
->host
);
2034 mp_update
->afi
= afi
;
2035 mp_update
->safi
= safi
;
2036 return BGP_ATTR_PARSE_EOR
;
2039 mp_update
->afi
= afi
;
2040 mp_update
->safi
= safi
;
2041 mp_update
->nlri
= stream_pnt(s
);
2042 mp_update
->length
= nlri_len
;
2044 stream_forward_getp(s
, nlri_len
);
2046 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2048 return BGP_ATTR_PARSE_PROCEED
;
2052 /* Multiprotocol unreachable parse */
2053 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2054 struct bgp_nlri
*mp_withdraw
)
2059 iana_safi_t pkt_safi
;
2061 uint16_t withdraw_len
;
2062 struct peer
*const peer
= args
->peer
;
2063 struct attr
*const attr
= args
->attr
;
2064 const bgp_size_t length
= args
->length
;
2068 #define BGP_MP_UNREACH_MIN_SIZE 3
2069 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2070 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2072 pkt_afi
= stream_getw(s
);
2073 pkt_safi
= stream_getc(s
);
2075 /* Convert AFI, SAFI to internal values, check. */
2076 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2077 /* Log if AFI or SAFI is unrecognized. This is not an error
2079 * the attribute is otherwise malformed.
2081 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2083 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2084 peer
->host
, iana_afi2str(pkt_afi
),
2085 iana_safi2str(pkt_safi
));
2086 return BGP_ATTR_PARSE_ERROR
;
2089 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2091 mp_withdraw
->afi
= afi
;
2092 mp_withdraw
->safi
= safi
;
2093 mp_withdraw
->nlri
= stream_pnt(s
);
2094 mp_withdraw
->length
= withdraw_len
;
2096 stream_forward_getp(s
, withdraw_len
);
2098 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2100 return BGP_ATTR_PARSE_PROCEED
;
2103 /* Large Community attribute. */
2104 static bgp_attr_parse_ret_t
2105 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2107 struct peer
*const peer
= args
->peer
;
2108 struct attr
*const attr
= args
->attr
;
2109 const bgp_size_t length
= args
->length
;
2112 * Large community follows new attribute format.
2115 attr
->lcommunity
= NULL
;
2116 /* Empty extcomm doesn't seem to be invalid per se */
2117 return BGP_ATTR_PARSE_PROCEED
;
2121 lcommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
2122 /* XXX: fix ecommunity_parse to use stream API */
2123 stream_forward_getp(peer
->curr
, length
);
2125 if (!attr
->lcommunity
)
2126 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2129 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2131 return BGP_ATTR_PARSE_PROCEED
;
2134 /* Extended Community attribute. */
2135 static bgp_attr_parse_ret_t
2136 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2138 struct peer
*const peer
= args
->peer
;
2139 struct attr
*const attr
= args
->attr
;
2140 const bgp_size_t length
= args
->length
;
2144 attr
->ecommunity
= NULL
;
2145 /* Empty extcomm doesn't seem to be invalid per se */
2146 return BGP_ATTR_PARSE_PROCEED
;
2150 ecommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
2151 /* XXX: fix ecommunity_parse to use stream API */
2152 stream_forward_getp(peer
->curr
, length
);
2154 if (!attr
->ecommunity
)
2155 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2158 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2160 /* Extract MAC mobility sequence number, if any. */
2161 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2162 attr
->sticky
= sticky
;
2164 /* Check if this is a Gateway MAC-IP advertisement */
2165 attr
->default_gw
= bgp_attr_default_gw(attr
);
2167 /* Handle scenario where router flag ecommunity is not
2168 * set but default gw ext community is present.
2169 * Use default gateway, set and propogate R-bit.
2171 if (attr
->default_gw
)
2172 attr
->router_flag
= 1;
2174 /* Check EVPN Neighbor advertisement flags, R-bit */
2175 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
);
2177 /* Extract the Rmac, if any */
2178 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2179 if (bgp_debug_update(peer
, NULL
, NULL
, 1) &&
2180 bgp_mac_exist(&attr
->rmac
)) {
2181 char buf1
[ETHER_ADDR_STRLEN
];
2183 zlog_debug("%s: router mac %s is self mac",
2185 prefix_mac2str(&attr
->rmac
, buf1
,
2191 /* Get the tunnel type from encap extended community */
2192 bgp_attr_extcom_tunnel_type(attr
,
2193 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2195 return BGP_ATTR_PARSE_PROCEED
;
2198 /* Parse Tunnel Encap attribute in an UPDATE */
2199 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2200 bgp_size_t length
, /* IN: attr's length field */
2201 struct attr
*attr
, /* IN: caller already allocated */
2202 uint8_t flag
, /* IN: attr's flags field */
2206 uint16_t tunneltype
= 0;
2208 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2210 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2211 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2213 "Tunnel Encap attribute flag isn't optional and transitive %d",
2215 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2216 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2221 if (BGP_ATTR_ENCAP
== type
) {
2222 /* read outer TLV type and length */
2223 uint16_t tlv_length
;
2227 "Tunnel Encap attribute not long enough to contain outer T,L");
2228 bgp_notify_send_with_data(
2229 peer
, BGP_NOTIFY_UPDATE_ERR
,
2230 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2233 tunneltype
= stream_getw(BGP_INPUT(peer
));
2234 tlv_length
= stream_getw(BGP_INPUT(peer
));
2237 if (tlv_length
!= length
) {
2238 zlog_info("%s: tlv_length(%d) != length(%d)",
2239 __func__
, tlv_length
, length
);
2243 while (length
>= 4) {
2244 uint16_t subtype
= 0;
2245 uint16_t sublength
= 0;
2246 struct bgp_attr_encap_subtlv
*tlv
;
2248 if (BGP_ATTR_ENCAP
== type
) {
2249 subtype
= stream_getc(BGP_INPUT(peer
));
2250 sublength
= stream_getc(BGP_INPUT(peer
));
2254 subtype
= stream_getw(BGP_INPUT(peer
));
2255 sublength
= stream_getw(BGP_INPUT(peer
));
2260 if (sublength
> length
) {
2262 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2264 bgp_notify_send_with_data(
2265 peer
, BGP_NOTIFY_UPDATE_ERR
,
2266 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2270 /* alloc and copy sub-tlv */
2271 /* TBD make sure these are freed when attributes are released */
2272 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2273 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2274 tlv
->type
= subtype
;
2275 tlv
->length
= sublength
;
2276 stream_get(tlv
->value
, peer
->curr
, sublength
);
2277 length
-= sublength
;
2279 /* attach tlv to encap chain */
2280 if (BGP_ATTR_ENCAP
== type
) {
2281 struct bgp_attr_encap_subtlv
*stlv_last
;
2282 for (stlv_last
= attr
->encap_subtlvs
;
2283 stlv_last
&& stlv_last
->next
;
2284 stlv_last
= stlv_last
->next
)
2287 stlv_last
->next
= tlv
;
2289 attr
->encap_subtlvs
= tlv
;
2293 struct bgp_attr_encap_subtlv
*stlv_last
;
2294 for (stlv_last
= attr
->vnc_subtlvs
;
2295 stlv_last
&& stlv_last
->next
;
2296 stlv_last
= stlv_last
->next
)
2299 stlv_last
->next
= tlv
;
2301 attr
->vnc_subtlvs
= tlv
;
2307 if (BGP_ATTR_ENCAP
== type
) {
2308 attr
->encap_tunneltype
= tunneltype
;
2312 /* spurious leftover data */
2314 "Tunnel Encap attribute length is bad: %d leftover octets",
2316 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2317 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2326 * Read an individual SID value returning how much data we have read
2327 * Returns 0 if there was an error that needs to be passed up the stack
2329 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2330 struct bgp_attr_parser_args
*args
,
2331 struct bgp_nlri
*mp_update
)
2333 struct peer
*const peer
= args
->peer
;
2334 struct attr
*const attr
= args
->attr
;
2335 uint32_t label_index
;
2336 struct in6_addr ipv6_sid
;
2338 uint32_t srgb_range
;
2340 uint8_t sid_type
, sid_flags
;
2341 uint16_t endpoint_behavior
;
2344 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2345 if (STREAM_READABLE(peer
->curr
) < length
2346 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2347 flog_err(EC_BGP_ATTR_LEN
,
2348 "Prefix SID label index length is %" PRIu16
2350 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2351 return bgp_attr_malformed(args
,
2352 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2356 /* Ignore flags and reserved */
2357 stream_getc(peer
->curr
);
2358 stream_getw(peer
->curr
);
2360 /* Fetch the label index and see if it is valid. */
2361 label_index
= stream_getl(peer
->curr
);
2362 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2363 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2366 /* Store label index; subsequently, we'll check on
2368 attr
->label_index
= label_index
;
2371 * Ignore the Label index attribute unless received for
2375 if (!mp_update
->length
2376 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2377 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2380 /* Placeholder code for the IPv6 SID type */
2381 else if (type
== BGP_PREFIX_SID_IPV6
) {
2382 if (STREAM_READABLE(peer
->curr
) < length
2383 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2384 flog_err(EC_BGP_ATTR_LEN
,
2385 "Prefix SID IPv6 length is %" PRIu16
2387 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2388 return bgp_attr_malformed(args
,
2389 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2393 /* Ignore reserved */
2394 stream_getc(peer
->curr
);
2395 stream_getw(peer
->curr
);
2397 stream_get(&ipv6_sid
, peer
->curr
, 16);
2400 /* Placeholder code for the Originator SRGB type */
2401 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2403 * ietf-idr-bgp-prefix-sid-05:
2404 * Length is the total length of the value portion of the
2405 * TLV: 2 + multiple of 6.
2407 * peer->curr stream readp should be at the beginning of the 16
2408 * bit flag field at this point in the code.
2412 * Check that the TLV length field is sane: at least 2 bytes of
2413 * flag, and at least 1 SRGB (these are 6 bytes each)
2415 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2418 "Prefix SID Originator SRGB length field claims length of %" PRIu16
" bytes, but the minimum for this TLV type is %u",
2420 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2421 return bgp_attr_malformed(
2422 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2427 * Check that we actually have at least as much data as
2428 * specified by the length field
2430 if (STREAM_READABLE(peer
->curr
) < length
) {
2431 flog_err(EC_BGP_ATTR_LEN
,
2432 "Prefix SID Originator SRGB specifies length %" PRIu16
", but only %zu bytes remain",
2433 length
, STREAM_READABLE(peer
->curr
));
2434 return bgp_attr_malformed(
2435 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2440 * Check that the portion of the TLV containing the sequence of
2441 * SRGBs corresponds to a multiple of the SRGB size; to get
2442 * that length, we skip the 16 bit flags field
2444 stream_getw(peer
->curr
);
2446 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2449 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %" PRIu16
"bytes, but it must be a multiple of %u",
2450 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2451 return bgp_attr_malformed(
2452 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2456 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2458 for (int i
= 0; i
< srgb_count
; i
++) {
2459 stream_get(&srgb_base
, peer
->curr
, 3);
2460 stream_get(&srgb_range
, peer
->curr
, 3);
2464 /* Placeholder code for the VPN-SID Service type */
2465 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2466 if (STREAM_READABLE(peer
->curr
) < length
2467 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2468 flog_err(EC_BGP_ATTR_LEN
,
2469 "Prefix SID VPN SID length is %" PRIu16
2471 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2472 return bgp_attr_malformed(args
,
2473 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2477 /* Parse VPN-SID Sub-TLV */
2478 stream_getc(peer
->curr
); /* reserved */
2479 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2480 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2481 stream_get(&ipv6_sid
, peer
->curr
,
2482 sizeof(ipv6_sid
)); /* sid_value */
2484 /* Log VPN-SID Sub-TLV */
2485 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2486 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2488 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2489 __func__
, buf
, sid_type
, sid_flags
);
2492 /* Configure from Info */
2493 attr
->srv6_vpn
= XMALLOC(MTYPE_BGP_SRV6_VPN
,
2494 sizeof(struct bgp_attr_srv6_vpn
));
2495 attr
->srv6_vpn
->refcnt
= 0;
2496 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2497 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2500 /* Placeholder code for the SRv6 L3 Service type */
2501 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2502 if (STREAM_READABLE(peer
->curr
) < length
2503 || length
!= BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
) {
2504 flog_err(EC_BGP_ATTR_LEN
,
2505 "Prefix SID SRv6 L3-Service length is %" PRIu16
2507 length
, BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
);
2508 return bgp_attr_malformed(args
,
2509 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2513 /* Parse L3-SERVICE Sub-TLV */
2514 stream_getc(peer
->curr
); /* reserved */
2515 stream_get(&ipv6_sid
, peer
->curr
,
2516 sizeof(ipv6_sid
)); /* sid_value */
2517 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2518 endpoint_behavior
= stream_getw(peer
->curr
); /* endpoint */
2519 stream_getc(peer
->curr
); /* reserved */
2521 /* Log L3-SERVICE Sub-TLV */
2522 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2523 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2525 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2526 __func__
, buf
, sid_flags
, endpoint_behavior
);
2529 /* Configure from Info */
2530 attr
->srv6_l3vpn
= XMALLOC(MTYPE_BGP_SRV6_L3VPN
,
2531 sizeof(struct bgp_attr_srv6_l3vpn
));
2532 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2533 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2534 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2537 /* Placeholder code for Unsupported TLV */
2540 if (STREAM_READABLE(peer
->curr
) < length
) {
2543 "Prefix SID SRv6 length is %" PRIu16
2544 " - too long, only %zu remaining in this UPDATE",
2545 length
, STREAM_READABLE(peer
->curr
));
2546 return bgp_attr_malformed(
2547 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2551 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2553 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2556 stream_forward_getp(peer
->curr
, length
);
2559 return BGP_ATTR_PARSE_PROCEED
;
2562 /* Prefix SID attribute
2563 * draft-ietf-idr-bgp-prefix-sid-05
2565 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
,
2566 struct bgp_nlri
*mp_update
)
2568 struct peer
*const peer
= args
->peer
;
2569 struct attr
*const attr
= args
->attr
;
2570 bgp_attr_parse_ret_t ret
;
2572 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2576 size_t headersz
= sizeof(type
) + sizeof(length
);
2578 while (STREAM_READABLE(peer
->curr
) > 0) {
2580 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2583 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2584 headersz
, STREAM_READABLE(peer
->curr
));
2585 return bgp_attr_malformed(
2586 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2590 type
= stream_getc(peer
->curr
);
2591 length
= stream_getw(peer
->curr
);
2593 if (STREAM_READABLE(peer
->curr
) < length
) {
2596 "Malformed Prefix SID attribute - insufficient data (need %" PRIu8
2597 " for attribute body, have %zu remaining in UPDATE)",
2598 length
, STREAM_READABLE(peer
->curr
));
2599 return bgp_attr_malformed(args
,
2600 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2604 ret
= bgp_attr_psid_sub(type
, length
, args
, mp_update
);
2606 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2610 return BGP_ATTR_PARSE_PROCEED
;
2613 /* PMSI tunnel attribute (RFC 6514)
2614 * Basic validation checks done here.
2616 static bgp_attr_parse_ret_t
2617 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2619 struct peer
*const peer
= args
->peer
;
2620 struct attr
*const attr
= args
->attr
;
2621 const bgp_size_t length
= args
->length
;
2623 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2625 /* Verify that the receiver is expecting "ingress replication" as we
2626 * can only support that.
2628 if (length
< attr_parse_len
) {
2629 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2631 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2634 stream_getc(peer
->curr
); /* Flags */
2635 tnl_type
= stream_getc(peer
->curr
);
2636 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2637 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2638 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2639 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2642 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2644 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2645 "Bad PMSI tunnel attribute length %d for IR",
2647 return bgp_attr_malformed(
2648 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2653 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2654 attr
->pmsi_tnl_type
= tnl_type
;
2655 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2657 /* Forward read pointer of input stream. */
2658 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2660 return BGP_ATTR_PARSE_PROCEED
;
2663 /* BGP unknown attribute treatment. */
2664 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2666 bgp_size_t total
= args
->total
;
2667 struct transit
*transit
;
2668 struct peer
*const peer
= args
->peer
;
2669 struct attr
*const attr
= args
->attr
;
2670 uint8_t *const startp
= args
->startp
;
2671 const uint8_t type
= args
->type
;
2672 const uint8_t flag
= args
->flags
;
2673 const bgp_size_t length
= args
->length
;
2675 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2677 "%s Unknown attribute is received (type %d, length %d)",
2678 peer
->host
, type
, length
);
2680 /* Forward read pointer of input stream. */
2681 stream_forward_getp(peer
->curr
, length
);
2683 /* If any of the mandatory well-known attributes are not recognized,
2684 then the Error Subcode is set to Unrecognized Well-known
2685 Attribute. The Data field contains the unrecognized attribute
2686 (type, length and value). */
2687 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2688 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2692 /* Unrecognized non-transitive optional attributes must be quietly
2693 ignored and not passed along to other BGP peers. */
2694 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2695 return BGP_ATTR_PARSE_PROCEED
;
2697 /* If a path with recognized transitive optional attribute is
2698 accepted and passed along to other BGP peers and the Partial bit
2699 in the Attribute Flags octet is set to 1 by some previous AS, it
2700 is not set back to 0 by the current AS. */
2701 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2703 /* Store transitive attribute to the end of attr->transit. */
2705 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2707 transit
= attr
->transit
;
2710 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2711 transit
->length
+ total
);
2713 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2715 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2716 transit
->length
+= total
;
2718 return BGP_ATTR_PARSE_PROCEED
;
2721 /* Well-known attribute check. */
2722 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2726 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2728 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2729 return BGP_ATTR_PARSE_PROCEED
;
2731 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2732 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2733 are present, it should. Check for any other attribute being present
2736 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2737 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2738 return BGP_ATTR_PARSE_PROCEED
;
2740 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2741 type
= BGP_ATTR_ORIGIN
;
2743 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2744 type
= BGP_ATTR_AS_PATH
;
2746 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2748 * NLRI is empty. We can't easily check NLRI empty here though.
2750 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2751 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2752 type
= BGP_ATTR_NEXT_HOP
;
2754 if (peer
->sort
== BGP_PEER_IBGP
2755 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2756 type
= BGP_ATTR_LOCAL_PREF
;
2759 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2760 "%s Missing well-known attribute %s.", peer
->host
,
2761 lookup_msg(attr_str
, type
, NULL
));
2762 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2763 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2765 return BGP_ATTR_PARSE_ERROR
;
2767 return BGP_ATTR_PARSE_PROCEED
;
2770 /* Read attribute of update packet. This function is called from
2771 bgp_update_receive() in bgp_packet.c. */
2772 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2773 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2774 struct bgp_nlri
*mp_withdraw
)
2776 bgp_attr_parse_ret_t ret
;
2780 uint8_t *startp
, *endp
;
2782 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2783 /* we need the as4_path only until we have synthesized the as_path with
2785 /* same goes for as4_aggregator */
2786 struct aspath
*as4_path
= NULL
;
2787 as_t as4_aggregator
= 0;
2788 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2790 /* Initialize bitmap. */
2791 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2793 /* End pointer of BGP attribute. */
2794 endp
= BGP_INPUT_PNT(peer
) + size
;
2796 /* Get attributes to the end of attribute length. */
2797 while (BGP_INPUT_PNT(peer
) < endp
) {
2798 /* Check remaining length check.*/
2799 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2800 /* XXX warning: long int format, int arg (arg 5) */
2802 EC_BGP_ATTRIBUTE_TOO_SMALL
,
2803 "%s: error BGP attribute length %lu is smaller than min len",
2805 (unsigned long)(endp
2806 - stream_pnt(BGP_INPUT(peer
))));
2808 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2809 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2810 ret
= BGP_ATTR_PARSE_ERROR
;
2814 /* Fetch attribute flag and type. */
2815 startp
= BGP_INPUT_PNT(peer
);
2816 /* "The lower-order four bits of the Attribute Flags octet are
2817 unused. They MUST be zero when sent and MUST be ignored when
2819 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2820 type
= stream_getc(BGP_INPUT(peer
));
2822 /* Check whether Extended-Length applies and is in bounds */
2823 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2824 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2826 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
2827 "%s: Extended length set, but just %lu bytes of attr header",
2829 (unsigned long)(endp
2830 - stream_pnt(BGP_INPUT(peer
))));
2832 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2833 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2834 ret
= BGP_ATTR_PARSE_ERROR
;
2838 /* Check extended attribue length bit. */
2839 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2840 length
= stream_getw(BGP_INPUT(peer
));
2842 length
= stream_getc(BGP_INPUT(peer
));
2844 /* If any attribute appears more than once in the UPDATE
2845 message, then the Error Subcode is set to Malformed Attribute
2848 if (CHECK_BITMAP(seen
, type
)) {
2850 EC_BGP_ATTRIBUTE_REPEATED
,
2851 "%s: error BGP attribute type %d appears twice in a message",
2854 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2855 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2856 ret
= BGP_ATTR_PARSE_ERROR
;
2860 /* Set type to bitmap to check duplicate attribute. `type' is
2861 unsigned char so it never overflow bitmap range. */
2863 SET_BITMAP(seen
, type
);
2865 /* Overflow check. */
2866 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2868 if (attr_endp
> endp
) {
2870 EC_BGP_ATTRIBUTE_TOO_LARGE
,
2871 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2872 peer
->host
, type
, length
, size
, attr_endp
,
2876 * If any recognized attribute has an Attribute
2877 * Length that conflicts with the expected length
2878 * (based on the attribute type code), then the
2879 * Error Subcode MUST be set to Attribute Length
2880 * Error. The Data field MUST contain the erroneous
2881 * attribute (type, length, and value).
2883 * We do not currently have a good way to determine the
2884 * length of the attribute independent of the length
2885 * received in the message. Instead we send the
2886 * minimum between the amount of data we have and the
2887 * amount specified by the attribute length field.
2889 * Instead of directly passing in the packet buffer and
2890 * offset we use the stream_get* functions to read into
2891 * a stack buffer, since they perform bounds checking
2892 * and we are working with untrusted data.
2894 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
2895 memset(ndata
, 0x00, sizeof(ndata
));
2897 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
2898 /* Rewind to end of flag field */
2899 stream_forward_getp(BGP_INPUT(peer
), -(1 + lfl
));
2901 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
2903 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
2905 size_t atl
= attr_endp
- startp
;
2906 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
2907 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
2909 bgp_notify_send_with_data(
2910 peer
, BGP_NOTIFY_UPDATE_ERR
,
2911 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
2914 ret
= BGP_ATTR_PARSE_ERROR
;
2918 struct bgp_attr_parser_args attr_args
= {
2925 .total
= attr_endp
- startp
,
2929 /* If any recognized attribute has Attribute Flags that conflict
2930 with the Attribute Type Code, then the Error Subcode is set
2932 Attribute Flags Error. The Data field contains the erroneous
2933 attribute (type, length and value). */
2934 if (bgp_attr_flag_invalid(&attr_args
)) {
2935 ret
= bgp_attr_malformed(
2936 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2938 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2943 /* OK check attribute and store it's value. */
2945 case BGP_ATTR_ORIGIN
:
2946 ret
= bgp_attr_origin(&attr_args
);
2948 case BGP_ATTR_AS_PATH
:
2949 ret
= bgp_attr_aspath(&attr_args
);
2951 case BGP_ATTR_AS4_PATH
:
2952 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2954 case BGP_ATTR_NEXT_HOP
:
2955 ret
= bgp_attr_nexthop(&attr_args
);
2957 case BGP_ATTR_MULTI_EXIT_DISC
:
2958 ret
= bgp_attr_med(&attr_args
);
2960 case BGP_ATTR_LOCAL_PREF
:
2961 ret
= bgp_attr_local_pref(&attr_args
);
2963 case BGP_ATTR_ATOMIC_AGGREGATE
:
2964 ret
= bgp_attr_atomic(&attr_args
);
2966 case BGP_ATTR_AGGREGATOR
:
2967 ret
= bgp_attr_aggregator(&attr_args
);
2969 case BGP_ATTR_AS4_AGGREGATOR
:
2970 ret
= bgp_attr_as4_aggregator(&attr_args
,
2972 &as4_aggregator_addr
);
2974 case BGP_ATTR_COMMUNITIES
:
2975 ret
= bgp_attr_community(&attr_args
);
2977 case BGP_ATTR_LARGE_COMMUNITIES
:
2978 ret
= bgp_attr_large_community(&attr_args
);
2980 case BGP_ATTR_ORIGINATOR_ID
:
2981 ret
= bgp_attr_originator_id(&attr_args
);
2983 case BGP_ATTR_CLUSTER_LIST
:
2984 ret
= bgp_attr_cluster_list(&attr_args
);
2986 case BGP_ATTR_MP_REACH_NLRI
:
2987 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2989 case BGP_ATTR_MP_UNREACH_NLRI
:
2990 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2992 case BGP_ATTR_EXT_COMMUNITIES
:
2993 ret
= bgp_attr_ext_communities(&attr_args
);
2995 #if ENABLE_BGP_VNC_ATTR
2998 case BGP_ATTR_ENCAP
:
2999 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3002 case BGP_ATTR_PREFIX_SID
:
3003 ret
= bgp_attr_prefix_sid(&attr_args
, mp_update
);
3005 case BGP_ATTR_PMSI_TUNNEL
:
3006 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3009 ret
= bgp_attr_unknown(&attr_args
);
3013 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3014 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3015 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3016 ret
= BGP_ATTR_PARSE_ERROR
;
3020 if (ret
== BGP_ATTR_PARSE_EOR
) {
3024 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3025 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3026 "%s: Attribute %s, parse error", peer
->host
,
3027 lookup_msg(attr_str
, type
, NULL
));
3030 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3032 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3033 "%s: Attribute %s, parse error - treating as withdrawal",
3034 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3038 /* Check the fetched length. */
3039 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3040 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3041 "%s: BGP attribute %s, fetch error",
3042 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3043 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3044 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3045 ret
= BGP_ATTR_PARSE_ERROR
;
3050 /* Check final read pointer is same as end pointer. */
3051 if (BGP_INPUT_PNT(peer
) != endp
) {
3052 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3053 "%s: BGP attribute %s, length mismatch", peer
->host
,
3054 lookup_msg(attr_str
, type
, NULL
));
3055 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3056 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3058 ret
= BGP_ATTR_PARSE_ERROR
;
3063 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3064 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3065 * This is implemented below and will result in a NOTIFICATION. If the
3066 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3067 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3068 * message SHOULD NOT be sent. This is implemented elsewhere.
3070 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3071 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3072 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3073 * speaker that receives the message SHOULD ignore this attribute.
3075 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3076 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3077 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3078 ret
= BGP_ATTR_PARSE_ERROR
;
3083 /* Check all mandatory well-known attributes are present */
3084 if ((ret
= bgp_attr_check(peer
, attr
)) < 0)
3088 * At this place we can see whether we got AS4_PATH and/or
3089 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3090 * We can not do this before we've read all attributes because
3091 * the as4 handling does not say whether AS4_PATH has to be sent
3092 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3093 * in relationship to AGGREGATOR.
3094 * So, to be defensive, we are not relying on any order and read
3095 * all attributes first, including these 32bit ones, and now,
3096 * afterwards, we look what and if something is to be done for as4.
3098 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3101 /* actually... this doesn't ever return failure currently, but
3102 * better safe than sorry */
3103 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3104 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3105 &as4_aggregator_addr
)) {
3106 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3107 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3108 ret
= BGP_ATTR_PARSE_ERROR
;
3113 * Finally do the checks on the aspath we did not do yet
3114 * because we waited for a potentially synthesized aspath.
3116 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3117 ret
= bgp_attr_aspath_check(peer
, attr
);
3118 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3122 ret
= BGP_ATTR_PARSE_PROCEED
;
3126 * At this stage, we have done all fiddling with as4, and the
3127 * resulting info is in attr->aggregator resp. attr->aspath so
3128 * we can chuck as4_aggregator and as4_path alltogether in order
3133 * unintern - it is in the hash
3134 * The flag that we got this is still there, but that
3135 * does not do any trouble
3137 aspath_unintern(&as4_path
);
3140 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3141 /* Finally intern unknown attribute. */
3143 attr
->transit
= transit_intern(attr
->transit
);
3144 if (attr
->encap_subtlvs
)
3145 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3148 if (attr
->vnc_subtlvs
)
3149 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
3153 if (attr
->transit
) {
3154 transit_free(attr
->transit
);
3155 attr
->transit
= NULL
;
3158 bgp_attr_flush_encap(attr
);
3163 assert(attr
->transit
->refcnt
> 0);
3164 if (attr
->encap_subtlvs
)
3165 assert(attr
->encap_subtlvs
->refcnt
> 0);
3167 if (attr
->vnc_subtlvs
)
3168 assert(attr
->vnc_subtlvs
->refcnt
> 0);
3175 * Extract the tunnel type from extended community
3177 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3178 bgp_encap_types
*tunnel_type
)
3180 struct ecommunity
*ecom
;
3185 ecom
= attr
->ecommunity
;
3186 if (!ecom
|| !ecom
->size
)
3189 for (i
= 0; i
< ecom
->size
; i
++) {
3191 uint8_t type
, sub_type
;
3193 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3196 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3197 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3199 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3206 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3207 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3212 iana_safi_t pkt_safi
;
3215 /* Set extended bit always to encode the attribute length as 2 bytes */
3216 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3217 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3218 sizep
= stream_get_endp(s
);
3219 stream_putw(s
, 0); /* Marker: Attribute length. */
3222 /* Convert AFI, SAFI to values for packet. */
3223 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3225 stream_putw(s
, pkt_afi
); /* AFI */
3226 stream_putc(s
, pkt_safi
); /* SAFI */
3230 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3231 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3232 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3233 else if (safi
== SAFI_FLOWSPEC
)
3236 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3239 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3244 case SAFI_MULTICAST
:
3245 case SAFI_LABELED_UNICAST
:
3247 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3251 stream_putl(s
, 0); /* RD = 0, per RFC */
3253 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3258 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3261 if (attr
->mp_nexthop_len
== 0)
3262 stream_putc(s
, 0); /* no nexthop for flowspec */
3264 stream_putc(s
, attr
->mp_nexthop_len
);
3265 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3274 case SAFI_MULTICAST
:
3275 case SAFI_LABELED_UNICAST
:
3277 if (attr
->mp_nexthop_len
3278 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3280 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3281 stream_put(s
, &attr
->mp_nexthop_global
,
3283 stream_put(s
, &attr
->mp_nexthop_local
,
3286 stream_putc(s
, IPV6_MAX_BYTELEN
);
3287 stream_put(s
, &attr
->mp_nexthop_global
,
3291 case SAFI_MPLS_VPN
: {
3292 if (attr
->mp_nexthop_len
3293 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3295 stream_putl(s
, 0); /* RD = 0, per RFC */
3297 stream_put(s
, &attr
->mp_nexthop_global
,
3299 } else if (attr
->mp_nexthop_len
3300 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3302 stream_putl(s
, 0); /* RD = 0, per RFC */
3304 stream_put(s
, &attr
->mp_nexthop_global
,
3306 stream_putl(s
, 0); /* RD = 0, per RFC */
3308 stream_put(s
, &attr
->mp_nexthop_local
,
3313 stream_putc(s
, IPV6_MAX_BYTELEN
);
3314 stream_put(s
, &attr
->mp_nexthop_global
,
3318 stream_putc(s
, 0); /* no nexthop for flowspec */
3324 if (safi
!= SAFI_FLOWSPEC
)
3326 EC_BGP_ATTR_NH_SEND_LEN
,
3327 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3328 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3337 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3338 struct prefix
*p
, struct prefix_rd
*prd
,
3339 mpls_label_t
*label
, uint32_t num_labels
,
3340 int addpath_encode
, uint32_t addpath_tx_id
,
3343 if (safi
== SAFI_MPLS_VPN
) {
3345 stream_putl(s
, addpath_tx_id
);
3346 /* Label, RD, Prefix write. */
3347 stream_putc(s
, p
->prefixlen
+ 88);
3348 stream_put(s
, label
, BGP_LABEL_BYTES
);
3349 stream_put(s
, prd
->val
, 8);
3350 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3351 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3352 /* EVPN prefix - contents depend on type */
3353 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3354 addpath_encode
, addpath_tx_id
);
3355 } else if (safi
== SAFI_LABELED_UNICAST
) {
3356 /* Prefix write with label. */
3357 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3359 } else if (safi
== SAFI_FLOWSPEC
) {
3360 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3361 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3362 p
->u
.prefix_flowspec
.prefixlen
);
3364 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3367 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
3369 int size
= PSIZE(p
->prefixlen
);
3370 if (safi
== SAFI_MPLS_VPN
)
3372 else if (safi
== SAFI_LABELED_UNICAST
)
3373 size
+= BGP_LABEL_BYTES
;
3374 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3375 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3381 * Encodes the tunnel encapsulation attribute,
3382 * and with ENABLE_BGP_VNC the VNC attribute which uses
3383 * almost the same TLV format
3385 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3386 struct stream
*s
, struct attr
*attr
,
3389 unsigned int attrlenfield
= 0;
3390 unsigned int attrhdrlen
= 0;
3391 struct bgp_attr_encap_subtlv
*subtlvs
;
3392 struct bgp_attr_encap_subtlv
*st
;
3393 const char *attrname
;
3395 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3396 && (!attr
->encap_tunneltype
3397 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3401 case BGP_ATTR_ENCAP
:
3402 attrname
= "Tunnel Encap";
3403 subtlvs
= attr
->encap_subtlvs
;
3404 if (subtlvs
== NULL
) /* nothing to do */
3407 * The tunnel encap attr has an "outer" tlv.
3409 * L = total length of subtlvs,
3410 * V = concatenated subtlvs.
3412 attrlenfield
= 2 + 2; /* T + L */
3413 attrhdrlen
= 1 + 1; /* subTLV T + L */
3416 #if ENABLE_BGP_VNC_ATTR
3419 subtlvs
= attr
->vnc_subtlvs
;
3420 if (subtlvs
== NULL
) /* nothing to do */
3422 attrlenfield
= 0; /* no outer T + L */
3423 attrhdrlen
= 2 + 2; /* subTLV T + L */
3431 /* compute attr length */
3432 for (st
= subtlvs
; st
; st
= st
->next
) {
3433 attrlenfield
+= (attrhdrlen
+ st
->length
);
3436 if (attrlenfield
> 0xffff) {
3437 zlog_info("%s attribute is too long (length=%d), can't send it",
3438 attrname
, attrlenfield
);
3442 if (attrlenfield
> 0xff) {
3443 /* 2-octet length field */
3445 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3446 | BGP_ATTR_FLAG_EXTLEN
);
3447 stream_putc(s
, attrtype
);
3448 stream_putw(s
, attrlenfield
& 0xffff);
3450 /* 1-octet length field */
3451 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3452 stream_putc(s
, attrtype
);
3453 stream_putc(s
, attrlenfield
& 0xff);
3456 if (attrtype
== BGP_ATTR_ENCAP
) {
3457 /* write outer T+L */
3458 stream_putw(s
, attr
->encap_tunneltype
);
3459 stream_putw(s
, attrlenfield
- 4);
3462 /* write each sub-tlv */
3463 for (st
= subtlvs
; st
; st
= st
->next
) {
3464 if (attrtype
== BGP_ATTR_ENCAP
) {
3465 stream_putc(s
, st
->type
);
3466 stream_putc(s
, st
->length
);
3469 stream_putw(s
, st
->type
);
3470 stream_putw(s
, st
->length
);
3473 stream_put(s
, st
->value
, st
->length
);
3477 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3479 /* Set MP attribute length. Don't count the (2) bytes used to encode
3481 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3484 static int bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3486 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3487 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3488 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3489 PEER_FLAG_REMOVE_PRIVATE_AS
)
3490 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3491 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3492 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3493 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3494 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3495 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3500 /* Make attribute packet. */
3501 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3502 struct stream
*s
, struct attr
*attr
,
3503 struct bpacket_attr_vec_arr
*vecarr
,
3504 struct prefix
*p
, afi_t afi
, safi_t safi
,
3505 struct peer
*from
, struct prefix_rd
*prd
,
3506 mpls_label_t
*label
, uint32_t num_labels
,
3507 int addpath_encode
, uint32_t addpath_tx_id
)
3510 size_t aspath_sizep
;
3511 struct aspath
*aspath
;
3512 int send_as4_path
= 0;
3513 int send_as4_aggregator
= 0;
3514 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3519 /* Remember current pointer. */
3520 cp
= stream_get_endp(s
);
3523 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3524 && !peer_cap_enhe(peer
, afi
, safi
))) {
3525 size_t mpattrlen_pos
= 0;
3527 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3529 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3530 num_labels
, addpath_encode
,
3531 addpath_tx_id
, attr
);
3532 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3535 /* Origin attribute. */
3536 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3537 stream_putc(s
, BGP_ATTR_ORIGIN
);
3539 stream_putc(s
, attr
->origin
);
3541 /* AS path attribute. */
3543 /* If remote-peer is EBGP */
3544 if (peer
->sort
== BGP_PEER_EBGP
3545 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3546 PEER_FLAG_AS_PATH_UNCHANGED
)
3547 || attr
->aspath
->segments
== NULL
)
3548 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3549 PEER_FLAG_RSERVER_CLIENT
))) {
3550 aspath
= aspath_dup(attr
->aspath
);
3552 /* Even though we may not be configured for confederations we
3554 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3555 aspath
= aspath_delete_confed_seq(aspath
);
3557 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3558 /* Stuff our path CONFED_ID on the front */
3559 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3561 if (peer
->change_local_as
) {
3562 /* If replace-as is specified, we only use the
3563 change_local_as when
3564 advertising routes. */
3565 if (!CHECK_FLAG(peer
->flags
,
3566 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3567 if (bgp_append_local_as(peer
, afi
,
3569 aspath
= aspath_add_seq(
3570 aspath
, peer
->local_as
);
3571 aspath
= aspath_add_seq(aspath
,
3572 peer
->change_local_as
);
3574 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3577 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3578 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3580 aspath
= aspath_dup(attr
->aspath
);
3581 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3583 aspath
= attr
->aspath
;
3585 /* If peer is not AS4 capable, then:
3586 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3587 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3589 * types are in it (i.e. exclude them if they are there)
3590 * AND do this only if there is at least one asnum > 65535 in the
3592 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3594 * all ASnums > 65535 to BGP_AS_TRANS
3597 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3598 stream_putc(s
, BGP_ATTR_AS_PATH
);
3599 aspath_sizep
= stream_get_endp(s
);
3601 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3603 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3606 if (!use32bit
&& aspath_has_as4(aspath
))
3608 1; /* we'll do this later, at the correct place */
3610 /* Nexthop attribute. */
3611 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3612 && !peer_cap_enhe(peer
, afi
, safi
)) {
3613 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3615 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3616 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3617 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3618 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3621 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3622 } else if (peer_cap_enhe(from
, afi
, safi
)
3623 || (nh_afi
== AFI_IP6
)) {
3625 * Likely this is the case when an IPv4 prefix was
3626 * received with Extended Next-hop capability in this
3627 * or another vrf and is now being advertised to
3628 * non-ENHE peers. Since peer_cap_enhe only checks
3629 * peers in this vrf, also check the nh_afi to catch
3630 * the case where the originator was in another vrf.
3631 * Setting the mandatory (ipv4) next-hop attribute here
3632 * to enable implicit next-hop self with correct A-F
3633 * (ipv4 address family).
3635 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3636 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3637 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3640 stream_put_ipv4(s
, 0);
3644 /* MED attribute. */
3645 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3646 || bgp
->maxmed_active
) {
3647 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3648 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3650 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3654 /* Local preference. */
3655 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3656 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3657 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3659 stream_putl(s
, attr
->local_pref
);
3662 /* Atomic aggregate. */
3663 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3664 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3665 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3670 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3671 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3672 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3673 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3676 /* AS4 capable peer */
3678 stream_putl(s
, attr
->aggregator_as
);
3680 /* 2-byte AS peer */
3683 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3685 if (attr
->aggregator_as
> 65535) {
3686 stream_putw(s
, BGP_AS_TRANS
);
3688 /* we have to send AS4_AGGREGATOR, too.
3689 * we'll do that later in order to send
3690 * attributes in ascending
3693 send_as4_aggregator
= 1;
3695 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3697 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3700 /* Community attribute. */
3701 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3702 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3703 if (attr
->community
->size
* 4 > 255) {
3705 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3706 | BGP_ATTR_FLAG_EXTLEN
);
3707 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3708 stream_putw(s
, attr
->community
->size
* 4);
3711 BGP_ATTR_FLAG_OPTIONAL
3712 | BGP_ATTR_FLAG_TRANS
);
3713 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3714 stream_putc(s
, attr
->community
->size
* 4);
3716 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3720 * Large Community attribute.
3722 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3723 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3724 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3725 if (lcom_length(attr
->lcommunity
) > 255) {
3727 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3728 | BGP_ATTR_FLAG_EXTLEN
);
3729 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3730 stream_putw(s
, lcom_length(attr
->lcommunity
));
3733 BGP_ATTR_FLAG_OPTIONAL
3734 | BGP_ATTR_FLAG_TRANS
);
3735 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3736 stream_putc(s
, lcom_length(attr
->lcommunity
));
3738 stream_put(s
, attr
->lcommunity
->val
,
3739 lcom_length(attr
->lcommunity
));
3742 /* Route Reflector. */
3743 if (peer
->sort
== BGP_PEER_IBGP
&& from
3744 && from
->sort
== BGP_PEER_IBGP
) {
3745 /* Originator ID. */
3746 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3747 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3750 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3751 stream_put_in_addr(s
, &attr
->originator_id
);
3753 stream_put_in_addr(s
, &from
->remote_id
);
3756 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3757 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3759 if (attr
->cluster
) {
3760 stream_putc(s
, attr
->cluster
->length
+ 4);
3761 /* If this peer configuration's parent BGP has
3763 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3764 stream_put_in_addr(s
, &bgp
->cluster_id
);
3766 stream_put_in_addr(s
, &bgp
->router_id
);
3767 stream_put(s
, attr
->cluster
->list
,
3768 attr
->cluster
->length
);
3771 /* If this peer configuration's parent BGP has
3773 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3774 stream_put_in_addr(s
, &bgp
->cluster_id
);
3776 stream_put_in_addr(s
, &bgp
->router_id
);
3780 /* Extended Communities attribute. */
3781 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3782 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3783 if (peer
->sort
== BGP_PEER_IBGP
3784 || peer
->sort
== BGP_PEER_CONFED
) {
3785 if (attr
->ecommunity
->size
* 8 > 255) {
3787 BGP_ATTR_FLAG_OPTIONAL
3788 | BGP_ATTR_FLAG_TRANS
3789 | BGP_ATTR_FLAG_EXTLEN
);
3790 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3791 stream_putw(s
, attr
->ecommunity
->size
* 8);
3794 BGP_ATTR_FLAG_OPTIONAL
3795 | BGP_ATTR_FLAG_TRANS
);
3796 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3797 stream_putc(s
, attr
->ecommunity
->size
* 8);
3799 stream_put(s
, attr
->ecommunity
->val
,
3800 attr
->ecommunity
->size
* 8);
3804 int ecom_tr_size
= 0;
3807 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3808 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3811 if (CHECK_FLAG(tbit
,
3812 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3819 if (ecom_tr_size
* 8 > 255) {
3822 BGP_ATTR_FLAG_OPTIONAL
3823 | BGP_ATTR_FLAG_TRANS
3824 | BGP_ATTR_FLAG_EXTLEN
);
3826 BGP_ATTR_EXT_COMMUNITIES
);
3827 stream_putw(s
, ecom_tr_size
* 8);
3831 BGP_ATTR_FLAG_OPTIONAL
3832 | BGP_ATTR_FLAG_TRANS
);
3834 BGP_ATTR_EXT_COMMUNITIES
);
3835 stream_putc(s
, ecom_tr_size
* 8);
3838 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3839 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3844 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3847 stream_put(s
, pnt
, 8);
3853 /* Label index attribute. */
3854 if (safi
== SAFI_LABELED_UNICAST
) {
3855 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3856 uint32_t label_index
;
3858 label_index
= attr
->label_index
;
3860 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3862 BGP_ATTR_FLAG_OPTIONAL
3863 | BGP_ATTR_FLAG_TRANS
);
3864 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3866 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3868 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3869 stream_putc(s
, 0); // reserved
3870 stream_putw(s
, 0); // flags
3871 stream_putl(s
, label_index
);
3876 /* SRv6 Service Information Attribute. */
3877 if (afi
== AFI_IP
&& safi
== SAFI_MPLS_VPN
) {
3878 if (attr
->srv6_l3vpn
) {
3879 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
3880 | BGP_ATTR_FLAG_TRANS
);
3881 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3882 stream_putc(s
, 24); /* tlv len */
3883 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
3884 stream_putw(s
, 21); /* sub-tlv len */
3885 stream_putc(s
, 0); /* reserved */
3886 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
3887 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
3888 stream_putc(s
, 0); /* sid_flags */
3889 stream_putw(s
, 0xffff); /* endpoint */
3890 stream_putc(s
, 0); /* reserved */
3891 } else if (attr
->srv6_vpn
) {
3892 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
3893 | BGP_ATTR_FLAG_TRANS
);
3894 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3895 stream_putc(s
, 22); /* tlv len */
3896 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
3897 stream_putw(s
, 0x13); /* tlv len */
3898 stream_putc(s
, 0x00); /* reserved */
3899 stream_putc(s
, 0x01); /* sid_type */
3900 stream_putc(s
, 0x00); /* sif_flags */
3901 stream_put(s
, &attr
->srv6_vpn
->sid
,
3902 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
3906 if (send_as4_path
) {
3907 /* If the peer is NOT As4 capable, AND */
3908 /* there are ASnums > 65535 in path THEN
3909 * give out AS4_PATH */
3911 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3913 * Hm, I wonder... confederation things *should* only be at
3914 * the beginning of an aspath, right? Then we should use
3915 * aspath_delete_confed_seq for this, because it is already
3917 * Folks, talk to me: what is reasonable here!?
3919 aspath
= aspath_delete_confed_seq(aspath
);
3922 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3923 | BGP_ATTR_FLAG_EXTLEN
);
3924 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3925 aspath_sizep
= stream_get_endp(s
);
3927 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3930 if (aspath
!= attr
->aspath
)
3931 aspath_free(aspath
);
3933 if (send_as4_aggregator
) {
3934 /* send AS4_AGGREGATOR, at this place */
3935 /* this section of code moved here in order to ensure the
3937 * *ascending* order of attributes
3939 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3940 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3942 stream_putl(s
, attr
->aggregator_as
);
3943 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3946 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3947 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3948 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3949 /* Tunnel Encap attribute */
3950 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3952 #if ENABLE_BGP_VNC_ATTR
3954 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3959 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
3960 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3961 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
3962 stream_putc(s
, 9); // Length
3963 stream_putc(s
, 0); // Flags
3964 stream_putc(s
, attr
->pmsi_tnl_type
);
3965 stream_put(s
, &(attr
->label
),
3966 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
3967 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3968 // Unicast tunnel endpoint IP address
3971 /* Unknown transit attribute. */
3973 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
3975 /* Return total size of attribute. */
3976 return stream_get_endp(s
) - cp
;
3979 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3981 unsigned long attrlen_pnt
;
3983 iana_safi_t pkt_safi
;
3985 /* Set extended bit always to encode the attribute length as 2 bytes */
3986 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3987 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3989 attrlen_pnt
= stream_get_endp(s
);
3990 stream_putw(s
, 0); /* Length of this attribute. */
3992 /* Convert AFI, SAFI to values for packet. */
3993 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3995 stream_putw(s
, pkt_afi
);
3996 stream_putc(s
, pkt_safi
);
4001 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
4002 safi_t safi
, struct prefix_rd
*prd
,
4003 mpls_label_t
*label
, uint32_t num_labels
,
4004 int addpath_encode
, uint32_t addpath_tx_id
,
4007 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4009 if (safi
== SAFI_LABELED_UNICAST
) {
4010 label
= (mpls_label_t
*)wlabel
;
4014 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4015 addpath_encode
, addpath_tx_id
, attr
);
4018 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4020 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4023 /* Initialization of attribute. */
4024 void bgp_attr_init(void)
4037 void bgp_attr_finish(void)
4042 ecommunity_finish();
4043 lcommunity_finish();
4050 /* Make attribute packet. */
4051 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4052 struct prefix
*prefix
)
4057 struct aspath
*aspath
;
4058 int addpath_encode
= 0;
4059 uint32_t addpath_tx_id
= 0;
4061 /* Remember current pointer. */
4062 cp
= stream_get_endp(s
);
4064 /* Place holder of length. */
4067 /* Origin attribute. */
4068 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4069 stream_putc(s
, BGP_ATTR_ORIGIN
);
4071 stream_putc(s
, attr
->origin
);
4073 aspath
= attr
->aspath
;
4075 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4076 stream_putc(s
, BGP_ATTR_AS_PATH
);
4077 aspath_lenp
= stream_get_endp(s
);
4080 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4082 /* Nexthop attribute. */
4083 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4084 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4085 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4086 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4088 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4091 /* MED attribute. */
4092 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4093 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4094 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4096 stream_putl(s
, attr
->med
);
4099 /* Local preference. */
4100 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4101 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4102 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4104 stream_putl(s
, attr
->local_pref
);
4107 /* Atomic aggregate. */
4108 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4109 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4110 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4115 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4116 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4117 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4119 stream_putl(s
, attr
->aggregator_as
);
4120 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4123 /* Community attribute. */
4124 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4125 if (attr
->community
->size
* 4 > 255) {
4127 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4128 | BGP_ATTR_FLAG_EXTLEN
);
4129 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4130 stream_putw(s
, attr
->community
->size
* 4);
4133 BGP_ATTR_FLAG_OPTIONAL
4134 | BGP_ATTR_FLAG_TRANS
);
4135 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4136 stream_putc(s
, attr
->community
->size
* 4);
4138 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4141 /* Large Community attribute. */
4142 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4143 if (lcom_length(attr
->lcommunity
) > 255) {
4145 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4146 | BGP_ATTR_FLAG_EXTLEN
);
4147 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4148 stream_putw(s
, lcom_length(attr
->lcommunity
));
4151 BGP_ATTR_FLAG_OPTIONAL
4152 | BGP_ATTR_FLAG_TRANS
);
4153 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4154 stream_putc(s
, lcom_length(attr
->lcommunity
));
4157 stream_put(s
, attr
->lcommunity
->val
,
4158 lcom_length(attr
->lcommunity
));
4161 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4162 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4163 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4164 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4167 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4168 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4169 sizep
= stream_get_endp(s
);
4172 stream_putc(s
, 0); /* Marker: Attribute length. */
4173 stream_putw(s
, AFI_IP6
); /* AFI */
4174 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4177 stream_putc(s
, attr
->mp_nexthop_len
);
4178 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4179 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4180 stream_put(s
, &attr
->mp_nexthop_local
,
4187 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
4190 /* Set MP attribute length. */
4191 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4195 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4196 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4198 BGP_ATTR_FLAG_OPTIONAL
4199 | BGP_ATTR_FLAG_TRANS
);
4200 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4202 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4203 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4204 stream_putc(s
, 0); // reserved
4205 stream_putw(s
, 0); // flags
4206 stream_putl(s
, attr
->label_index
);
4210 /* Return total size of attribute. */
4211 len
= stream_get_endp(s
) - cp
- 2;
4212 stream_putw_at(s
, cp
, len
);