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 #ifdef ENABLE_BGP_VNC_ATTR
83 {BGP_ATTR_VNC
, "VNC"},
85 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
86 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
87 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
90 static const struct message attr_flag_str
[] = {
91 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
92 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
93 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
94 /* bgp_attr_flags_diagnose() relies on this bit being last in
96 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
99 static struct hash
*cluster_hash
;
101 static void *cluster_hash_alloc(void *p
)
103 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
104 struct cluster_list
*cluster
;
106 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
107 cluster
->length
= val
->length
;
109 if (cluster
->length
) {
110 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
111 memcpy(cluster
->list
, val
->list
, val
->length
);
113 cluster
->list
= NULL
;
120 /* Cluster list related functions. */
121 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
123 struct cluster_list tmp
= {};
124 struct cluster_list
*cluster
;
127 tmp
.list
= length
== 0 ? NULL
: pnt
;
129 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
134 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
138 for (i
= 0; i
< cluster
->length
/ 4; i
++)
139 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
144 static unsigned int cluster_hash_key_make(const void *p
)
146 const struct cluster_list
*cluster
= p
;
148 return jhash(cluster
->list
, cluster
->length
, 0);
151 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
153 const struct cluster_list
*cluster1
= p1
;
154 const struct cluster_list
*cluster2
= p2
;
156 if (cluster1
->list
== cluster2
->list
)
159 if (!cluster1
->list
|| !cluster2
->list
)
162 if (cluster1
->length
!= cluster2
->length
)
165 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
168 static void cluster_free(struct cluster_list
*cluster
)
170 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
171 XFREE(MTYPE_CLUSTER
, cluster
);
174 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
176 struct cluster_list
*find
;
178 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
184 static void cluster_unintern(struct cluster_list
**cluster
)
186 if ((*cluster
)->refcnt
)
187 (*cluster
)->refcnt
--;
189 if ((*cluster
)->refcnt
== 0) {
190 void *p
= hash_release(cluster_hash
, *cluster
);
191 assert(p
== *cluster
);
192 cluster_free(*cluster
);
197 static void cluster_init(void)
199 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
203 static void cluster_finish(void)
205 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
206 hash_free(cluster_hash
);
210 static struct hash
*encap_hash
= NULL
;
211 #ifdef ENABLE_BGP_VNC
212 static struct hash
*vnc_hash
= NULL
;
214 static struct hash
*srv6_l3vpn_hash
;
215 static struct hash
*srv6_vpn_hash
;
217 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
219 struct bgp_attr_encap_subtlv
*new;
220 struct bgp_attr_encap_subtlv
*tail
;
221 struct bgp_attr_encap_subtlv
*p
;
223 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
224 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
226 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
229 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
232 memcpy(tail
, p
, size
);
239 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
241 struct bgp_attr_encap_subtlv
*next
;
245 XFREE(MTYPE_ENCAP_TLV
, p
);
250 void bgp_attr_flush_encap(struct attr
*attr
)
255 if (attr
->encap_subtlvs
) {
256 encap_free(attr
->encap_subtlvs
);
257 attr
->encap_subtlvs
= NULL
;
259 #ifdef ENABLE_BGP_VNC
260 if (attr
->vnc_subtlvs
) {
261 encap_free(attr
->vnc_subtlvs
);
262 attr
->vnc_subtlvs
= NULL
;
268 * Compare encap sub-tlv chains
273 * This algorithm could be made faster if needed
275 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
276 const struct bgp_attr_encap_subtlv
*h2
)
278 const struct bgp_attr_encap_subtlv
*p
;
279 const struct bgp_attr_encap_subtlv
*q
;
283 if (h1
== NULL
|| h2
== NULL
)
286 for (p
= h1
; p
; p
= p
->next
) {
287 for (q
= h2
; q
; q
= q
->next
) {
288 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
289 && !memcmp(p
->value
, q
->value
, p
->length
)) {
298 for (p
= h2
; p
; p
= p
->next
) {
299 for (q
= h1
; q
; q
= q
->next
) {
300 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
301 && !memcmp(p
->value
, q
->value
, p
->length
)) {
313 static void *encap_hash_alloc(void *p
)
315 /* Encap structure is already allocated. */
321 #ifdef ENABLE_BGP_VNC
326 static struct bgp_attr_encap_subtlv
*
327 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
329 struct bgp_attr_encap_subtlv
*find
;
330 struct hash
*hash
= encap_hash
;
331 #ifdef ENABLE_BGP_VNC
332 if (type
== VNC_SUBTLV_TYPE
)
336 find
= hash_get(hash
, encap
, encap_hash_alloc
);
344 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
345 encap_subtlv_type type
)
347 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
351 if (encap
->refcnt
== 0) {
352 struct hash
*hash
= encap_hash
;
353 #ifdef ENABLE_BGP_VNC
354 if (type
== VNC_SUBTLV_TYPE
)
357 hash_release(hash
, encap
);
363 static unsigned int encap_hash_key_make(const void *p
)
365 const struct bgp_attr_encap_subtlv
*encap
= p
;
367 return jhash(encap
->value
, encap
->length
, 0);
370 static bool encap_hash_cmp(const void *p1
, const void *p2
)
372 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
373 (const struct bgp_attr_encap_subtlv
*)p2
);
376 static void encap_init(void)
378 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
380 #ifdef ENABLE_BGP_VNC
381 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
386 static void encap_finish(void)
388 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
389 hash_free(encap_hash
);
391 #ifdef ENABLE_BGP_VNC
392 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
398 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
406 return !memcmp(&(a1
->evpn_overlay
), &(a2
->evpn_overlay
),
407 sizeof(struct bgp_route_evpn
));
410 /* Unknown transit attribute. */
411 static struct hash
*transit_hash
;
413 static void transit_free(struct transit
*transit
)
415 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
416 XFREE(MTYPE_TRANSIT
, transit
);
419 static void *transit_hash_alloc(void *p
)
421 /* Transit structure is already allocated. */
425 static struct transit
*transit_intern(struct transit
*transit
)
427 struct transit
*find
;
429 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
431 transit_free(transit
);
437 static void transit_unintern(struct transit
**transit
)
439 if ((*transit
)->refcnt
)
440 (*transit
)->refcnt
--;
442 if ((*transit
)->refcnt
== 0) {
443 hash_release(transit_hash
, *transit
);
444 transit_free(*transit
);
449 static void *srv6_l3vpn_hash_alloc(void *p
)
454 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
456 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
459 static struct bgp_attr_srv6_l3vpn
*
460 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
462 struct bgp_attr_srv6_l3vpn
*find
;
464 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
466 srv6_l3vpn_free(l3vpn
);
471 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
473 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
478 if (l3vpn
->refcnt
== 0) {
479 hash_release(srv6_l3vpn_hash
, l3vpn
);
480 srv6_l3vpn_free(l3vpn
);
485 static void *srv6_vpn_hash_alloc(void *p
)
490 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
492 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
495 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
497 struct bgp_attr_srv6_vpn
*find
;
499 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
506 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
508 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
513 if (vpn
->refcnt
== 0) {
514 hash_release(srv6_vpn_hash
, vpn
);
520 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
522 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
525 key
= jhash(&l3vpn
->sid
, 16, key
);
526 key
= jhash_1word(l3vpn
->sid_flags
, key
);
527 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
531 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
533 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
534 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
536 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
537 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
538 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
;
541 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
542 const struct bgp_attr_srv6_l3vpn
*h2
)
546 else if (h1
== NULL
|| h2
== NULL
)
549 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
552 static unsigned int srv6_vpn_hash_key_make(const void *p
)
554 const struct bgp_attr_srv6_vpn
*vpn
= p
;
557 key
= jhash(&vpn
->sid
, 16, key
);
558 key
= jhash_1word(vpn
->sid_flags
, key
);
562 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
564 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
565 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
567 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
568 && vpn1
->sid_flags
== vpn2
->sid_flags
;
571 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
572 const struct bgp_attr_srv6_vpn
*h2
)
576 else if (h1
== NULL
|| h2
== NULL
)
579 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
582 static void srv6_init(void)
585 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
586 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
587 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
588 "BGP Prefix-SID SRv6-VPN-Service-TLV");
591 static void srv6_finish(void)
593 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
594 hash_free(srv6_l3vpn_hash
);
595 srv6_l3vpn_hash
= NULL
;
596 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
597 hash_free(srv6_vpn_hash
);
598 srv6_vpn_hash
= NULL
;
601 static unsigned int transit_hash_key_make(const void *p
)
603 const struct transit
*transit
= p
;
605 return jhash(transit
->val
, transit
->length
, 0);
608 static bool transit_hash_cmp(const void *p1
, const void *p2
)
610 const struct transit
*transit1
= p1
;
611 const struct transit
*transit2
= p2
;
613 return (transit1
->length
== transit2
->length
614 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
617 static void transit_init(void)
619 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
623 static void transit_finish(void)
625 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
626 hash_free(transit_hash
);
630 /* Attribute hash routines. */
631 static struct hash
*attrhash
;
633 unsigned long int attr_count(void)
635 return attrhash
->count
;
638 unsigned long int attr_unknown_count(void)
640 return transit_hash
->count
;
643 unsigned int attrhash_key_make(const void *p
)
645 const struct attr
*attr
= (struct attr
*)p
;
647 #define MIX(val) key = jhash_1word(val, key)
648 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
650 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
651 MIX3(attr
->local_pref
, attr
->aggregator_as
,
652 attr
->aggregator_addr
.s_addr
);
653 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
654 attr
->originator_id
.s_addr
);
655 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
658 MIX(aspath_key_make(attr
->aspath
));
660 MIX(community_hash_make(attr
->community
));
662 if (attr
->lcommunity
)
663 MIX(lcommunity_hash_make(attr
->lcommunity
));
664 if (attr
->ecommunity
)
665 MIX(ecommunity_hash_make(attr
->ecommunity
));
666 if (attr
->ipv6_ecommunity
)
667 MIX(ecommunity_hash_make(attr
->ipv6_ecommunity
));
669 MIX(cluster_hash_key_make(attr
->cluster
));
671 MIX(transit_hash_key_make(attr
->transit
));
672 if (attr
->encap_subtlvs
)
673 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
674 #ifdef ENABLE_BGP_VNC
675 if (attr
->vnc_subtlvs
)
676 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
678 MIX(attr
->mp_nexthop_len
);
679 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
680 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
681 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
682 MIX(attr
->rmap_table_id
);
687 bool attrhash_cmp(const void *p1
, const void *p2
)
689 const struct attr
*attr1
= p1
;
690 const struct attr
*attr2
= p2
;
692 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
693 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
694 && attr1
->aspath
== attr2
->aspath
695 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
696 && attr1
->local_pref
== attr2
->local_pref
697 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
698 if (attr1
->aggregator_as
== attr2
->aggregator_as
699 && attr1
->aggregator_addr
.s_addr
700 == attr2
->aggregator_addr
.s_addr
701 && attr1
->weight
== attr2
->weight
702 && attr1
->tag
== attr2
->tag
703 && attr1
->label_index
== attr2
->label_index
704 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
705 && attr1
->ecommunity
== attr2
->ecommunity
706 && attr1
->ipv6_ecommunity
== attr2
->ipv6_ecommunity
707 && attr1
->lcommunity
== attr2
->lcommunity
708 && attr1
->cluster
== attr2
->cluster
709 && attr1
->transit
== attr2
->transit
710 && attr1
->rmap_table_id
== attr2
->rmap_table_id
711 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
712 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
713 #ifdef ENABLE_BGP_VNC
714 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
716 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
717 &attr2
->mp_nexthop_global
)
718 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
719 &attr2
->mp_nexthop_local
)
720 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
721 &attr2
->mp_nexthop_global_in
)
722 && IPV4_ADDR_SAME(&attr1
->originator_id
,
723 &attr2
->originator_id
)
724 && overlay_index_same(attr1
, attr2
)
725 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
726 && attr1
->es_flags
== attr2
->es_flags
727 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
728 && attr1
->nh_ifindex
== attr2
->nh_ifindex
729 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
730 && attr1
->distance
== attr2
->distance
731 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
732 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
733 && attr1
->srte_color
== attr2
->srte_color
)
740 static void attrhash_init(void)
743 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
747 * special for hash_clean below
749 static void attr_vfree(void *attr
)
751 XFREE(MTYPE_ATTR
, attr
);
754 static void attrhash_finish(void)
756 hash_clean(attrhash
, attr_vfree
);
761 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
763 struct attr
*attr
= bucket
->data
;
764 char sid_str
[BUFSIZ
];
766 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
769 if (attr
->srv6_l3vpn
)
770 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
771 else if (attr
->srv6_vpn
)
772 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
775 "\tflags: %" PRIu64
" med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
776 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
777 attr
->weight
, attr
->label
, sid_str
);
780 void attr_show_all(struct vty
*vty
)
782 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
783 void *))attr_show_all_iterator
,
787 static void *bgp_attr_hash_alloc(void *p
)
789 struct attr
*val
= (struct attr
*)p
;
792 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
794 if (val
->encap_subtlvs
) {
795 val
->encap_subtlvs
= NULL
;
797 #ifdef ENABLE_BGP_VNC
798 if (val
->vnc_subtlvs
) {
799 val
->vnc_subtlvs
= NULL
;
803 val
->srv6_l3vpn
= NULL
;
805 val
->srv6_vpn
= NULL
;
811 /* Internet argument attribute. */
812 struct attr
*bgp_attr_intern(struct attr
*attr
)
816 /* Intern referenced strucutre. */
818 if (!attr
->aspath
->refcnt
)
819 attr
->aspath
= aspath_intern(attr
->aspath
);
821 attr
->aspath
->refcnt
++;
823 if (attr
->community
) {
824 if (!attr
->community
->refcnt
)
825 attr
->community
= community_intern(attr
->community
);
827 attr
->community
->refcnt
++;
830 if (attr
->ecommunity
) {
831 if (!attr
->ecommunity
->refcnt
)
832 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
834 attr
->ecommunity
->refcnt
++;
837 if (attr
->ipv6_ecommunity
) {
838 if (!attr
->ipv6_ecommunity
->refcnt
)
839 attr
->ipv6_ecommunity
=
840 ecommunity_intern(attr
->ipv6_ecommunity
);
842 attr
->ipv6_ecommunity
->refcnt
++;
845 if (attr
->lcommunity
) {
846 if (!attr
->lcommunity
->refcnt
)
847 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
849 attr
->lcommunity
->refcnt
++;
852 if (!attr
->cluster
->refcnt
)
853 attr
->cluster
= cluster_intern(attr
->cluster
);
855 attr
->cluster
->refcnt
++;
858 if (!attr
->transit
->refcnt
)
859 attr
->transit
= transit_intern(attr
->transit
);
861 attr
->transit
->refcnt
++;
863 if (attr
->encap_subtlvs
) {
864 if (!attr
->encap_subtlvs
->refcnt
)
865 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
868 attr
->encap_subtlvs
->refcnt
++;
870 if (attr
->srv6_l3vpn
) {
871 if (!attr
->srv6_l3vpn
->refcnt
)
872 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
874 attr
->srv6_l3vpn
->refcnt
++;
876 if (attr
->srv6_vpn
) {
877 if (!attr
->srv6_vpn
->refcnt
)
878 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
880 attr
->srv6_vpn
->refcnt
++;
882 #ifdef ENABLE_BGP_VNC
883 if (attr
->vnc_subtlvs
) {
884 if (!attr
->vnc_subtlvs
->refcnt
)
885 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
888 attr
->vnc_subtlvs
->refcnt
++;
892 /* At this point, attr only contains intern'd pointers. that means
893 * if we find it in attrhash, it has all the same pointers and we
894 * correctly updated the refcounts on these.
895 * If we don't find it, we need to allocate a one because in all
896 * cases this returns a new reference to a hashed attr, but the input
898 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
904 /* Make network statement's attribute. */
905 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
907 memset(attr
, 0, sizeof(struct attr
));
909 attr
->origin
= origin
;
910 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
911 attr
->aspath
= aspath_empty();
912 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
913 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
915 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
916 attr
->label
= MPLS_INVALID_LABEL
;
917 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
918 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
923 /* Create the attributes for an aggregate */
924 struct attr
*bgp_attr_aggregate_intern(
925 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
926 struct community
*community
, struct ecommunity
*ecommunity
,
927 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
928 uint8_t atomic_aggregate
, const struct prefix
*p
)
934 memset(&attr
, 0, sizeof(struct attr
));
936 /* Origin attribute. */
937 attr
.origin
= origin
;
938 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
940 /* AS path attribute. */
942 attr
.aspath
= aspath_intern(aspath
);
944 attr
.aspath
= aspath_empty();
945 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
947 /* Next hop attribute. */
948 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
951 uint32_t gshut
= COMMUNITY_GSHUT
;
953 /* If we are not shutting down ourselves and we are
954 * aggregating a route that contains the GSHUT community we
955 * need to remove that community when creating the aggregate */
956 if (!bgp_in_graceful_shutdown(bgp
)
957 && community_include(community
, gshut
)) {
958 community_del_val(community
, &gshut
);
961 attr
.community
= community
;
962 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
966 attr
.ecommunity
= ecommunity
;
967 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
971 attr
.lcommunity
= lcommunity
;
972 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
975 if (bgp_in_graceful_shutdown(bgp
))
976 bgp_attr_add_gshut_community(&attr
);
978 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
979 attr
.label
= MPLS_INVALID_LABEL
;
980 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
981 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
982 if (!aggregate
->as_set
|| atomic_aggregate
)
983 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
984 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
985 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
986 attr
.aggregator_as
= bgp
->confed_id
;
988 attr
.aggregator_as
= bgp
->as
;
989 attr
.aggregator_addr
= bgp
->router_id
;
990 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
991 attr
.label
= MPLS_INVALID_LABEL
;
993 /* Apply route-map */
994 if (aggregate
->rmap
.name
) {
995 struct attr attr_tmp
= attr
;
996 struct bgp_path_info rmap_path
;
998 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
999 rmap_path
.peer
= bgp
->peer_self
;
1000 rmap_path
.attr
= &attr_tmp
;
1002 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1004 ret
= route_map_apply(aggregate
->rmap
.map
, p
, RMAP_BGP
,
1007 bgp
->peer_self
->rmap_type
= 0;
1009 if (ret
== RMAP_DENYMATCH
) {
1010 /* Free uninterned attribute. */
1011 bgp_attr_flush(&attr_tmp
);
1013 /* Unintern original. */
1014 aspath_unintern(&attr
.aspath
);
1018 if (bgp_in_graceful_shutdown(bgp
))
1019 bgp_attr_add_gshut_community(&attr_tmp
);
1021 new = bgp_attr_intern(&attr_tmp
);
1024 if (bgp_in_graceful_shutdown(bgp
))
1025 bgp_attr_add_gshut_community(&attr
);
1027 new = bgp_attr_intern(&attr
);
1030 aspath_unintern(&new->aspath
);
1034 /* Unintern just the sub-components of the attr, but not the attr */
1035 void bgp_attr_unintern_sub(struct attr
*attr
)
1037 /* aspath refcount shoud be decrement. */
1039 aspath_unintern(&attr
->aspath
);
1040 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1042 if (attr
->community
)
1043 community_unintern(&attr
->community
);
1044 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1046 if (attr
->ecommunity
)
1047 ecommunity_unintern(&attr
->ecommunity
);
1048 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1050 if (attr
->ipv6_ecommunity
)
1051 ecommunity_unintern(&attr
->ipv6_ecommunity
);
1052 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
));
1054 if (attr
->lcommunity
)
1055 lcommunity_unintern(&attr
->lcommunity
);
1056 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1059 cluster_unintern(&attr
->cluster
);
1060 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1063 transit_unintern(&attr
->transit
);
1065 if (attr
->encap_subtlvs
)
1066 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1068 #ifdef ENABLE_BGP_VNC
1069 if (attr
->vnc_subtlvs
)
1070 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1073 if (attr
->srv6_l3vpn
)
1074 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1077 srv6_vpn_unintern(&attr
->srv6_vpn
);
1081 * We have some show commands that let you experimentally
1082 * apply a route-map. When we apply the route-map
1083 * we are reseting values but not saving them for
1084 * posterity via intern'ing( because route-maps don't
1085 * do that) but at this point in time we need
1086 * to compare the new attr to the old and if the
1087 * routemap has changed it we need to, as Snoop Dog says,
1088 * Drop it like it's hot
1090 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
1092 if (new->aspath
!= old
->aspath
)
1093 aspath_free(new->aspath
);
1095 if (new->community
!= old
->community
)
1096 community_free(&new->community
);
1098 if (new->ecommunity
!= old
->ecommunity
)
1099 ecommunity_free(&new->ecommunity
);
1101 if (new->lcommunity
!= old
->lcommunity
)
1102 lcommunity_free(&new->lcommunity
);
1105 /* Free bgp attribute and aspath. */
1106 void bgp_attr_unintern(struct attr
**pattr
)
1108 struct attr
*attr
= *pattr
;
1112 /* Decrement attribute reference. */
1117 /* If reference becomes zero then free attribute object. */
1118 if (attr
->refcnt
== 0) {
1119 ret
= hash_release(attrhash
, attr
);
1120 assert(ret
!= NULL
);
1121 XFREE(MTYPE_ATTR
, attr
);
1125 bgp_attr_unintern_sub(&tmp
);
1128 void bgp_attr_flush(struct attr
*attr
)
1130 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1131 aspath_free(attr
->aspath
);
1132 attr
->aspath
= NULL
;
1134 if (attr
->community
&& !attr
->community
->refcnt
)
1135 community_free(&attr
->community
);
1136 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
1137 ecommunity_free(&attr
->ecommunity
);
1138 if (attr
->ipv6_ecommunity
&& !attr
->ipv6_ecommunity
->refcnt
)
1139 ecommunity_free(&attr
->ipv6_ecommunity
);
1140 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
1141 lcommunity_free(&attr
->lcommunity
);
1142 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
1143 cluster_free(attr
->cluster
);
1144 attr
->cluster
= NULL
;
1146 if (attr
->transit
&& !attr
->transit
->refcnt
) {
1147 transit_free(attr
->transit
);
1148 attr
->transit
= NULL
;
1150 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1151 encap_free(attr
->encap_subtlvs
);
1152 attr
->encap_subtlvs
= NULL
;
1154 #ifdef ENABLE_BGP_VNC
1155 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
1156 encap_free(attr
->vnc_subtlvs
);
1157 attr
->vnc_subtlvs
= NULL
;
1162 /* Implement draft-scudder-idr-optional-transitive behaviour and
1163 * avoid resetting sessions for malformed attributes which are
1164 * are partial/optional and hence where the error likely was not
1165 * introduced by the sending neighbour.
1167 static bgp_attr_parse_ret_t
1168 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1171 struct peer
*const peer
= args
->peer
;
1172 struct attr
*const attr
= args
->attr
;
1173 const uint8_t flags
= args
->flags
;
1174 /* startp and length must be special-cased, as whether or not to
1175 * send the attribute data with the NOTIFY depends on the error,
1176 * the caller therefore signals this with the seperate length argument
1178 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1180 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1181 char attr_str
[BUFSIZ
] = {0};
1183 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1185 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1188 /* Only relax error handling for eBGP peers */
1189 if (peer
->sort
!= BGP_PEER_EBGP
) {
1190 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1191 notify_datap
, length
);
1192 return BGP_ATTR_PARSE_ERROR
;
1195 /* Adjust the stream getp to the end of the attribute, in case we can
1196 * still proceed but the caller hasn't read all the attribute.
1198 stream_set_getp(BGP_INPUT(peer
),
1199 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1202 switch (args
->type
) {
1203 /* where an attribute is relatively inconsequential, e.g. it does not
1204 * affect route selection, and can be safely ignored, then any such
1205 * attributes which are malformed should just be ignored and the route
1206 * processed as normal.
1208 case BGP_ATTR_AS4_AGGREGATOR
:
1209 case BGP_ATTR_AGGREGATOR
:
1210 case BGP_ATTR_ATOMIC_AGGREGATE
:
1211 return BGP_ATTR_PARSE_PROCEED
;
1213 /* Core attributes, particularly ones which may influence route
1214 * selection, should be treat-as-withdraw.
1216 case BGP_ATTR_ORIGIN
:
1217 case BGP_ATTR_AS_PATH
:
1218 case BGP_ATTR_NEXT_HOP
:
1219 case BGP_ATTR_MULTI_EXIT_DISC
:
1220 case BGP_ATTR_LOCAL_PREF
:
1221 case BGP_ATTR_COMMUNITIES
:
1222 case BGP_ATTR_EXT_COMMUNITIES
:
1223 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1224 case BGP_ATTR_LARGE_COMMUNITIES
:
1225 case BGP_ATTR_ORIGINATOR_ID
:
1226 case BGP_ATTR_CLUSTER_LIST
:
1227 return BGP_ATTR_PARSE_WITHDRAW
;
1228 case BGP_ATTR_MP_REACH_NLRI
:
1229 case BGP_ATTR_MP_UNREACH_NLRI
:
1230 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1231 notify_datap
, length
);
1232 return BGP_ATTR_PARSE_ERROR
;
1235 /* Partial optional attributes that are malformed should not cause
1236 * the whole session to be reset. Instead treat it as a withdrawal
1237 * of the routes, if possible.
1239 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1240 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1241 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1242 return BGP_ATTR_PARSE_WITHDRAW
;
1244 /* default to reset */
1245 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1248 /* Find out what is wrong with the path attribute flag bits and log the error.
1249 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1250 Extended Length. Checking O/T/P bits at once implies, that the attribute
1251 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1252 non-transitive" attribute. */
1254 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1255 uint8_t desired_flags
/* how RFC says it must be */
1258 uint8_t seen
= 0, i
;
1259 uint8_t real_flags
= args
->flags
;
1260 const uint8_t attr_code
= args
->type
;
1262 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1263 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1264 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1265 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1266 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1267 flog_err(EC_BGP_ATTR_FLAG
,
1268 "%s attribute must%s be flagged as \"%s\"",
1269 lookup_msg(attr_str
, attr_code
, NULL
),
1270 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1273 attr_flag_str
[i
].str
);
1278 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1279 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1280 real_flags
, desired_flags
);
1284 /* Required flags for attributes. EXTLEN will be masked off when testing,
1285 * as will PARTIAL for optional+transitive attributes.
1287 const uint8_t attr_flags_values
[] = {
1288 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1289 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1290 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1291 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1292 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1293 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1294 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1295 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1296 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1297 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1298 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1299 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1300 [BGP_ATTR_EXT_COMMUNITIES
] =
1301 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1302 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1303 [BGP_ATTR_AS4_AGGREGATOR
] =
1304 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1305 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1306 [BGP_ATTR_LARGE_COMMUNITIES
] =
1307 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1308 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1309 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1310 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1312 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1314 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1316 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1317 const uint8_t flags
= args
->flags
;
1318 const uint8_t attr_code
= args
->type
;
1320 /* there may be attributes we don't know about */
1321 if (attr_code
> attr_flags_values_max
)
1323 if (attr_flags_values
[attr_code
] == 0)
1326 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1330 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1331 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1334 "%s well-known attributes must have transitive flag set (%x)",
1335 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1339 /* "For well-known attributes and for optional non-transitive
1341 * the Partial bit MUST be set to 0."
1343 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1344 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1345 flog_err(EC_BGP_ATTR_FLAG
,
1346 "%s well-known attribute must NOT have the partial flag set (%x)",
1347 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1350 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1351 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1352 flog_err(EC_BGP_ATTR_FLAG
,
1353 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1354 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1359 /* Optional transitive attributes may go through speakers that don't
1360 * reocgnise them and set the Partial bit.
1362 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1363 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1364 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1366 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1369 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1373 /* Get origin attribute of the update message. */
1374 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1376 struct peer
*const peer
= args
->peer
;
1377 struct attr
*const attr
= args
->attr
;
1378 const bgp_size_t length
= args
->length
;
1380 /* If any recognized attribute has Attribute Length that conflicts
1381 with the expected length (based on the attribute type code), then
1382 the Error Subcode is set to Attribute Length Error. The Data
1383 field contains the erroneous attribute (type, length and
1386 flog_err(EC_BGP_ATTR_LEN
,
1387 "Origin attribute length is not one %d", length
);
1388 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1392 /* Fetch origin attribute. */
1393 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1395 /* If the ORIGIN attribute has an undefined value, then the Error
1396 Subcode is set to Invalid Origin Attribute. The Data field
1397 contains the unrecognized attribute (type, length and value). */
1398 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1399 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1400 flog_err(EC_BGP_ATTR_ORIGIN
,
1401 "Origin attribute value is invalid %d", attr
->origin
);
1402 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1406 /* Set oring attribute flag. */
1407 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1412 /* Parse AS path information. This function is wrapper of
1414 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1416 struct attr
*const attr
= args
->attr
;
1417 struct peer
*const peer
= args
->peer
;
1418 const bgp_size_t length
= args
->length
;
1421 * peer with AS4 => will get 4Byte ASnums
1422 * otherwise, will get 16 Bit
1424 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1425 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1427 /* In case of IBGP, length will be zero. */
1428 if (!attr
->aspath
) {
1429 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1430 "Malformed AS path from %s, length is %d", peer
->host
,
1432 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1436 /* Codification of AS 0 Processing */
1437 if (aspath_check_as_zero(attr
->aspath
)) {
1439 EC_BGP_ATTR_MAL_AS_PATH
,
1440 "Malformed AS path, AS number is 0 in the path from %s",
1442 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1446 /* Set aspath attribute flag. */
1447 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1449 return BGP_ATTR_PARSE_PROCEED
;
1452 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1453 struct attr
*const attr
)
1455 /* These checks were part of bgp_attr_aspath, but with
1456 * as4 we should to check aspath things when
1457 * aspath synthesizing with as4_path has already taken place.
1458 * Otherwise we check ASPATH and use the synthesized thing, and that is
1460 * So do the checks later, i.e. here
1462 struct aspath
*aspath
;
1464 /* Confederation sanity check. */
1465 if ((peer
->sort
== BGP_PEER_CONFED
1466 && !aspath_left_confed_check(attr
->aspath
))
1467 || (peer
->sort
== BGP_PEER_EBGP
1468 && aspath_confed_check(attr
->aspath
))) {
1469 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1471 return BGP_ATTR_PARSE_WITHDRAW
;
1474 /* First AS check for EBGP. */
1475 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1476 if (peer
->sort
== BGP_PEER_EBGP
1477 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1478 flog_err(EC_BGP_ATTR_FIRST_AS
,
1479 "%s incorrect first AS (must be %u)",
1480 peer
->host
, peer
->as
);
1481 return BGP_ATTR_PARSE_WITHDRAW
;
1485 /* local-as prepend */
1486 if (peer
->change_local_as
1487 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1488 aspath
= aspath_dup(attr
->aspath
);
1489 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1490 aspath_unintern(&attr
->aspath
);
1491 attr
->aspath
= aspath_intern(aspath
);
1494 return BGP_ATTR_PARSE_PROCEED
;
1497 /* Parse AS4 path information. This function is another wrapper of
1499 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1500 struct aspath
**as4_path
)
1502 struct peer
*const peer
= args
->peer
;
1503 struct attr
*const attr
= args
->attr
;
1504 const bgp_size_t length
= args
->length
;
1506 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1508 /* In case of IBGP, length will be zero. */
1510 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1511 "Malformed AS4 path from %s, length is %d", peer
->host
,
1513 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1517 /* Codification of AS 0 Processing */
1518 if (aspath_check_as_zero(*as4_path
)) {
1520 EC_BGP_ATTR_MAL_AS_PATH
,
1521 "Malformed AS path, AS number is 0 in the path from %s",
1523 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1527 /* Set aspath attribute flag. */
1528 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1530 return BGP_ATTR_PARSE_PROCEED
;
1534 * Check that the nexthop attribute is valid.
1536 bgp_attr_parse_ret_t
1537 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1539 in_addr_t nexthop_h
;
1541 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1542 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1543 || IPV4_CLASS_DE(nexthop_h
))
1544 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1545 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1546 char buf
[INET_ADDRSTRLEN
];
1548 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1550 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1552 data
[0] = BGP_ATTR_FLAG_TRANS
;
1553 data
[1] = BGP_ATTR_NEXT_HOP
;
1554 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1555 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1556 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1557 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1559 return BGP_ATTR_PARSE_ERROR
;
1562 return BGP_ATTR_PARSE_PROCEED
;
1565 /* Nexthop attribute. */
1566 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1568 struct peer
*const peer
= args
->peer
;
1569 struct attr
*const attr
= args
->attr
;
1570 const bgp_size_t length
= args
->length
;
1572 /* Check nexthop attribute length. */
1574 flog_err(EC_BGP_ATTR_LEN
,
1575 "Nexthop attribute length isn't four [%d]", length
);
1577 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1581 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1582 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1584 return BGP_ATTR_PARSE_PROCEED
;
1587 /* MED atrribute. */
1588 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1590 struct peer
*const peer
= args
->peer
;
1591 struct attr
*const attr
= args
->attr
;
1592 const bgp_size_t length
= args
->length
;
1596 flog_err(EC_BGP_ATTR_LEN
,
1597 "MED attribute length isn't four [%d]", length
);
1599 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1603 attr
->med
= stream_getl(peer
->curr
);
1605 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1607 return BGP_ATTR_PARSE_PROCEED
;
1610 /* Local preference attribute. */
1611 static bgp_attr_parse_ret_t
1612 bgp_attr_local_pref(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
;
1618 /* if received from an internal neighbor, it SHALL be considered
1619 * malformed if its length is not equal to 4. If malformed, the
1620 * UPDATE message SHALL be handled using the approach of "treat-as-
1623 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1624 flog_err(EC_BGP_ATTR_LEN
,
1625 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1626 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1630 /* If it is contained in an UPDATE message that is received from an
1631 external peer, then this attribute MUST be ignored by the
1632 receiving speaker. */
1633 if (peer
->sort
== BGP_PEER_EBGP
) {
1634 STREAM_FORWARD_GETP(peer
->curr
, length
);
1635 return BGP_ATTR_PARSE_PROCEED
;
1638 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1640 /* Set the local-pref flag. */
1641 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1643 return BGP_ATTR_PARSE_PROCEED
;
1646 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1650 /* Atomic aggregate. */
1651 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1653 struct attr
*const attr
= args
->attr
;
1654 const bgp_size_t length
= args
->length
;
1658 flog_err(EC_BGP_ATTR_LEN
,
1659 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1661 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1665 /* Set atomic aggregate flag. */
1666 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1668 return BGP_ATTR_PARSE_PROCEED
;
1671 /* Aggregator attribute */
1672 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1674 struct peer
*const peer
= args
->peer
;
1675 struct attr
*const attr
= args
->attr
;
1676 const bgp_size_t length
= args
->length
;
1681 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1682 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1683 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1686 if (length
!= wantedlen
) {
1687 flog_err(EC_BGP_ATTR_LEN
,
1688 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1690 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1694 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1695 aggregator_as
= stream_getl(peer
->curr
);
1697 aggregator_as
= stream_getw(peer
->curr
);
1699 attr
->aggregator_as
= aggregator_as
;
1700 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1702 /* Set atomic aggregate flag. */
1703 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1705 /* Codification of AS 0 Processing */
1706 if (aggregator_as
== BGP_AS_ZERO
)
1707 flog_err(EC_BGP_ATTR_LEN
,
1708 "AGGREGATOR AS number is 0 for aspath: %s",
1709 aspath_print(attr
->aspath
));
1711 return BGP_ATTR_PARSE_PROCEED
;
1714 /* New Aggregator attribute */
1715 static bgp_attr_parse_ret_t
1716 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1717 as_t
*as4_aggregator_as
,
1718 struct in_addr
*as4_aggregator_addr
)
1720 struct peer
*const peer
= args
->peer
;
1721 struct attr
*const attr
= args
->attr
;
1722 const bgp_size_t length
= args
->length
;
1726 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1728 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1732 aggregator_as
= stream_getl(peer
->curr
);
1733 *as4_aggregator_as
= aggregator_as
;
1734 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1736 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1738 /* Codification of AS 0 Processing */
1739 if (aggregator_as
== BGP_AS_ZERO
)
1740 flog_err(EC_BGP_ATTR_LEN
,
1741 "AS4_AGGREGATOR AS number is 0 for aspath: %s",
1742 aspath_print(attr
->aspath
));
1744 return BGP_ATTR_PARSE_PROCEED
;
1747 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1749 static bgp_attr_parse_ret_t
1750 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1751 struct aspath
*as4_path
, as_t as4_aggregator
,
1752 struct in_addr
*as4_aggregator_addr
)
1754 int ignore_as4_path
= 0;
1755 struct aspath
*newpath
;
1757 if (!attr
->aspath
) {
1758 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1760 * checked that all well-known, mandatory attributes were
1763 * Can only be a problem with peer itself - hard error
1765 return BGP_ATTR_PARSE_ERROR
;
1768 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1769 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1771 * It is worth a warning though, because the peer really
1772 * should not send them
1774 if (BGP_DEBUG(as4
, AS4
)) {
1775 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1776 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1777 "AS4 capable peer, yet it sent");
1780 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1781 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1783 "AS4 capable peer, yet it sent");
1786 return BGP_ATTR_PARSE_PROCEED
;
1789 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1790 * because that may override AS4_PATH
1792 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1793 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1795 * if the as_number in aggregator is not AS_TRANS,
1796 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1797 * and the Aggregator shall be taken as
1798 * info on the aggregating node, and the AS_PATH
1799 * shall be taken as the AS_PATH
1801 * the Aggregator shall be ignored and the
1802 * AS4_AGGREGATOR shall be taken as the
1803 * Aggregating node and the AS_PATH is to be
1804 * constructed "as in all other cases"
1806 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1808 if (BGP_DEBUG(as4
, AS4
))
1810 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1812 ignore_as4_path
= 1;
1814 /* "New_aggregator shall be taken as aggregator"
1816 attr
->aggregator_as
= as4_aggregator
;
1817 attr
->aggregator_addr
.s_addr
=
1818 as4_aggregator_addr
->s_addr
;
1821 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1822 * That is bogus - but reading the conditions
1823 * we have to handle AS4_AGGREGATOR as if it were
1824 * AGGREGATOR in that case
1826 if (BGP_DEBUG(as4
, AS4
))
1828 "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there",
1830 attr
->aggregator_as
= as4_aggregator
;
1831 /* sweep it under the carpet and simulate a "good"
1833 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1837 /* need to reconcile NEW_AS_PATH and AS_PATH */
1838 if (!ignore_as4_path
1839 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1840 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1842 return BGP_ATTR_PARSE_ERROR
;
1844 aspath_unintern(&attr
->aspath
);
1845 attr
->aspath
= aspath_intern(newpath
);
1847 return BGP_ATTR_PARSE_PROCEED
;
1850 /* Community attribute. */
1851 static bgp_attr_parse_ret_t
1852 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1854 struct peer
*const peer
= args
->peer
;
1855 struct attr
*const attr
= args
->attr
;
1856 const bgp_size_t length
= args
->length
;
1859 attr
->community
= NULL
;
1860 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1865 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1867 /* XXX: fix community_parse to use stream API and remove this */
1868 stream_forward_getp(peer
->curr
, length
);
1870 /* The Community attribute SHALL be considered malformed if its
1871 * length is not a non-zero multiple of 4.
1873 if (!attr
->community
)
1874 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1877 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1879 return BGP_ATTR_PARSE_PROCEED
;
1882 /* Originator ID attribute. */
1883 static bgp_attr_parse_ret_t
1884 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1886 struct peer
*const peer
= args
->peer
;
1887 struct attr
*const attr
= args
->attr
;
1888 const bgp_size_t length
= args
->length
;
1890 /* if received from an internal neighbor, it SHALL be considered
1891 * malformed if its length is not equal to 4. If malformed, the
1892 * UPDATE message SHALL be handled using the approach of "treat-as-
1896 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1899 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1903 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1905 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1907 return BGP_ATTR_PARSE_PROCEED
;
1910 /* Cluster list attribute. */
1911 static bgp_attr_parse_ret_t
1912 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1914 struct peer
*const peer
= args
->peer
;
1915 struct attr
*const attr
= args
->attr
;
1916 const bgp_size_t length
= args
->length
;
1918 /* if received from an internal neighbor, it SHALL be considered
1919 * malformed if its length is not a non-zero multiple of 4. If
1920 * malformed, the UPDATE message SHALL be handled using the approach
1921 * of "treat-as-withdraw".
1923 if (length
== 0 || length
% 4) {
1924 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
1926 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1931 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1933 /* XXX: Fix cluster_parse to use stream API and then remove this */
1934 stream_forward_getp(peer
->curr
, length
);
1936 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1938 return BGP_ATTR_PARSE_PROCEED
;
1941 /* Multiprotocol reachability information parse. */
1942 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1943 struct bgp_nlri
*mp_update
)
1947 iana_safi_t pkt_safi
;
1949 bgp_size_t nlri_len
;
1952 struct peer
*const peer
= args
->peer
;
1953 struct attr
*const attr
= args
->attr
;
1954 const bgp_size_t length
= args
->length
;
1956 /* Set end of packet. */
1957 s
= BGP_INPUT(peer
);
1958 start
= stream_get_getp(s
);
1960 /* safe to read statically sized header? */
1961 #define BGP_MP_REACH_MIN_SIZE 5
1962 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1963 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1964 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
1965 __func__
, peer
->host
, (unsigned long)length
);
1966 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1969 /* Load AFI, SAFI. */
1970 pkt_afi
= stream_getw(s
);
1971 pkt_safi
= stream_getc(s
);
1973 /* Convert AFI, SAFI to internal values, check. */
1974 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1975 /* Log if AFI or SAFI is unrecognized. This is not an error
1977 * the attribute is otherwise malformed.
1979 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1981 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
1982 peer
->host
, iana_afi2str(pkt_afi
),
1983 iana_safi2str(pkt_safi
));
1984 return BGP_ATTR_PARSE_ERROR
;
1987 /* Get nexthop length. */
1988 attr
->mp_nexthop_len
= stream_getc(s
);
1990 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1992 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
1993 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1994 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1997 /* Nexthop length check. */
1998 switch (attr
->mp_nexthop_len
) {
2000 if (safi
!= SAFI_FLOWSPEC
) {
2001 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2002 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2003 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2006 case BGP_ATTR_NHLEN_VPNV4
:
2007 stream_getl(s
); /* RD high */
2008 stream_getl(s
); /* RD low */
2010 * NOTE: intentional fall through
2011 * - for consistency in rx processing
2013 * The following comment is to signal GCC this intention
2014 * and suppress the warning
2017 case BGP_ATTR_NHLEN_IPV4
:
2018 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2019 /* Probably needed for RFC 2283 */
2020 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2021 memcpy(&attr
->nexthop
.s_addr
,
2022 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2024 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2025 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2026 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2027 stream_getl(s
); /* RD high */
2028 stream_getl(s
); /* RD low */
2030 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2031 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2032 if (!peer
->nexthop
.ifp
) {
2033 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2035 return BGP_ATTR_PARSE_WITHDRAW
;
2037 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2040 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2041 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2042 if (attr
->mp_nexthop_len
2043 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2044 stream_getl(s
); /* RD high */
2045 stream_getl(s
); /* RD low */
2047 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2048 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2049 if (!peer
->nexthop
.ifp
) {
2050 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",
2052 return BGP_ATTR_PARSE_WITHDRAW
;
2054 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2056 if (attr
->mp_nexthop_len
2057 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2058 stream_getl(s
); /* RD high */
2059 stream_getl(s
); /* RD low */
2061 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2062 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2063 char buf1
[INET6_ADDRSTRLEN
];
2064 char buf2
[INET6_ADDRSTRLEN
];
2066 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2068 "%s sent next-hops %s and %s. Ignoring non-LL value",
2071 &attr
->mp_nexthop_global
,
2072 buf1
, INET6_ADDRSTRLEN
),
2074 &attr
->mp_nexthop_local
, buf2
,
2077 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2079 if (!peer
->nexthop
.ifp
) {
2080 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2082 return BGP_ATTR_PARSE_WITHDRAW
;
2084 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2087 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2088 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2089 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2093 zlog_info("%s: %s sent SNPA which couldn't be read",
2094 __func__
, peer
->host
);
2095 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2100 if ((val
= stream_getc(s
)))
2102 EC_BGP_DEFUNCT_SNPA_LEN
,
2103 "%s sent non-zero value, %u, for defunct SNPA-length field",
2107 /* must have nrli_len, what is left of the attribute */
2108 nlri_len
= LEN_LEFT
;
2109 if (nlri_len
> STREAM_READABLE(s
)) {
2110 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2111 __func__
, peer
->host
);
2112 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2116 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2117 __func__
, peer
->host
);
2119 mp_update
->afi
= afi
;
2120 mp_update
->safi
= safi
;
2121 return BGP_ATTR_PARSE_EOR
;
2124 mp_update
->afi
= afi
;
2125 mp_update
->safi
= safi
;
2126 mp_update
->nlri
= stream_pnt(s
);
2127 mp_update
->length
= nlri_len
;
2129 stream_forward_getp(s
, nlri_len
);
2131 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2133 return BGP_ATTR_PARSE_PROCEED
;
2137 /* Multiprotocol unreachable parse */
2138 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2139 struct bgp_nlri
*mp_withdraw
)
2144 iana_safi_t pkt_safi
;
2146 uint16_t withdraw_len
;
2147 struct peer
*const peer
= args
->peer
;
2148 struct attr
*const attr
= args
->attr
;
2149 const bgp_size_t length
= args
->length
;
2153 #define BGP_MP_UNREACH_MIN_SIZE 3
2154 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2155 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2157 pkt_afi
= stream_getw(s
);
2158 pkt_safi
= stream_getc(s
);
2160 /* Convert AFI, SAFI to internal values, check. */
2161 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2162 /* Log if AFI or SAFI is unrecognized. This is not an error
2164 * the attribute is otherwise malformed.
2166 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2168 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2169 peer
->host
, iana_afi2str(pkt_afi
),
2170 iana_safi2str(pkt_safi
));
2171 return BGP_ATTR_PARSE_ERROR
;
2174 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2176 mp_withdraw
->afi
= afi
;
2177 mp_withdraw
->safi
= safi
;
2178 mp_withdraw
->nlri
= stream_pnt(s
);
2179 mp_withdraw
->length
= withdraw_len
;
2181 stream_forward_getp(s
, withdraw_len
);
2183 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2185 return BGP_ATTR_PARSE_PROCEED
;
2188 /* Large Community attribute. */
2189 static bgp_attr_parse_ret_t
2190 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2192 struct peer
*const peer
= args
->peer
;
2193 struct attr
*const attr
= args
->attr
;
2194 const bgp_size_t length
= args
->length
;
2197 * Large community follows new attribute format.
2200 attr
->lcommunity
= NULL
;
2201 /* Empty extcomm doesn't seem to be invalid per se */
2202 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2206 attr
->lcommunity
= lcommunity_parse(stream_pnt(peer
->curr
), length
);
2207 /* XXX: fix ecommunity_parse to use stream API */
2208 stream_forward_getp(peer
->curr
, length
);
2210 if (!attr
->lcommunity
)
2211 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2214 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2216 return BGP_ATTR_PARSE_PROCEED
;
2219 /* Extended Community attribute. */
2220 static bgp_attr_parse_ret_t
2221 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2223 struct peer
*const peer
= args
->peer
;
2224 struct attr
*const attr
= args
->attr
;
2225 const bgp_size_t length
= args
->length
;
2230 attr
->ecommunity
= NULL
;
2231 /* Empty extcomm doesn't seem to be invalid per se */
2232 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2237 ecommunity_parse(stream_pnt(peer
->curr
), length
);
2238 /* XXX: fix ecommunity_parse to use stream API */
2239 stream_forward_getp(peer
->curr
, length
);
2241 /* The Extended Community attribute SHALL be considered malformed if
2242 * its length is not a non-zero multiple of 8.
2244 if (!attr
->ecommunity
)
2245 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2248 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2250 /* Extract MAC mobility sequence number, if any. */
2251 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2252 attr
->sticky
= sticky
;
2254 /* Check if this is a Gateway MAC-IP advertisement */
2255 attr
->default_gw
= bgp_attr_default_gw(attr
);
2257 /* Handle scenario where router flag ecommunity is not
2258 * set but default gw ext community is present.
2259 * Use default gateway, set and propogate R-bit.
2261 if (attr
->default_gw
)
2262 attr
->router_flag
= 1;
2264 /* Check EVPN Neighbor advertisement flags, R-bit */
2265 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2267 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2269 /* Extract the Rmac, if any */
2270 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2271 if (bgp_debug_update(peer
, NULL
, NULL
, 1) &&
2272 bgp_mac_exist(&attr
->rmac
)) {
2273 char buf1
[ETHER_ADDR_STRLEN
];
2275 zlog_debug("%s: router mac %s is self mac",
2277 prefix_mac2str(&attr
->rmac
, buf1
,
2283 /* Get the tunnel type from encap extended community */
2284 bgp_attr_extcom_tunnel_type(attr
,
2285 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2287 /* Extract link bandwidth, if any. */
2288 (void)ecommunity_linkbw_present(attr
->ecommunity
, &attr
->link_bw
);
2290 return BGP_ATTR_PARSE_PROCEED
;
2293 /* IPv6 Extended Community attribute. */
2294 static bgp_attr_parse_ret_t
2295 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2297 struct peer
*const peer
= args
->peer
;
2298 struct attr
*const attr
= args
->attr
;
2299 const bgp_size_t length
= args
->length
;
2302 attr
->ipv6_ecommunity
= NULL
;
2303 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2307 attr
->ipv6_ecommunity
=
2308 ecommunity_parse_ipv6(stream_pnt(peer
->curr
), length
);
2309 /* XXX: fix ecommunity_parse to use stream API */
2310 stream_forward_getp(peer
->curr
, length
);
2312 if (!attr
->ipv6_ecommunity
)
2313 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2316 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2318 return BGP_ATTR_PARSE_PROCEED
;
2321 /* Parse Tunnel Encap attribute in an UPDATE */
2322 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2323 bgp_size_t length
, /* IN: attr's length field */
2324 struct attr
*attr
, /* IN: caller already allocated */
2325 uint8_t flag
, /* IN: attr's flags field */
2329 uint16_t tunneltype
= 0;
2331 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2333 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2334 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2336 "Tunnel Encap attribute flag isn't optional and transitive %d",
2338 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2339 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2344 if (BGP_ATTR_ENCAP
== type
) {
2345 /* read outer TLV type and length */
2346 uint16_t tlv_length
;
2350 "Tunnel Encap attribute not long enough to contain outer T,L");
2351 bgp_notify_send_with_data(
2352 peer
, BGP_NOTIFY_UPDATE_ERR
,
2353 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2356 tunneltype
= stream_getw(BGP_INPUT(peer
));
2357 tlv_length
= stream_getw(BGP_INPUT(peer
));
2360 if (tlv_length
!= length
) {
2361 zlog_info("%s: tlv_length(%d) != length(%d)",
2362 __func__
, tlv_length
, length
);
2366 while (length
>= 4) {
2367 uint16_t subtype
= 0;
2368 uint16_t sublength
= 0;
2369 struct bgp_attr_encap_subtlv
*tlv
;
2371 if (BGP_ATTR_ENCAP
== type
) {
2372 subtype
= stream_getc(BGP_INPUT(peer
));
2373 sublength
= stream_getc(BGP_INPUT(peer
));
2375 #ifdef ENABLE_BGP_VNC
2377 subtype
= stream_getw(BGP_INPUT(peer
));
2378 sublength
= stream_getw(BGP_INPUT(peer
));
2383 if (sublength
> length
) {
2385 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2387 bgp_notify_send_with_data(
2388 peer
, BGP_NOTIFY_UPDATE_ERR
,
2389 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2393 /* alloc and copy sub-tlv */
2394 /* TBD make sure these are freed when attributes are released */
2395 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2396 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2397 tlv
->type
= subtype
;
2398 tlv
->length
= sublength
;
2399 stream_get(tlv
->value
, peer
->curr
, sublength
);
2400 length
-= sublength
;
2402 /* attach tlv to encap chain */
2403 if (BGP_ATTR_ENCAP
== type
) {
2404 struct bgp_attr_encap_subtlv
*stlv_last
;
2405 for (stlv_last
= attr
->encap_subtlvs
;
2406 stlv_last
&& stlv_last
->next
;
2407 stlv_last
= stlv_last
->next
)
2410 stlv_last
->next
= tlv
;
2412 attr
->encap_subtlvs
= tlv
;
2414 #ifdef ENABLE_BGP_VNC
2416 struct bgp_attr_encap_subtlv
*stlv_last
;
2417 for (stlv_last
= attr
->vnc_subtlvs
;
2418 stlv_last
&& stlv_last
->next
;
2419 stlv_last
= stlv_last
->next
)
2422 stlv_last
->next
= tlv
;
2424 attr
->vnc_subtlvs
= tlv
;
2430 if (BGP_ATTR_ENCAP
== type
) {
2431 attr
->encap_tunneltype
= tunneltype
;
2435 /* spurious leftover data */
2437 "Tunnel Encap attribute length is bad: %d leftover octets",
2439 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2440 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2449 * Read an individual SID value returning how much data we have read
2450 * Returns 0 if there was an error that needs to be passed up the stack
2452 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2453 struct bgp_attr_parser_args
*args
)
2455 struct peer
*const peer
= args
->peer
;
2456 struct attr
*const attr
= args
->attr
;
2457 uint32_t label_index
;
2458 struct in6_addr ipv6_sid
;
2460 uint32_t srgb_range
;
2462 uint8_t sid_type
, sid_flags
;
2463 uint16_t endpoint_behavior
;
2466 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2467 if (STREAM_READABLE(peer
->curr
) < length
2468 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2469 flog_err(EC_BGP_ATTR_LEN
,
2470 "Prefix SID label index length is %hu instead of %u",
2471 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2472 return bgp_attr_malformed(args
,
2473 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2477 /* Ignore flags and reserved */
2478 stream_getc(peer
->curr
);
2479 stream_getw(peer
->curr
);
2481 /* Fetch the label index and see if it is valid. */
2482 label_index
= stream_getl(peer
->curr
);
2483 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2484 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2487 /* Store label index; subsequently, we'll check on
2489 attr
->label_index
= label_index
;
2492 /* Placeholder code for the IPv6 SID type */
2493 else if (type
== BGP_PREFIX_SID_IPV6
) {
2494 if (STREAM_READABLE(peer
->curr
) < length
2495 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2496 flog_err(EC_BGP_ATTR_LEN
,
2497 "Prefix SID IPv6 length is %hu instead of %u",
2498 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2499 return bgp_attr_malformed(args
,
2500 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2504 /* Ignore reserved */
2505 stream_getc(peer
->curr
);
2506 stream_getw(peer
->curr
);
2508 stream_get(&ipv6_sid
, peer
->curr
, 16);
2511 /* Placeholder code for the Originator SRGB type */
2512 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2514 * ietf-idr-bgp-prefix-sid-05:
2515 * Length is the total length of the value portion of the
2516 * TLV: 2 + multiple of 6.
2518 * peer->curr stream readp should be at the beginning of the 16
2519 * bit flag field at this point in the code.
2523 * Check that the TLV length field is sane: at least 2 bytes of
2524 * flag, and at least 1 SRGB (these are 6 bytes each)
2526 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2529 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2531 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2532 return bgp_attr_malformed(
2533 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2538 * Check that we actually have at least as much data as
2539 * specified by the length field
2541 if (STREAM_READABLE(peer
->curr
) < length
) {
2542 flog_err(EC_BGP_ATTR_LEN
,
2543 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2544 length
, STREAM_READABLE(peer
->curr
));
2545 return bgp_attr_malformed(
2546 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2551 * Check that the portion of the TLV containing the sequence of
2552 * SRGBs corresponds to a multiple of the SRGB size; to get
2553 * that length, we skip the 16 bit flags field
2555 stream_getw(peer
->curr
);
2557 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2560 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2561 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2562 return bgp_attr_malformed(
2563 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2567 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2569 for (int i
= 0; i
< srgb_count
; i
++) {
2570 stream_get(&srgb_base
, peer
->curr
, 3);
2571 stream_get(&srgb_range
, peer
->curr
, 3);
2575 /* Placeholder code for the VPN-SID Service type */
2576 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2577 if (STREAM_READABLE(peer
->curr
) < length
2578 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2579 flog_err(EC_BGP_ATTR_LEN
,
2580 "Prefix SID VPN SID length is %hu instead of %u",
2581 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2582 return bgp_attr_malformed(args
,
2583 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2587 /* Parse VPN-SID Sub-TLV */
2588 stream_getc(peer
->curr
); /* reserved */
2589 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2590 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2591 stream_get(&ipv6_sid
, peer
->curr
,
2592 sizeof(ipv6_sid
)); /* sid_value */
2594 /* Log VPN-SID Sub-TLV */
2595 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2596 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2598 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2599 __func__
, buf
, sid_type
, sid_flags
);
2602 /* Configure from Info */
2603 if (attr
->srv6_vpn
) {
2604 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2605 "Prefix SID SRv6 VPN field repeated");
2606 return bgp_attr_malformed(
2607 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2609 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2610 sizeof(struct bgp_attr_srv6_vpn
));
2611 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2612 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2615 /* Placeholder code for the SRv6 L3 Service type */
2616 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2617 if (STREAM_READABLE(peer
->curr
) < length
2618 || length
!= BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
) {
2619 flog_err(EC_BGP_ATTR_LEN
,
2620 "Prefix SID SRv6 L3-Service length is %hu instead of %u",
2621 length
, BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
);
2622 return bgp_attr_malformed(args
,
2623 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2627 /* Parse L3-SERVICE Sub-TLV */
2628 stream_getc(peer
->curr
); /* reserved */
2629 stream_get(&ipv6_sid
, peer
->curr
,
2630 sizeof(ipv6_sid
)); /* sid_value */
2631 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2632 endpoint_behavior
= stream_getw(peer
->curr
); /* endpoint */
2633 stream_getc(peer
->curr
); /* reserved */
2635 /* Log L3-SERVICE Sub-TLV */
2636 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2637 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2639 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2640 __func__
, buf
, sid_flags
, endpoint_behavior
);
2643 /* Configure from Info */
2644 if (attr
->srv6_l3vpn
) {
2645 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2646 "Prefix SID SRv6 L3VPN field repeated");
2647 return bgp_attr_malformed(
2648 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2650 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2651 sizeof(struct bgp_attr_srv6_l3vpn
));
2652 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2653 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2654 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2657 /* Placeholder code for Unsupported TLV */
2660 if (STREAM_READABLE(peer
->curr
) < length
) {
2663 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2664 length
, STREAM_READABLE(peer
->curr
));
2665 return bgp_attr_malformed(
2666 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2670 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2672 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2675 stream_forward_getp(peer
->curr
, length
);
2678 return BGP_ATTR_PARSE_PROCEED
;
2681 /* Prefix SID attribute
2682 * draft-ietf-idr-bgp-prefix-sid-05
2684 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2686 struct peer
*const peer
= args
->peer
;
2687 struct attr
*const attr
= args
->attr
;
2688 bgp_attr_parse_ret_t ret
;
2690 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2694 size_t headersz
= sizeof(type
) + sizeof(length
);
2695 size_t psid_parsed_length
= 0;
2697 while (STREAM_READABLE(peer
->curr
) > 0
2698 && psid_parsed_length
< args
->length
) {
2700 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2703 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2704 headersz
, STREAM_READABLE(peer
->curr
));
2705 return bgp_attr_malformed(
2706 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2710 type
= stream_getc(peer
->curr
);
2711 length
= stream_getw(peer
->curr
);
2713 if (STREAM_READABLE(peer
->curr
) < length
) {
2716 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2717 length
, STREAM_READABLE(peer
->curr
));
2718 return bgp_attr_malformed(args
,
2719 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2723 ret
= bgp_attr_psid_sub(type
, length
, args
);
2725 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2728 psid_parsed_length
+= length
+ headersz
;
2730 if (psid_parsed_length
> args
->length
) {
2733 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2734 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2735 return bgp_attr_malformed(
2736 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2741 return BGP_ATTR_PARSE_PROCEED
;
2744 /* PMSI tunnel attribute (RFC 6514)
2745 * Basic validation checks done here.
2747 static bgp_attr_parse_ret_t
2748 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2750 struct peer
*const peer
= args
->peer
;
2751 struct attr
*const attr
= args
->attr
;
2752 const bgp_size_t length
= args
->length
;
2754 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2756 /* Verify that the receiver is expecting "ingress replication" as we
2757 * can only support that.
2759 if (length
< attr_parse_len
) {
2760 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2762 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2765 stream_getc(peer
->curr
); /* Flags */
2766 tnl_type
= stream_getc(peer
->curr
);
2767 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2768 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2769 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2770 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2773 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2775 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2776 "Bad PMSI tunnel attribute length %d for IR",
2778 return bgp_attr_malformed(
2779 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2784 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2785 attr
->pmsi_tnl_type
= tnl_type
;
2786 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2788 /* Forward read pointer of input stream. */
2789 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2791 return BGP_ATTR_PARSE_PROCEED
;
2794 /* BGP unknown attribute treatment. */
2795 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2797 bgp_size_t total
= args
->total
;
2798 struct transit
*transit
;
2799 struct peer
*const peer
= args
->peer
;
2800 struct attr
*const attr
= args
->attr
;
2801 uint8_t *const startp
= args
->startp
;
2802 const uint8_t type
= args
->type
;
2803 const uint8_t flag
= args
->flags
;
2804 const bgp_size_t length
= args
->length
;
2806 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2808 "%s Unknown attribute is received (type %d, length %d)",
2809 peer
->host
, type
, length
);
2811 /* Forward read pointer of input stream. */
2812 stream_forward_getp(peer
->curr
, length
);
2814 /* If any of the mandatory well-known attributes are not recognized,
2815 then the Error Subcode is set to Unrecognized Well-known
2816 Attribute. The Data field contains the unrecognized attribute
2817 (type, length and value). */
2818 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2819 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2823 /* Unrecognized non-transitive optional attributes must be quietly
2824 ignored and not passed along to other BGP peers. */
2825 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2826 return BGP_ATTR_PARSE_PROCEED
;
2828 /* If a path with recognized transitive optional attribute is
2829 accepted and passed along to other BGP peers and the Partial bit
2830 in the Attribute Flags octet is set to 1 by some previous AS, it
2831 is not set back to 0 by the current AS. */
2832 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2834 /* Store transitive attribute to the end of attr->transit. */
2836 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2838 transit
= attr
->transit
;
2841 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2842 transit
->length
+ total
);
2844 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2846 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2847 transit
->length
+= total
;
2849 return BGP_ATTR_PARSE_PROCEED
;
2852 /* Well-known attribute check. */
2853 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2857 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2859 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2860 return BGP_ATTR_PARSE_PROCEED
;
2862 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2863 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2864 are present, it should. Check for any other attribute being present
2867 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2868 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2869 return BGP_ATTR_PARSE_PROCEED
;
2871 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2872 type
= BGP_ATTR_ORIGIN
;
2874 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2875 type
= BGP_ATTR_AS_PATH
;
2877 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2879 * NLRI is empty. We can't easily check NLRI empty here though.
2881 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2882 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2883 type
= BGP_ATTR_NEXT_HOP
;
2885 if (peer
->sort
== BGP_PEER_IBGP
2886 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2887 type
= BGP_ATTR_LOCAL_PREF
;
2889 /* If any of the well-known mandatory attributes are not present
2890 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
2893 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2894 "%s Missing well-known attribute %s.", peer
->host
,
2895 lookup_msg(attr_str
, type
, NULL
));
2896 return BGP_ATTR_PARSE_WITHDRAW
;
2898 return BGP_ATTR_PARSE_PROCEED
;
2901 /* Read attribute of update packet. This function is called from
2902 bgp_update_receive() in bgp_packet.c. */
2903 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2904 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2905 struct bgp_nlri
*mp_withdraw
)
2907 bgp_attr_parse_ret_t ret
;
2911 uint8_t *startp
, *endp
;
2913 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2914 /* we need the as4_path only until we have synthesized the as_path with
2916 /* same goes for as4_aggregator */
2917 struct aspath
*as4_path
= NULL
;
2918 as_t as4_aggregator
= 0;
2919 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2921 /* Initialize bitmap. */
2922 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2924 /* End pointer of BGP attribute. */
2925 endp
= BGP_INPUT_PNT(peer
) + size
;
2927 /* Get attributes to the end of attribute length. */
2928 while (BGP_INPUT_PNT(peer
) < endp
) {
2929 /* Check remaining length check.*/
2930 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2931 /* XXX warning: long int format, int arg (arg 5) */
2933 EC_BGP_ATTRIBUTE_TOO_SMALL
,
2934 "%s: error BGP attribute length %lu is smaller than min len",
2936 (unsigned long)(endp
2937 - stream_pnt(BGP_INPUT(peer
))));
2939 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2940 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2941 ret
= BGP_ATTR_PARSE_ERROR
;
2945 /* Fetch attribute flag and type. */
2946 startp
= BGP_INPUT_PNT(peer
);
2947 /* "The lower-order four bits of the Attribute Flags octet are
2948 unused. They MUST be zero when sent and MUST be ignored when
2950 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2951 type
= stream_getc(BGP_INPUT(peer
));
2953 /* Check whether Extended-Length applies and is in bounds */
2954 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2955 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2957 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
2958 "%s: Extended length set, but just %lu bytes of attr header",
2960 (unsigned long)(endp
2961 - stream_pnt(BGP_INPUT(peer
))));
2963 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2964 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2965 ret
= BGP_ATTR_PARSE_ERROR
;
2969 /* Check extended attribue length bit. */
2970 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2971 length
= stream_getw(BGP_INPUT(peer
));
2973 length
= stream_getc(BGP_INPUT(peer
));
2975 /* If any attribute appears more than once in the UPDATE
2976 message, then the Error Subcode is set to Malformed Attribute
2979 if (CHECK_BITMAP(seen
, type
)) {
2981 EC_BGP_ATTRIBUTE_REPEATED
,
2982 "%s: error BGP attribute type %d appears twice in a message",
2985 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2986 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2987 ret
= BGP_ATTR_PARSE_ERROR
;
2991 /* Set type to bitmap to check duplicate attribute. `type' is
2992 unsigned char so it never overflow bitmap range. */
2994 SET_BITMAP(seen
, type
);
2996 /* Overflow check. */
2997 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2999 if (attr_endp
> endp
) {
3001 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3002 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3003 peer
->host
, type
, length
, size
, attr_endp
,
3007 * If any recognized attribute has an Attribute
3008 * Length that conflicts with the expected length
3009 * (based on the attribute type code), then the
3010 * Error Subcode MUST be set to Attribute Length
3011 * Error. The Data field MUST contain the erroneous
3012 * attribute (type, length, and value).
3014 * We do not currently have a good way to determine the
3015 * length of the attribute independent of the length
3016 * received in the message. Instead we send the
3017 * minimum between the amount of data we have and the
3018 * amount specified by the attribute length field.
3020 * Instead of directly passing in the packet buffer and
3021 * offset we use the stream_get* functions to read into
3022 * a stack buffer, since they perform bounds checking
3023 * and we are working with untrusted data.
3025 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
3026 memset(ndata
, 0x00, sizeof(ndata
));
3028 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3029 /* Rewind to end of flag field */
3030 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3032 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3034 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3036 size_t atl
= attr_endp
- startp
;
3037 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3038 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3040 bgp_notify_send_with_data(
3041 peer
, BGP_NOTIFY_UPDATE_ERR
,
3042 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3045 ret
= BGP_ATTR_PARSE_ERROR
;
3049 struct bgp_attr_parser_args attr_args
= {
3056 .total
= attr_endp
- startp
,
3060 /* If any recognized attribute has Attribute Flags that conflict
3061 with the Attribute Type Code, then the Error Subcode is set
3063 Attribute Flags Error. The Data field contains the erroneous
3064 attribute (type, length and value). */
3065 if (bgp_attr_flag_invalid(&attr_args
)) {
3066 ret
= bgp_attr_malformed(
3067 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3069 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3074 /* OK check attribute and store it's value. */
3076 case BGP_ATTR_ORIGIN
:
3077 ret
= bgp_attr_origin(&attr_args
);
3079 case BGP_ATTR_AS_PATH
:
3080 ret
= bgp_attr_aspath(&attr_args
);
3082 case BGP_ATTR_AS4_PATH
:
3083 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3085 case BGP_ATTR_NEXT_HOP
:
3086 ret
= bgp_attr_nexthop(&attr_args
);
3088 case BGP_ATTR_MULTI_EXIT_DISC
:
3089 ret
= bgp_attr_med(&attr_args
);
3091 case BGP_ATTR_LOCAL_PREF
:
3092 ret
= bgp_attr_local_pref(&attr_args
);
3094 case BGP_ATTR_ATOMIC_AGGREGATE
:
3095 ret
= bgp_attr_atomic(&attr_args
);
3097 case BGP_ATTR_AGGREGATOR
:
3098 ret
= bgp_attr_aggregator(&attr_args
);
3100 case BGP_ATTR_AS4_AGGREGATOR
:
3101 ret
= bgp_attr_as4_aggregator(&attr_args
,
3103 &as4_aggregator_addr
);
3105 case BGP_ATTR_COMMUNITIES
:
3106 ret
= bgp_attr_community(&attr_args
);
3108 case BGP_ATTR_LARGE_COMMUNITIES
:
3109 ret
= bgp_attr_large_community(&attr_args
);
3111 case BGP_ATTR_ORIGINATOR_ID
:
3112 ret
= bgp_attr_originator_id(&attr_args
);
3114 case BGP_ATTR_CLUSTER_LIST
:
3115 ret
= bgp_attr_cluster_list(&attr_args
);
3117 case BGP_ATTR_MP_REACH_NLRI
:
3118 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3120 case BGP_ATTR_MP_UNREACH_NLRI
:
3121 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3123 case BGP_ATTR_EXT_COMMUNITIES
:
3124 ret
= bgp_attr_ext_communities(&attr_args
);
3126 #ifdef ENABLE_BGP_VNC_ATTR
3129 case BGP_ATTR_ENCAP
:
3130 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3133 case BGP_ATTR_PREFIX_SID
:
3134 ret
= bgp_attr_prefix_sid(&attr_args
);
3136 case BGP_ATTR_PMSI_TUNNEL
:
3137 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3139 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3140 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3143 ret
= bgp_attr_unknown(&attr_args
);
3147 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3148 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3149 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3150 ret
= BGP_ATTR_PARSE_ERROR
;
3154 if (ret
== BGP_ATTR_PARSE_EOR
) {
3158 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3159 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3160 "%s: Attribute %s, parse error", peer
->host
,
3161 lookup_msg(attr_str
, type
, NULL
));
3164 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3166 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3167 "%s: Attribute %s, parse error - treating as withdrawal",
3168 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3172 /* Check the fetched length. */
3173 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3174 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3175 "%s: BGP attribute %s, fetch error",
3176 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3177 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3178 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3179 ret
= BGP_ATTR_PARSE_ERROR
;
3185 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3186 * About Prefix-SID path attribute,
3187 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3188 * may only appear in a BGP Prefix-SID attribute attached to
3189 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3190 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3192 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3193 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3195 /* Check final read pointer is same as end pointer. */
3196 if (BGP_INPUT_PNT(peer
) != endp
) {
3197 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3198 "%s: BGP attribute %s, length mismatch", peer
->host
,
3199 lookup_msg(attr_str
, type
, NULL
));
3200 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3201 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3203 ret
= BGP_ATTR_PARSE_ERROR
;
3208 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3209 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3210 * This is implemented below and will result in a NOTIFICATION. If the
3211 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3212 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3213 * message SHOULD NOT be sent. This is implemented elsewhere.
3215 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3216 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3217 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3218 * speaker that receives the message SHOULD ignore this attribute.
3220 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3221 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3222 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3223 ret
= BGP_ATTR_PARSE_ERROR
;
3228 /* Check all mandatory well-known attributes are present */
3229 if ((ret
= bgp_attr_check(peer
, attr
)) < 0)
3233 * At this place we can see whether we got AS4_PATH and/or
3234 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3235 * We can not do this before we've read all attributes because
3236 * the as4 handling does not say whether AS4_PATH has to be sent
3237 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3238 * in relationship to AGGREGATOR.
3239 * So, to be defensive, we are not relying on any order and read
3240 * all attributes first, including these 32bit ones, and now,
3241 * afterwards, we look what and if something is to be done for as4.
3243 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3246 /* actually... this doesn't ever return failure currently, but
3247 * better safe than sorry */
3248 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3249 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3250 &as4_aggregator_addr
)) {
3251 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3252 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3253 ret
= BGP_ATTR_PARSE_ERROR
;
3258 * Finally do the checks on the aspath we did not do yet
3259 * because we waited for a potentially synthesized aspath.
3261 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3262 ret
= bgp_attr_aspath_check(peer
, attr
);
3263 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3267 ret
= BGP_ATTR_PARSE_PROCEED
;
3271 * At this stage, we have done all fiddling with as4, and the
3272 * resulting info is in attr->aggregator resp. attr->aspath so
3273 * we can chuck as4_aggregator and as4_path alltogether in order
3278 * unintern - it is in the hash
3279 * The flag that we got this is still there, but that
3280 * does not do any trouble
3282 aspath_unintern(&as4_path
);
3285 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3286 /* Finally intern unknown attribute. */
3288 attr
->transit
= transit_intern(attr
->transit
);
3289 if (attr
->encap_subtlvs
)
3290 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3292 #ifdef ENABLE_BGP_VNC
3293 if (attr
->vnc_subtlvs
)
3294 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
3298 if (attr
->transit
) {
3299 transit_free(attr
->transit
);
3300 attr
->transit
= NULL
;
3303 bgp_attr_flush_encap(attr
);
3308 assert(attr
->transit
->refcnt
> 0);
3309 if (attr
->encap_subtlvs
)
3310 assert(attr
->encap_subtlvs
->refcnt
> 0);
3311 #ifdef ENABLE_BGP_VNC
3312 if (attr
->vnc_subtlvs
)
3313 assert(attr
->vnc_subtlvs
->refcnt
> 0);
3320 * Extract the tunnel type from extended community
3322 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3323 bgp_encap_types
*tunnel_type
)
3325 struct ecommunity
*ecom
;
3330 ecom
= attr
->ecommunity
;
3331 if (!ecom
|| !ecom
->size
)
3334 for (i
= 0; i
< ecom
->size
; i
++) {
3336 uint8_t type
, sub_type
;
3338 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3341 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3342 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3344 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3351 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3352 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3357 iana_safi_t pkt_safi
;
3360 /* Set extended bit always to encode the attribute length as 2 bytes */
3361 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3362 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3363 sizep
= stream_get_endp(s
);
3364 stream_putw(s
, 0); /* Marker: Attribute length. */
3367 /* Convert AFI, SAFI to values for packet. */
3368 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3370 stream_putw(s
, pkt_afi
); /* AFI */
3371 stream_putc(s
, pkt_safi
); /* SAFI */
3375 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3376 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3377 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3378 else if (safi
== SAFI_FLOWSPEC
)
3381 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3384 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3389 case SAFI_MULTICAST
:
3390 case SAFI_LABELED_UNICAST
:
3392 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3396 stream_putl(s
, 0); /* RD = 0, per RFC */
3398 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3403 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3406 if (attr
->mp_nexthop_len
== 0)
3407 stream_putc(s
, 0); /* no nexthop for flowspec */
3409 stream_putc(s
, attr
->mp_nexthop_len
);
3410 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3419 case SAFI_MULTICAST
:
3420 case SAFI_LABELED_UNICAST
:
3422 if (attr
->mp_nexthop_len
3423 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3425 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3426 stream_put(s
, &attr
->mp_nexthop_global
,
3428 stream_put(s
, &attr
->mp_nexthop_local
,
3431 stream_putc(s
, IPV6_MAX_BYTELEN
);
3432 stream_put(s
, &attr
->mp_nexthop_global
,
3436 case SAFI_MPLS_VPN
: {
3437 if (attr
->mp_nexthop_len
3438 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3440 stream_putl(s
, 0); /* RD = 0, per RFC */
3442 stream_put(s
, &attr
->mp_nexthop_global
,
3444 } else if (attr
->mp_nexthop_len
3445 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3447 stream_putl(s
, 0); /* RD = 0, per RFC */
3449 stream_put(s
, &attr
->mp_nexthop_global
,
3451 stream_putl(s
, 0); /* RD = 0, per RFC */
3453 stream_put(s
, &attr
->mp_nexthop_local
,
3458 stream_putc(s
, IPV6_MAX_BYTELEN
);
3459 stream_put(s
, &attr
->mp_nexthop_global
,
3463 stream_putc(s
, 0); /* no nexthop for flowspec */
3469 if (safi
!= SAFI_FLOWSPEC
)
3471 EC_BGP_ATTR_NH_SEND_LEN
,
3472 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3473 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3482 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3483 const struct prefix
*p
,
3484 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3485 uint32_t num_labels
, int addpath_encode
,
3486 uint32_t addpath_tx_id
, struct attr
*attr
)
3488 if (safi
== SAFI_MPLS_VPN
) {
3490 stream_putl(s
, addpath_tx_id
);
3491 /* Label, RD, Prefix write. */
3492 stream_putc(s
, p
->prefixlen
+ 88);
3493 stream_put(s
, label
, BGP_LABEL_BYTES
);
3494 stream_put(s
, prd
->val
, 8);
3495 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3496 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3497 /* EVPN prefix - contents depend on type */
3498 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3499 addpath_encode
, addpath_tx_id
);
3500 } else if (safi
== SAFI_LABELED_UNICAST
) {
3501 /* Prefix write with label. */
3502 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3504 } else if (safi
== SAFI_FLOWSPEC
) {
3505 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3506 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3507 p
->u
.prefix_flowspec
.prefixlen
);
3509 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3512 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3513 const struct prefix
*p
)
3515 int size
= PSIZE(p
->prefixlen
);
3516 if (safi
== SAFI_MPLS_VPN
)
3518 else if (safi
== SAFI_LABELED_UNICAST
)
3519 size
+= BGP_LABEL_BYTES
;
3520 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3521 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3527 * Encodes the tunnel encapsulation attribute,
3528 * and with ENABLE_BGP_VNC the VNC attribute which uses
3529 * almost the same TLV format
3531 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3532 struct stream
*s
, struct attr
*attr
,
3535 unsigned int attrlenfield
= 0;
3536 unsigned int attrhdrlen
= 0;
3537 struct bgp_attr_encap_subtlv
*subtlvs
;
3538 struct bgp_attr_encap_subtlv
*st
;
3539 const char *attrname
;
3541 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3542 && (!attr
->encap_tunneltype
3543 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3547 case BGP_ATTR_ENCAP
:
3548 attrname
= "Tunnel Encap";
3549 subtlvs
= attr
->encap_subtlvs
;
3550 if (subtlvs
== NULL
) /* nothing to do */
3553 * The tunnel encap attr has an "outer" tlv.
3555 * L = total length of subtlvs,
3556 * V = concatenated subtlvs.
3558 attrlenfield
= 2 + 2; /* T + L */
3559 attrhdrlen
= 1 + 1; /* subTLV T + L */
3562 #ifdef ENABLE_BGP_VNC_ATTR
3565 subtlvs
= attr
->vnc_subtlvs
;
3566 if (subtlvs
== NULL
) /* nothing to do */
3568 attrlenfield
= 0; /* no outer T + L */
3569 attrhdrlen
= 2 + 2; /* subTLV T + L */
3577 /* compute attr length */
3578 for (st
= subtlvs
; st
; st
= st
->next
) {
3579 attrlenfield
+= (attrhdrlen
+ st
->length
);
3582 if (attrlenfield
> 0xffff) {
3583 zlog_info("%s attribute is too long (length=%d), can't send it",
3584 attrname
, attrlenfield
);
3588 if (attrlenfield
> 0xff) {
3589 /* 2-octet length field */
3591 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3592 | BGP_ATTR_FLAG_EXTLEN
);
3593 stream_putc(s
, attrtype
);
3594 stream_putw(s
, attrlenfield
& 0xffff);
3596 /* 1-octet length field */
3597 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3598 stream_putc(s
, attrtype
);
3599 stream_putc(s
, attrlenfield
& 0xff);
3602 if (attrtype
== BGP_ATTR_ENCAP
) {
3603 /* write outer T+L */
3604 stream_putw(s
, attr
->encap_tunneltype
);
3605 stream_putw(s
, attrlenfield
- 4);
3608 /* write each sub-tlv */
3609 for (st
= subtlvs
; st
; st
= st
->next
) {
3610 if (attrtype
== BGP_ATTR_ENCAP
) {
3611 stream_putc(s
, st
->type
);
3612 stream_putc(s
, st
->length
);
3613 #ifdef ENABLE_BGP_VNC
3615 stream_putw(s
, st
->type
);
3616 stream_putw(s
, st
->length
);
3619 stream_put(s
, st
->value
, st
->length
);
3623 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3625 /* Set MP attribute length. Don't count the (2) bytes used to encode
3627 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3630 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3632 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3633 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3634 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3635 PEER_FLAG_REMOVE_PRIVATE_AS
)
3636 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3637 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3638 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3639 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3640 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3641 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3646 /* Make attribute packet. */
3647 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3648 struct stream
*s
, struct attr
*attr
,
3649 struct bpacket_attr_vec_arr
*vecarr
,
3650 struct prefix
*p
, afi_t afi
, safi_t safi
,
3651 struct peer
*from
, struct prefix_rd
*prd
,
3652 mpls_label_t
*label
, uint32_t num_labels
,
3653 int addpath_encode
, uint32_t addpath_tx_id
)
3656 size_t aspath_sizep
;
3657 struct aspath
*aspath
;
3658 int send_as4_path
= 0;
3659 int send_as4_aggregator
= 0;
3660 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3665 /* Remember current pointer. */
3666 cp
= stream_get_endp(s
);
3669 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3670 && !peer_cap_enhe(peer
, afi
, safi
))) {
3671 size_t mpattrlen_pos
= 0;
3673 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3675 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3676 num_labels
, addpath_encode
,
3677 addpath_tx_id
, attr
);
3678 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3681 /* Origin attribute. */
3682 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3683 stream_putc(s
, BGP_ATTR_ORIGIN
);
3685 stream_putc(s
, attr
->origin
);
3687 /* AS path attribute. */
3689 /* If remote-peer is EBGP */
3690 if (peer
->sort
== BGP_PEER_EBGP
3691 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3692 PEER_FLAG_AS_PATH_UNCHANGED
)
3693 || attr
->aspath
->segments
== NULL
)
3694 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3695 PEER_FLAG_RSERVER_CLIENT
))) {
3696 aspath
= aspath_dup(attr
->aspath
);
3698 /* Even though we may not be configured for confederations we
3700 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3701 aspath
= aspath_delete_confed_seq(aspath
);
3703 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3704 /* Stuff our path CONFED_ID on the front */
3705 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3707 if (peer
->change_local_as
) {
3708 /* If replace-as is specified, we only use the
3709 change_local_as when
3710 advertising routes. */
3711 if (!CHECK_FLAG(peer
->flags
,
3712 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3713 if (bgp_append_local_as(peer
, afi
,
3715 aspath
= aspath_add_seq(
3716 aspath
, peer
->local_as
);
3717 aspath
= aspath_add_seq(aspath
,
3718 peer
->change_local_as
);
3720 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3723 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3724 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3726 aspath
= aspath_dup(attr
->aspath
);
3727 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3729 aspath
= attr
->aspath
;
3731 /* If peer is not AS4 capable, then:
3732 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3733 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3735 * types are in it (i.e. exclude them if they are there)
3736 * AND do this only if there is at least one asnum > 65535 in the
3738 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3740 * all ASnums > 65535 to BGP_AS_TRANS
3743 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3744 stream_putc(s
, BGP_ATTR_AS_PATH
);
3745 aspath_sizep
= stream_get_endp(s
);
3747 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3749 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3752 if (!use32bit
&& aspath_has_as4(aspath
))
3754 1; /* we'll do this later, at the correct place */
3756 /* Nexthop attribute. */
3757 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3758 && !peer_cap_enhe(peer
, afi
, safi
)) {
3759 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3761 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3762 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3763 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3764 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3767 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3768 } else if (peer_cap_enhe(from
, afi
, safi
)
3769 || (nh_afi
== AFI_IP6
)) {
3771 * Likely this is the case when an IPv4 prefix was
3772 * received with Extended Next-hop capability in this
3773 * or another vrf and is now being advertised to
3774 * non-ENHE peers. Since peer_cap_enhe only checks
3775 * peers in this vrf, also check the nh_afi to catch
3776 * the case where the originator was in another vrf.
3777 * Setting the mandatory (ipv4) next-hop attribute here
3778 * to enable implicit next-hop self with correct A-F
3779 * (ipv4 address family).
3781 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3782 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3783 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3786 stream_put_ipv4(s
, 0);
3790 /* MED attribute. */
3791 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3792 || bgp
->maxmed_active
) {
3793 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3794 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3796 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3800 /* Local preference. */
3801 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3802 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3803 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3805 stream_putl(s
, attr
->local_pref
);
3808 /* Atomic aggregate. */
3809 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3810 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3811 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3816 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3817 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3818 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3819 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3822 /* AS4 capable peer */
3824 stream_putl(s
, attr
->aggregator_as
);
3826 /* 2-byte AS peer */
3829 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3831 if (attr
->aggregator_as
> 65535) {
3832 stream_putw(s
, BGP_AS_TRANS
);
3834 /* we have to send AS4_AGGREGATOR, too.
3835 * we'll do that later in order to send
3836 * attributes in ascending
3839 send_as4_aggregator
= 1;
3841 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3843 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3846 /* Community attribute. */
3847 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3848 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3849 if (attr
->community
->size
* 4 > 255) {
3851 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3852 | BGP_ATTR_FLAG_EXTLEN
);
3853 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3854 stream_putw(s
, attr
->community
->size
* 4);
3857 BGP_ATTR_FLAG_OPTIONAL
3858 | BGP_ATTR_FLAG_TRANS
);
3859 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3860 stream_putc(s
, attr
->community
->size
* 4);
3862 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3866 * Large Community attribute.
3868 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3869 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3870 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3871 if (lcom_length(attr
->lcommunity
) > 255) {
3873 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3874 | BGP_ATTR_FLAG_EXTLEN
);
3875 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3876 stream_putw(s
, lcom_length(attr
->lcommunity
));
3879 BGP_ATTR_FLAG_OPTIONAL
3880 | BGP_ATTR_FLAG_TRANS
);
3881 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3882 stream_putc(s
, lcom_length(attr
->lcommunity
));
3884 stream_put(s
, attr
->lcommunity
->val
,
3885 lcom_length(attr
->lcommunity
));
3888 /* Route Reflector. */
3889 if (peer
->sort
== BGP_PEER_IBGP
&& from
3890 && from
->sort
== BGP_PEER_IBGP
) {
3891 /* Originator ID. */
3892 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3893 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3896 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3897 stream_put_in_addr(s
, &attr
->originator_id
);
3899 stream_put_in_addr(s
, &from
->remote_id
);
3902 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3903 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3905 if (attr
->cluster
) {
3906 stream_putc(s
, attr
->cluster
->length
+ 4);
3907 /* If this peer configuration's parent BGP has
3909 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3910 stream_put_in_addr(s
, &bgp
->cluster_id
);
3912 stream_put_in_addr(s
, &bgp
->router_id
);
3913 stream_put(s
, attr
->cluster
->list
,
3914 attr
->cluster
->length
);
3917 /* If this peer configuration's parent BGP has
3919 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3920 stream_put_in_addr(s
, &bgp
->cluster_id
);
3922 stream_put_in_addr(s
, &bgp
->router_id
);
3926 /* Extended Communities attribute. */
3927 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3928 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3929 if (peer
->sort
== BGP_PEER_IBGP
3930 || peer
->sort
== BGP_PEER_CONFED
) {
3931 if (attr
->ecommunity
->size
* 8 > 255) {
3933 BGP_ATTR_FLAG_OPTIONAL
3934 | BGP_ATTR_FLAG_TRANS
3935 | BGP_ATTR_FLAG_EXTLEN
);
3936 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3937 stream_putw(s
, attr
->ecommunity
->size
* 8);
3940 BGP_ATTR_FLAG_OPTIONAL
3941 | BGP_ATTR_FLAG_TRANS
);
3942 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3943 stream_putc(s
, attr
->ecommunity
->size
* 8);
3945 stream_put(s
, attr
->ecommunity
->val
,
3946 attr
->ecommunity
->size
* 8);
3950 int ecom_tr_size
= 0;
3953 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3954 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3957 if (CHECK_FLAG(tbit
,
3958 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3965 if (ecom_tr_size
* 8 > 255) {
3968 BGP_ATTR_FLAG_OPTIONAL
3969 | BGP_ATTR_FLAG_TRANS
3970 | BGP_ATTR_FLAG_EXTLEN
);
3972 BGP_ATTR_EXT_COMMUNITIES
);
3973 stream_putw(s
, ecom_tr_size
* 8);
3977 BGP_ATTR_FLAG_OPTIONAL
3978 | BGP_ATTR_FLAG_TRANS
);
3980 BGP_ATTR_EXT_COMMUNITIES
);
3981 stream_putc(s
, ecom_tr_size
* 8);
3984 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3985 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3990 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3993 stream_put(s
, pnt
, 8);
3999 /* Label index attribute. */
4000 if (safi
== SAFI_LABELED_UNICAST
) {
4001 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4002 uint32_t label_index
;
4004 label_index
= attr
->label_index
;
4006 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4008 BGP_ATTR_FLAG_OPTIONAL
4009 | BGP_ATTR_FLAG_TRANS
);
4010 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4012 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4014 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4015 stream_putc(s
, 0); // reserved
4016 stream_putw(s
, 0); // flags
4017 stream_putl(s
, label_index
);
4022 /* SRv6 Service Information Attribute. */
4023 if (afi
== AFI_IP
&& safi
== SAFI_MPLS_VPN
) {
4024 if (attr
->srv6_l3vpn
) {
4025 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4026 | BGP_ATTR_FLAG_TRANS
);
4027 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4028 stream_putc(s
, 24); /* tlv len */
4029 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4030 stream_putw(s
, 21); /* sub-tlv len */
4031 stream_putc(s
, 0); /* reserved */
4032 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4033 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4034 stream_putc(s
, 0); /* sid_flags */
4035 stream_putw(s
, 0xffff); /* endpoint */
4036 stream_putc(s
, 0); /* reserved */
4037 } else if (attr
->srv6_vpn
) {
4038 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4039 | BGP_ATTR_FLAG_TRANS
);
4040 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4041 stream_putc(s
, 22); /* tlv len */
4042 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4043 stream_putw(s
, 0x13); /* tlv len */
4044 stream_putc(s
, 0x00); /* reserved */
4045 stream_putc(s
, 0x01); /* sid_type */
4046 stream_putc(s
, 0x00); /* sif_flags */
4047 stream_put(s
, &attr
->srv6_vpn
->sid
,
4048 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4052 if (send_as4_path
) {
4053 /* If the peer is NOT As4 capable, AND */
4054 /* there are ASnums > 65535 in path THEN
4055 * give out AS4_PATH */
4057 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4059 * Hm, I wonder... confederation things *should* only be at
4060 * the beginning of an aspath, right? Then we should use
4061 * aspath_delete_confed_seq for this, because it is already
4063 * Folks, talk to me: what is reasonable here!?
4065 aspath
= aspath_delete_confed_seq(aspath
);
4068 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4069 | BGP_ATTR_FLAG_EXTLEN
);
4070 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4071 aspath_sizep
= stream_get_endp(s
);
4073 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4076 if (aspath
!= attr
->aspath
)
4077 aspath_free(aspath
);
4079 if (send_as4_aggregator
) {
4080 /* send AS4_AGGREGATOR, at this place */
4081 /* this section of code moved here in order to ensure the
4083 * *ascending* order of attributes
4085 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4086 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4088 stream_putl(s
, attr
->aggregator_as
);
4089 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4092 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4093 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4094 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4095 /* Tunnel Encap attribute */
4096 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4098 #ifdef ENABLE_BGP_VNC_ATTR
4100 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4105 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4106 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4107 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4108 stream_putc(s
, 9); // Length
4109 stream_putc(s
, 0); // Flags
4110 stream_putc(s
, attr
->pmsi_tnl_type
);
4111 stream_put(s
, &(attr
->label
),
4112 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4113 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4114 // Unicast tunnel endpoint IP address
4117 /* Unknown transit attribute. */
4119 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
4121 /* Return total size of attribute. */
4122 return stream_get_endp(s
) - cp
;
4125 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4127 unsigned long attrlen_pnt
;
4129 iana_safi_t pkt_safi
;
4131 /* Set extended bit always to encode the attribute length as 2 bytes */
4132 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4133 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4135 attrlen_pnt
= stream_get_endp(s
);
4136 stream_putw(s
, 0); /* Length of this attribute. */
4138 /* Convert AFI, SAFI to values for packet. */
4139 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4141 stream_putw(s
, pkt_afi
);
4142 stream_putc(s
, pkt_safi
);
4147 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4148 afi_t afi
, safi_t safi
,
4149 const struct prefix_rd
*prd
,
4150 mpls_label_t
*label
, uint32_t num_labels
,
4151 int addpath_encode
, uint32_t addpath_tx_id
,
4154 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4156 if (safi
== SAFI_LABELED_UNICAST
) {
4157 label
= (mpls_label_t
*)wlabel
;
4161 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4162 addpath_encode
, addpath_tx_id
, attr
);
4165 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4167 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4170 /* Initialization of attribute. */
4171 void bgp_attr_init(void)
4184 void bgp_attr_finish(void)
4189 ecommunity_finish();
4190 lcommunity_finish();
4197 /* Make attribute packet. */
4198 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4199 const struct prefix
*prefix
)
4204 struct aspath
*aspath
;
4205 int addpath_encode
= 0;
4206 uint32_t addpath_tx_id
= 0;
4208 /* Remember current pointer. */
4209 cp
= stream_get_endp(s
);
4211 /* Place holder of length. */
4214 /* Origin attribute. */
4215 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4216 stream_putc(s
, BGP_ATTR_ORIGIN
);
4218 stream_putc(s
, attr
->origin
);
4220 aspath
= attr
->aspath
;
4222 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4223 stream_putc(s
, BGP_ATTR_AS_PATH
);
4224 aspath_lenp
= stream_get_endp(s
);
4227 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4229 /* Nexthop attribute. */
4230 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4231 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4232 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4233 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4235 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4238 /* MED attribute. */
4239 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4240 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4241 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4243 stream_putl(s
, attr
->med
);
4246 /* Local preference. */
4247 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4248 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4249 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4251 stream_putl(s
, attr
->local_pref
);
4254 /* Atomic aggregate. */
4255 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4256 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4257 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4262 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4263 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4264 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4266 stream_putl(s
, attr
->aggregator_as
);
4267 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4270 /* Community attribute. */
4271 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4272 if (attr
->community
->size
* 4 > 255) {
4274 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4275 | BGP_ATTR_FLAG_EXTLEN
);
4276 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4277 stream_putw(s
, attr
->community
->size
* 4);
4280 BGP_ATTR_FLAG_OPTIONAL
4281 | BGP_ATTR_FLAG_TRANS
);
4282 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4283 stream_putc(s
, attr
->community
->size
* 4);
4285 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4288 /* Large Community attribute. */
4289 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4290 if (lcom_length(attr
->lcommunity
) > 255) {
4292 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4293 | BGP_ATTR_FLAG_EXTLEN
);
4294 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4295 stream_putw(s
, lcom_length(attr
->lcommunity
));
4298 BGP_ATTR_FLAG_OPTIONAL
4299 | BGP_ATTR_FLAG_TRANS
);
4300 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4301 stream_putc(s
, lcom_length(attr
->lcommunity
));
4304 stream_put(s
, attr
->lcommunity
->val
,
4305 lcom_length(attr
->lcommunity
));
4308 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4309 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4310 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4311 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4314 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4315 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4316 sizep
= stream_get_endp(s
);
4319 stream_putc(s
, 0); /* Marker: Attribute length. */
4320 stream_putw(s
, AFI_IP6
); /* AFI */
4321 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4324 stream_putc(s
, attr
->mp_nexthop_len
);
4325 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4326 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4327 stream_put(s
, &attr
->mp_nexthop_local
,
4334 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
4337 /* Set MP attribute length. */
4338 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4342 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4343 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4345 BGP_ATTR_FLAG_OPTIONAL
4346 | BGP_ATTR_FLAG_TRANS
);
4347 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4349 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4350 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4351 stream_putc(s
, 0); // reserved
4352 stream_putw(s
, 0); // flags
4353 stream_putl(s
, attr
->label_index
);
4357 /* Return total size of attribute. */
4358 len
= stream_get_endp(s
) - cp
- 2;
4359 stream_putw_at(s
, cp
, len
);