1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_errors.h"
44 #include "bgpd/bgp_label.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_ecommunity.h"
47 #include "bgpd/bgp_lcommunity.h"
48 #include "bgpd/bgp_updgrp.h"
49 #include "bgpd/bgp_encap_types.h"
51 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
52 #include "bgp_encap_types.h"
53 #include "bgp_vnc_types.h"
56 #include "bgp_flowspec_private.h"
59 /* Attribute strings for logging. */
60 static const struct message attr_str
[] = {
61 {BGP_ATTR_ORIGIN
, "ORIGIN"},
62 {BGP_ATTR_AS_PATH
, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
71 {BGP_ATTR_DPA
, "DPA"},
72 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
73 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
74 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
75 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
76 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
77 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
78 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
79 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
80 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
81 {BGP_ATTR_ENCAP
, "ENCAP"},
82 #if ENABLE_BGP_VNC_ATTR
83 {BGP_ATTR_VNC
, "VNC"},
85 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
86 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
89 static const struct message attr_flag_str
[] = {
90 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
91 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
92 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
93 /* bgp_attr_flags_diagnose() relies on this bit being last in
95 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
98 static struct hash
*cluster_hash
;
100 static void *cluster_hash_alloc(void *p
)
102 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
103 struct cluster_list
*cluster
;
105 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
106 cluster
->length
= val
->length
;
108 if (cluster
->length
) {
109 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
110 memcpy(cluster
->list
, val
->list
, val
->length
);
112 cluster
->list
= NULL
;
119 /* Cluster list related functions. */
120 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
122 struct cluster_list tmp
;
123 struct cluster_list
*cluster
;
128 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
133 int cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
137 for (i
= 0; i
< cluster
->length
/ 4; i
++)
138 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
143 static unsigned int cluster_hash_key_make(const void *p
)
145 const struct cluster_list
*cluster
= p
;
147 return jhash(cluster
->list
, cluster
->length
, 0);
150 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
152 const struct cluster_list
*cluster1
= p1
;
153 const struct cluster_list
*cluster2
= p2
;
155 return (cluster1
->length
== cluster2
->length
156 && (cluster1
->list
== cluster2
->list
157 || memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
)
161 static void cluster_free(struct cluster_list
*cluster
)
163 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
164 XFREE(MTYPE_CLUSTER
, cluster
);
167 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
169 struct cluster_list
*find
;
171 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
177 void cluster_unintern(struct cluster_list
*cluster
)
182 if (cluster
->refcnt
== 0) {
183 hash_release(cluster_hash
, cluster
);
184 cluster_free(cluster
);
188 static void cluster_init(void)
190 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
194 static void cluster_finish(void)
196 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
197 hash_free(cluster_hash
);
201 static struct hash
*encap_hash
= NULL
;
203 static struct hash
*vnc_hash
= NULL
;
205 static struct hash
*srv6_l3vpn_hash
;
206 static struct hash
*srv6_vpn_hash
;
208 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
210 struct bgp_attr_encap_subtlv
*new;
211 struct bgp_attr_encap_subtlv
*tail
;
212 struct bgp_attr_encap_subtlv
*p
;
214 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
215 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
217 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
220 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
223 memcpy(tail
, p
, size
);
230 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
232 struct bgp_attr_encap_subtlv
*next
;
236 XFREE(MTYPE_ENCAP_TLV
, p
);
241 void bgp_attr_flush_encap(struct attr
*attr
)
246 if (attr
->encap_subtlvs
) {
247 encap_free(attr
->encap_subtlvs
);
248 attr
->encap_subtlvs
= NULL
;
251 if (attr
->vnc_subtlvs
) {
252 encap_free(attr
->vnc_subtlvs
);
253 attr
->vnc_subtlvs
= NULL
;
259 * Compare encap sub-tlv chains
264 * This algorithm could be made faster if needed
266 static int encap_same(const struct bgp_attr_encap_subtlv
*h1
,
267 const struct bgp_attr_encap_subtlv
*h2
)
269 const struct bgp_attr_encap_subtlv
*p
;
270 const struct bgp_attr_encap_subtlv
*q
;
274 if (h1
== NULL
|| h2
== NULL
)
277 for (p
= h1
; p
; p
= p
->next
) {
278 for (q
= h2
; q
; q
= q
->next
) {
279 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
280 && !memcmp(p
->value
, q
->value
, p
->length
)) {
289 for (p
= h2
; p
; p
= p
->next
) {
290 for (q
= h1
; q
; q
= q
->next
) {
291 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
292 && !memcmp(p
->value
, q
->value
, p
->length
)) {
304 static void *encap_hash_alloc(void *p
)
306 /* Encap structure is already allocated. */
317 static struct bgp_attr_encap_subtlv
*
318 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
320 struct bgp_attr_encap_subtlv
*find
;
321 struct hash
*hash
= encap_hash
;
323 if (type
== VNC_SUBTLV_TYPE
)
327 find
= hash_get(hash
, encap
, encap_hash_alloc
);
335 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
336 encap_subtlv_type type
)
338 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
342 if (encap
->refcnt
== 0) {
343 struct hash
*hash
= encap_hash
;
345 if (type
== VNC_SUBTLV_TYPE
)
348 hash_release(hash
, encap
);
354 static unsigned int encap_hash_key_make(const void *p
)
356 const struct bgp_attr_encap_subtlv
*encap
= p
;
358 return jhash(encap
->value
, encap
->length
, 0);
361 static bool encap_hash_cmp(const void *p1
, const void *p2
)
363 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
364 (const struct bgp_attr_encap_subtlv
*)p2
);
367 static void encap_init(void)
369 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
372 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
377 static void encap_finish(void)
379 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
380 hash_free(encap_hash
);
383 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
389 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
397 return !memcmp(&(a1
->evpn_overlay
), &(a2
->evpn_overlay
),
398 sizeof(struct bgp_route_evpn
));
401 /* Unknown transit attribute. */
402 static struct hash
*transit_hash
;
404 static void transit_free(struct transit
*transit
)
406 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
407 XFREE(MTYPE_TRANSIT
, transit
);
410 static void *transit_hash_alloc(void *p
)
412 /* Transit structure is already allocated. */
416 static struct transit
*transit_intern(struct transit
*transit
)
418 struct transit
*find
;
420 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
422 transit_free(transit
);
428 static void transit_unintern(struct transit
**transit
)
430 if ((*transit
)->refcnt
)
431 (*transit
)->refcnt
--;
433 if ((*transit
)->refcnt
== 0) {
434 hash_release(transit_hash
, *transit
);
435 transit_free(*transit
);
440 static void *srv6_l3vpn_hash_alloc(void *p
)
445 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
447 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
450 static struct bgp_attr_srv6_l3vpn
*
451 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
453 struct bgp_attr_srv6_l3vpn
*find
;
455 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
457 srv6_l3vpn_free(l3vpn
);
462 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
464 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
469 if (l3vpn
->refcnt
== 0) {
470 hash_release(srv6_l3vpn_hash
, l3vpn
);
471 srv6_l3vpn_free(l3vpn
);
476 static void *srv6_vpn_hash_alloc(void *p
)
481 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
483 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
486 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
488 struct bgp_attr_srv6_vpn
*find
;
490 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
497 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
499 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
504 if (vpn
->refcnt
== 0) {
505 hash_release(srv6_vpn_hash
, vpn
);
511 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
513 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
516 key
= jhash(&l3vpn
->sid
, 16, key
);
517 key
= jhash_1word(l3vpn
->sid_flags
, key
);
518 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
522 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
524 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
525 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
527 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
528 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
529 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
;
532 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
533 const struct bgp_attr_srv6_l3vpn
*h2
)
537 else if (h1
== NULL
|| h2
== NULL
)
540 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
543 static unsigned int srv6_vpn_hash_key_make(const void *p
)
545 const struct bgp_attr_srv6_vpn
*vpn
= p
;
548 key
= jhash(&vpn
->sid
, 16, key
);
549 key
= jhash_1word(vpn
->sid_flags
, key
);
553 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
555 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
556 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
558 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
559 && vpn1
->sid_flags
== vpn2
->sid_flags
;
562 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
563 const struct bgp_attr_srv6_vpn
*h2
)
567 else if (h1
== NULL
|| h2
== NULL
)
570 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
573 static void srv6_init(void)
576 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
577 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
578 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
579 "BGP Prefix-SID SRv6-VPN-Service-TLV");
582 static void srv6_finish(void)
584 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
585 hash_free(srv6_l3vpn_hash
);
586 srv6_l3vpn_hash
= NULL
;
587 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
588 hash_free(srv6_vpn_hash
);
589 srv6_vpn_hash
= NULL
;
592 static unsigned int transit_hash_key_make(const void *p
)
594 const struct transit
*transit
= p
;
596 return jhash(transit
->val
, transit
->length
, 0);
599 static bool transit_hash_cmp(const void *p1
, const void *p2
)
601 const struct transit
*transit1
= p1
;
602 const struct transit
*transit2
= p2
;
604 return (transit1
->length
== transit2
->length
605 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
608 static void transit_init(void)
610 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
614 static void transit_finish(void)
616 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
617 hash_free(transit_hash
);
621 /* Attribute hash routines. */
622 static struct hash
*attrhash
;
624 unsigned long int attr_count(void)
626 return attrhash
->count
;
629 unsigned long int attr_unknown_count(void)
631 return transit_hash
->count
;
634 unsigned int attrhash_key_make(const void *p
)
636 const struct attr
*attr
= (struct attr
*)p
;
638 #define MIX(val) key = jhash_1word(val, key)
639 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
641 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
642 MIX3(attr
->local_pref
, attr
->aggregator_as
,
643 attr
->aggregator_addr
.s_addr
);
644 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
645 attr
->originator_id
.s_addr
);
646 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
649 MIX(aspath_key_make(attr
->aspath
));
651 MIX(community_hash_make(attr
->community
));
653 if (attr
->lcommunity
)
654 MIX(lcommunity_hash_make(attr
->lcommunity
));
655 if (attr
->ecommunity
)
656 MIX(ecommunity_hash_make(attr
->ecommunity
));
658 MIX(cluster_hash_key_make(attr
->cluster
));
660 MIX(transit_hash_key_make(attr
->transit
));
661 if (attr
->encap_subtlvs
)
662 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
664 if (attr
->vnc_subtlvs
)
665 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
667 MIX(attr
->mp_nexthop_len
);
668 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
669 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
670 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
671 MIX(attr
->rmap_table_id
);
676 bool attrhash_cmp(const void *p1
, const void *p2
)
678 const struct attr
*attr1
= p1
;
679 const struct attr
*attr2
= p2
;
681 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
682 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
683 && attr1
->aspath
== attr2
->aspath
684 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
685 && attr1
->local_pref
== attr2
->local_pref
686 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
687 if (attr1
->aggregator_as
== attr2
->aggregator_as
688 && attr1
->aggregator_addr
.s_addr
689 == attr2
->aggregator_addr
.s_addr
690 && attr1
->weight
== attr2
->weight
691 && attr1
->tag
== attr2
->tag
692 && attr1
->label_index
== attr2
->label_index
693 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
694 && attr1
->ecommunity
== attr2
->ecommunity
695 && attr1
->lcommunity
== attr2
->lcommunity
696 && attr1
->cluster
== attr2
->cluster
697 && attr1
->transit
== attr2
->transit
698 && attr1
->rmap_table_id
== attr2
->rmap_table_id
699 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
700 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
702 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
704 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
705 &attr2
->mp_nexthop_global
)
706 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
707 &attr2
->mp_nexthop_local
)
708 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
709 &attr2
->mp_nexthop_global_in
)
710 && IPV4_ADDR_SAME(&attr1
->originator_id
,
711 &attr2
->originator_id
)
712 && overlay_index_same(attr1
, attr2
)
713 && attr1
->nh_ifindex
== attr2
->nh_ifindex
714 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
715 && attr1
->distance
== attr2
->distance
716 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
717 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
))
724 static void attrhash_init(void)
727 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
731 * special for hash_clean below
733 static void attr_vfree(void *attr
)
735 XFREE(MTYPE_ATTR
, attr
);
738 static void attrhash_finish(void)
740 hash_clean(attrhash
, attr_vfree
);
745 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
747 struct attr
*attr
= bucket
->data
;
748 char sid_str
[BUFSIZ
];
750 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
751 inet_ntoa(attr
->nexthop
));
754 if (attr
->srv6_l3vpn
)
755 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
756 else if (attr
->srv6_vpn
)
757 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
761 " med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
762 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
763 attr
->weight
, attr
->label
, sid_str
);
766 void attr_show_all(struct vty
*vty
)
768 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
769 void *))attr_show_all_iterator
,
773 static void *bgp_attr_hash_alloc(void *p
)
775 struct attr
*val
= (struct attr
*)p
;
778 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
780 if (val
->encap_subtlvs
) {
781 val
->encap_subtlvs
= NULL
;
784 if (val
->vnc_subtlvs
) {
785 val
->vnc_subtlvs
= NULL
;
789 val
->srv6_l3vpn
= NULL
;
791 val
->srv6_vpn
= NULL
;
797 /* Internet argument attribute. */
798 struct attr
*bgp_attr_intern(struct attr
*attr
)
802 /* Intern referenced strucutre. */
804 if (!attr
->aspath
->refcnt
)
805 attr
->aspath
= aspath_intern(attr
->aspath
);
807 attr
->aspath
->refcnt
++;
809 if (attr
->community
) {
810 if (!attr
->community
->refcnt
)
811 attr
->community
= community_intern(attr
->community
);
813 attr
->community
->refcnt
++;
816 if (attr
->ecommunity
) {
817 if (!attr
->ecommunity
->refcnt
)
818 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
820 attr
->ecommunity
->refcnt
++;
822 if (attr
->lcommunity
) {
823 if (!attr
->lcommunity
->refcnt
)
824 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
826 attr
->lcommunity
->refcnt
++;
829 if (!attr
->cluster
->refcnt
)
830 attr
->cluster
= cluster_intern(attr
->cluster
);
832 attr
->cluster
->refcnt
++;
835 if (!attr
->transit
->refcnt
)
836 attr
->transit
= transit_intern(attr
->transit
);
838 attr
->transit
->refcnt
++;
840 if (attr
->encap_subtlvs
) {
841 if (!attr
->encap_subtlvs
->refcnt
)
842 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
845 attr
->encap_subtlvs
->refcnt
++;
847 if (attr
->srv6_l3vpn
) {
848 if (!attr
->srv6_l3vpn
->refcnt
)
849 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
851 attr
->srv6_l3vpn
->refcnt
++;
853 if (attr
->srv6_vpn
) {
854 if (!attr
->srv6_vpn
->refcnt
)
855 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
857 attr
->srv6_vpn
->refcnt
++;
860 if (attr
->vnc_subtlvs
) {
861 if (!attr
->vnc_subtlvs
->refcnt
)
862 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
865 attr
->vnc_subtlvs
->refcnt
++;
869 /* At this point, attr only contains intern'd pointers. that means
870 * if we find it in attrhash, it has all the same pointers and we
871 * correctly updated the refcounts on these.
872 * If we don't find it, we need to allocate a one because in all
873 * cases this returns a new reference to a hashed attr, but the input
875 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
881 /* Make network statement's attribute. */
882 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
884 memset(attr
, 0, sizeof(struct attr
));
886 attr
->origin
= origin
;
887 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
888 attr
->aspath
= aspath_empty();
889 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
890 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
892 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
893 attr
->label
= MPLS_INVALID_LABEL
;
894 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
895 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
900 /* Create the attributes for an aggregate */
901 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, uint8_t origin
,
902 struct aspath
*aspath
,
903 struct community
*community
,
904 struct ecommunity
*ecommunity
,
905 struct lcommunity
*lcommunity
,
906 struct bgp_aggregate
*aggregate
,
907 uint8_t atomic_aggregate
,
914 memset(&attr
, 0, sizeof(struct attr
));
916 /* Origin attribute. */
917 attr
.origin
= origin
;
918 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
920 /* AS path attribute. */
922 attr
.aspath
= aspath_intern(aspath
);
924 attr
.aspath
= aspath_empty();
925 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
927 /* Next hop attribute. */
928 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
931 uint32_t gshut
= COMMUNITY_GSHUT
;
933 /* If we are not shutting down ourselves and we are
934 * aggregating a route that contains the GSHUT community we
935 * need to remove that community when creating the aggregate */
936 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
)
937 && community_include(community
, gshut
)) {
938 community_del_val(community
, &gshut
);
941 attr
.community
= community
;
942 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
946 attr
.ecommunity
= ecommunity
;
947 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
951 attr
.lcommunity
= lcommunity
;
952 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
955 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
956 bgp_attr_add_gshut_community(&attr
);
958 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
959 attr
.label
= MPLS_INVALID_LABEL
;
960 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
961 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
962 if (!aggregate
->as_set
|| atomic_aggregate
)
963 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
964 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
965 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
966 attr
.aggregator_as
= bgp
->confed_id
;
968 attr
.aggregator_as
= bgp
->as
;
969 attr
.aggregator_addr
= bgp
->router_id
;
970 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
971 attr
.label
= MPLS_INVALID_LABEL
;
973 /* Apply route-map */
974 if (aggregate
->rmap
.name
) {
975 struct attr attr_tmp
= attr
;
976 struct bgp_path_info rmap_path
;
978 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
979 rmap_path
.peer
= bgp
->peer_self
;
980 rmap_path
.attr
= &attr_tmp
;
982 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
984 ret
= route_map_apply(aggregate
->rmap
.map
, p
, RMAP_BGP
,
987 bgp
->peer_self
->rmap_type
= 0;
989 if (ret
== RMAP_DENYMATCH
) {
990 /* Free uninterned attribute. */
991 bgp_attr_flush(&attr_tmp
);
993 /* Unintern original. */
994 aspath_unintern(&attr
.aspath
);
998 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
999 bgp_attr_add_gshut_community(&attr_tmp
);
1001 new = bgp_attr_intern(&attr_tmp
);
1004 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
1005 bgp_attr_add_gshut_community(&attr
);
1007 new = bgp_attr_intern(&attr
);
1010 aspath_unintern(&new->aspath
);
1014 /* Unintern just the sub-components of the attr, but not the attr */
1015 void bgp_attr_unintern_sub(struct attr
*attr
)
1017 /* aspath refcount shoud be decrement. */
1019 aspath_unintern(&attr
->aspath
);
1020 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1022 if (attr
->community
)
1023 community_unintern(&attr
->community
);
1024 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1026 if (attr
->ecommunity
)
1027 ecommunity_unintern(&attr
->ecommunity
);
1028 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1030 if (attr
->lcommunity
)
1031 lcommunity_unintern(&attr
->lcommunity
);
1032 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1035 cluster_unintern(attr
->cluster
);
1036 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1039 transit_unintern(&attr
->transit
);
1041 if (attr
->encap_subtlvs
)
1042 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1045 if (attr
->vnc_subtlvs
)
1046 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1049 if (attr
->srv6_l3vpn
)
1050 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1053 srv6_vpn_unintern(&attr
->srv6_vpn
);
1057 * We have some show commands that let you experimentally
1058 * apply a route-map. When we apply the route-map
1059 * we are reseting values but not saving them for
1060 * posterity via intern'ing( because route-maps don't
1061 * do that) but at this point in time we need
1062 * to compare the new attr to the old and if the
1063 * routemap has changed it we need to, as Snoop Dog says,
1064 * Drop it like it's hot
1066 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
1068 if (new->aspath
!= old
->aspath
)
1069 aspath_free(new->aspath
);
1071 if (new->community
!= old
->community
)
1072 community_free(&new->community
);
1074 if (new->ecommunity
!= old
->ecommunity
)
1075 ecommunity_free(&new->ecommunity
);
1077 if (new->lcommunity
!= old
->lcommunity
)
1078 lcommunity_free(&new->lcommunity
);
1081 /* Free bgp attribute and aspath. */
1082 void bgp_attr_unintern(struct attr
**pattr
)
1084 struct attr
*attr
= *pattr
;
1088 /* Decrement attribute reference. */
1093 /* If reference becomes zero then free attribute object. */
1094 if (attr
->refcnt
== 0) {
1095 ret
= hash_release(attrhash
, attr
);
1096 assert(ret
!= NULL
);
1097 XFREE(MTYPE_ATTR
, attr
);
1101 bgp_attr_unintern_sub(&tmp
);
1104 void bgp_attr_flush(struct attr
*attr
)
1106 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1107 aspath_free(attr
->aspath
);
1108 attr
->aspath
= NULL
;
1110 if (attr
->community
&& !attr
->community
->refcnt
)
1111 community_free(&attr
->community
);
1112 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
1113 ecommunity_free(&attr
->ecommunity
);
1114 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
1115 lcommunity_free(&attr
->lcommunity
);
1116 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
1117 cluster_free(attr
->cluster
);
1118 attr
->cluster
= NULL
;
1120 if (attr
->transit
&& !attr
->transit
->refcnt
) {
1121 transit_free(attr
->transit
);
1122 attr
->transit
= NULL
;
1124 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1125 encap_free(attr
->encap_subtlvs
);
1126 attr
->encap_subtlvs
= NULL
;
1129 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
1130 encap_free(attr
->vnc_subtlvs
);
1131 attr
->vnc_subtlvs
= NULL
;
1136 /* Implement draft-scudder-idr-optional-transitive behaviour and
1137 * avoid resetting sessions for malformed attributes which are
1138 * are partial/optional and hence where the error likely was not
1139 * introduced by the sending neighbour.
1141 static bgp_attr_parse_ret_t
1142 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1145 struct peer
*const peer
= args
->peer
;
1146 const uint8_t flags
= args
->flags
;
1147 /* startp and length must be special-cased, as whether or not to
1148 * send the attribute data with the NOTIFY depends on the error,
1149 * the caller therefore signals this with the seperate length argument
1151 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1153 /* Only relax error handling for eBGP peers */
1154 if (peer
->sort
!= BGP_PEER_EBGP
) {
1155 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1156 notify_datap
, length
);
1157 return BGP_ATTR_PARSE_ERROR
;
1160 /* Adjust the stream getp to the end of the attribute, in case we can
1161 * still proceed but the caller hasn't read all the attribute.
1163 stream_set_getp(BGP_INPUT(peer
),
1164 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1167 switch (args
->type
) {
1168 /* where an attribute is relatively inconsequential, e.g. it does not
1169 * affect route selection, and can be safely ignored, then any such
1170 * attributes which are malformed should just be ignored and the route
1171 * processed as normal.
1173 case BGP_ATTR_AS4_AGGREGATOR
:
1174 case BGP_ATTR_AGGREGATOR
:
1175 case BGP_ATTR_ATOMIC_AGGREGATE
:
1176 return BGP_ATTR_PARSE_PROCEED
;
1178 /* Core attributes, particularly ones which may influence route
1179 * selection, should be treat-as-withdraw.
1181 case BGP_ATTR_ORIGIN
:
1182 case BGP_ATTR_AS_PATH
:
1183 case BGP_ATTR_NEXT_HOP
:
1184 case BGP_ATTR_MULTI_EXIT_DISC
:
1185 case BGP_ATTR_LOCAL_PREF
:
1186 case BGP_ATTR_COMMUNITIES
:
1187 case BGP_ATTR_EXT_COMMUNITIES
:
1188 case BGP_ATTR_LARGE_COMMUNITIES
:
1189 case BGP_ATTR_ORIGINATOR_ID
:
1190 case BGP_ATTR_CLUSTER_LIST
:
1191 return BGP_ATTR_PARSE_WITHDRAW
;
1192 case BGP_ATTR_MP_REACH_NLRI
:
1193 case BGP_ATTR_MP_UNREACH_NLRI
:
1194 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1195 notify_datap
, length
);
1196 return BGP_ATTR_PARSE_ERROR
;
1199 /* Partial optional attributes that are malformed should not cause
1200 * the whole session to be reset. Instead treat it as a withdrawal
1201 * of the routes, if possible.
1203 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1204 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1205 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1206 return BGP_ATTR_PARSE_WITHDRAW
;
1208 /* default to reset */
1209 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1212 /* Find out what is wrong with the path attribute flag bits and log the error.
1213 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1214 Extended Length. Checking O/T/P bits at once implies, that the attribute
1215 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1216 non-transitive" attribute. */
1218 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1219 uint8_t desired_flags
/* how RFC says it must be */
1222 uint8_t seen
= 0, i
;
1223 uint8_t real_flags
= args
->flags
;
1224 const uint8_t attr_code
= args
->type
;
1226 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1227 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1228 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1229 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1230 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1231 flog_err(EC_BGP_ATTR_FLAG
,
1232 "%s attribute must%s be flagged as \"%s\"",
1233 lookup_msg(attr_str
, attr_code
, NULL
),
1234 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1237 attr_flag_str
[i
].str
);
1242 "Strange, %s called for attr %s, but no problem found with flags"
1243 " (real flags 0x%x, desired 0x%x)",
1244 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1245 real_flags
, desired_flags
);
1249 /* Required flags for attributes. EXTLEN will be masked off when testing,
1250 * as will PARTIAL for optional+transitive attributes.
1252 const uint8_t attr_flags_values
[] = {
1253 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1254 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1255 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1256 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1257 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1258 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1259 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1260 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1261 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1262 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1263 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1264 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1265 [BGP_ATTR_EXT_COMMUNITIES
] =
1266 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1267 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1268 [BGP_ATTR_AS4_AGGREGATOR
] =
1269 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1270 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1271 [BGP_ATTR_LARGE_COMMUNITIES
] =
1272 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1273 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1275 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1277 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1279 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1280 const uint8_t flags
= args
->flags
;
1281 const uint8_t attr_code
= args
->type
;
1283 /* there may be attributes we don't know about */
1284 if (attr_code
> attr_flags_values_max
)
1286 if (attr_flags_values
[attr_code
] == 0)
1289 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1293 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1294 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1297 "%s well-known attributes must have transitive flag set (%x)",
1298 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1302 /* "For well-known attributes and for optional non-transitive
1304 * the Partial bit MUST be set to 0."
1306 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1307 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1308 flog_err(EC_BGP_ATTR_FLAG
,
1309 "%s well-known attribute "
1310 "must NOT have the partial flag set (%x)",
1311 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1314 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1315 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1316 flog_err(EC_BGP_ATTR_FLAG
,
1317 "%s optional + transitive attribute "
1318 "must NOT have the partial flag set (%x)",
1319 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1324 /* Optional transitive attributes may go through speakers that don't
1325 * reocgnise them and set the Partial bit.
1327 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1328 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1329 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1331 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1334 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1338 /* Get origin attribute of the update message. */
1339 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1341 struct peer
*const peer
= args
->peer
;
1342 struct attr
*const attr
= args
->attr
;
1343 const bgp_size_t length
= args
->length
;
1345 /* If any recognized attribute has Attribute Length that conflicts
1346 with the expected length (based on the attribute type code), then
1347 the Error Subcode is set to Attribute Length Error. The Data
1348 field contains the erroneous attribute (type, length and
1351 flog_err(EC_BGP_ATTR_LEN
,
1352 "Origin attribute length is not one %d", length
);
1353 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1357 /* Fetch origin attribute. */
1358 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1360 /* If the ORIGIN attribute has an undefined value, then the Error
1361 Subcode is set to Invalid Origin Attribute. The Data field
1362 contains the unrecognized attribute (type, length and value). */
1363 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1364 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1365 flog_err(EC_BGP_ATTR_ORIGIN
,
1366 "Origin attribute value is invalid %d", attr
->origin
);
1367 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1371 /* Set oring attribute flag. */
1372 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1377 /* Parse AS path information. This function is wrapper of
1379 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1381 struct attr
*const attr
= args
->attr
;
1382 struct peer
*const peer
= args
->peer
;
1383 const bgp_size_t length
= args
->length
;
1386 * peer with AS4 => will get 4Byte ASnums
1387 * otherwise, will get 16 Bit
1389 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1390 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1392 /* In case of IBGP, length will be zero. */
1393 if (!attr
->aspath
) {
1394 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1395 "Malformed AS path from %s, length is %d", peer
->host
,
1397 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1401 /* Set aspath attribute flag. */
1402 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1404 return BGP_ATTR_PARSE_PROCEED
;
1407 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1408 struct attr
*const attr
)
1410 /* These checks were part of bgp_attr_aspath, but with
1411 * as4 we should to check aspath things when
1412 * aspath synthesizing with as4_path has already taken place.
1413 * Otherwise we check ASPATH and use the synthesized thing, and that is
1415 * So do the checks later, i.e. here
1417 struct aspath
*aspath
;
1419 /* Confederation sanity check. */
1420 if ((peer
->sort
== BGP_PEER_CONFED
1421 && !aspath_left_confed_check(attr
->aspath
))
1422 || (peer
->sort
== BGP_PEER_EBGP
1423 && aspath_confed_check(attr
->aspath
))) {
1424 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1426 return BGP_ATTR_PARSE_WITHDRAW
;
1429 /* First AS check for EBGP. */
1430 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1431 if (peer
->sort
== BGP_PEER_EBGP
1432 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1433 flog_err(EC_BGP_ATTR_FIRST_AS
,
1434 "%s incorrect first AS (must be %u)",
1435 peer
->host
, peer
->as
);
1436 return BGP_ATTR_PARSE_WITHDRAW
;
1440 /* local-as prepend */
1441 if (peer
->change_local_as
1442 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1443 aspath
= aspath_dup(attr
->aspath
);
1444 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1445 aspath_unintern(&attr
->aspath
);
1446 attr
->aspath
= aspath_intern(aspath
);
1449 return BGP_ATTR_PARSE_PROCEED
;
1452 /* Parse AS4 path information. This function is another wrapper of
1454 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1455 struct aspath
**as4_path
)
1457 struct peer
*const peer
= args
->peer
;
1458 struct attr
*const attr
= args
->attr
;
1459 const bgp_size_t length
= args
->length
;
1461 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1463 /* In case of IBGP, length will be zero. */
1465 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1466 "Malformed AS4 path from %s, length is %d", peer
->host
,
1468 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1472 /* Set aspath attribute flag. */
1473 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1475 return BGP_ATTR_PARSE_PROCEED
;
1479 * Check that the nexthop attribute is valid.
1481 bgp_attr_parse_ret_t
1482 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1484 in_addr_t nexthop_h
;
1486 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1487 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1488 || IPV4_CLASS_DE(nexthop_h
))
1489 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1490 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1491 char buf
[INET_ADDRSTRLEN
];
1493 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1495 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1497 data
[0] = BGP_ATTR_FLAG_TRANS
;
1498 data
[1] = BGP_ATTR_NEXT_HOP
;
1499 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1500 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1501 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1502 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1504 return BGP_ATTR_PARSE_ERROR
;
1507 return BGP_ATTR_PARSE_PROCEED
;
1510 /* Nexthop attribute. */
1511 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1513 struct peer
*const peer
= args
->peer
;
1514 struct attr
*const attr
= args
->attr
;
1515 const bgp_size_t length
= args
->length
;
1517 /* Check nexthop attribute length. */
1519 flog_err(EC_BGP_ATTR_LEN
,
1520 "Nexthop attribute length isn't four [%d]", length
);
1522 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1526 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1527 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1529 return BGP_ATTR_PARSE_PROCEED
;
1532 /* MED atrribute. */
1533 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1535 struct peer
*const peer
= args
->peer
;
1536 struct attr
*const attr
= args
->attr
;
1537 const bgp_size_t length
= args
->length
;
1541 flog_err(EC_BGP_ATTR_LEN
,
1542 "MED attribute length isn't four [%d]", length
);
1544 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1548 attr
->med
= stream_getl(peer
->curr
);
1550 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1552 return BGP_ATTR_PARSE_PROCEED
;
1555 /* Local preference attribute. */
1556 static bgp_attr_parse_ret_t
1557 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1559 struct peer
*const peer
= args
->peer
;
1560 struct attr
*const attr
= args
->attr
;
1561 const bgp_size_t length
= args
->length
;
1563 /* if received from an internal neighbor, it SHALL be considered
1564 * malformed if its length is not equal to 4. If malformed, the
1565 * UPDATE message SHALL be handled using the approach of "treat-as-
1568 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1569 flog_err(EC_BGP_ATTR_LEN
,
1570 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1571 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1575 /* If it is contained in an UPDATE message that is received from an
1576 external peer, then this attribute MUST be ignored by the
1577 receiving speaker. */
1578 if (peer
->sort
== BGP_PEER_EBGP
) {
1579 stream_forward_getp(peer
->curr
, length
);
1580 return BGP_ATTR_PARSE_PROCEED
;
1583 attr
->local_pref
= stream_getl(peer
->curr
);
1585 /* Set the local-pref flag. */
1586 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1588 return BGP_ATTR_PARSE_PROCEED
;
1591 /* Atomic aggregate. */
1592 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1594 struct attr
*const attr
= args
->attr
;
1595 const bgp_size_t length
= args
->length
;
1599 flog_err(EC_BGP_ATTR_LEN
,
1600 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1602 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1606 /* Set atomic aggregate flag. */
1607 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1609 return BGP_ATTR_PARSE_PROCEED
;
1612 /* Aggregator attribute */
1613 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1615 struct peer
*const peer
= args
->peer
;
1616 struct attr
*const attr
= args
->attr
;
1617 const bgp_size_t length
= args
->length
;
1621 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1622 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1623 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1626 if (length
!= wantedlen
) {
1627 flog_err(EC_BGP_ATTR_LEN
,
1628 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1630 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1634 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1635 attr
->aggregator_as
= stream_getl(peer
->curr
);
1637 attr
->aggregator_as
= stream_getw(peer
->curr
);
1638 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1640 /* Set atomic aggregate flag. */
1641 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1643 return BGP_ATTR_PARSE_PROCEED
;
1646 /* New Aggregator attribute */
1647 static bgp_attr_parse_ret_t
1648 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1649 as_t
*as4_aggregator_as
,
1650 struct in_addr
*as4_aggregator_addr
)
1652 struct peer
*const peer
= args
->peer
;
1653 struct attr
*const attr
= args
->attr
;
1654 const bgp_size_t length
= args
->length
;
1657 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1659 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1663 *as4_aggregator_as
= stream_getl(peer
->curr
);
1664 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1666 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1668 return BGP_ATTR_PARSE_PROCEED
;
1671 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1673 static bgp_attr_parse_ret_t
1674 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1675 struct aspath
*as4_path
, as_t as4_aggregator
,
1676 struct in_addr
*as4_aggregator_addr
)
1678 int ignore_as4_path
= 0;
1679 struct aspath
*newpath
;
1681 if (!attr
->aspath
) {
1682 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1684 * checked that all well-known, mandatory attributes were
1687 * Can only be a problem with peer itself - hard error
1689 return BGP_ATTR_PARSE_ERROR
;
1692 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1693 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1695 * It is worth a warning though, because the peer really
1696 * should not send them
1698 if (BGP_DEBUG(as4
, AS4
)) {
1699 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1700 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1701 "AS4 capable peer, yet it sent");
1704 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1705 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1707 "AS4 capable peer, yet it sent");
1710 return BGP_ATTR_PARSE_PROCEED
;
1713 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1714 * because that may override AS4_PATH
1716 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1717 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1719 * if the as_number in aggregator is not AS_TRANS,
1720 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1721 * and the Aggregator shall be taken as
1722 * info on the aggregating node, and the AS_PATH
1723 * shall be taken as the AS_PATH
1725 * the Aggregator shall be ignored and the
1726 * AS4_AGGREGATOR shall be taken as the
1727 * Aggregating node and the AS_PATH is to be
1728 * constructed "as in all other cases"
1730 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1732 if (BGP_DEBUG(as4
, AS4
))
1734 "[AS4] %s BGP not AS4 capable peer"
1735 " send AGGREGATOR != AS_TRANS and"
1736 " AS4_AGGREGATOR, so ignore"
1737 " AS4_AGGREGATOR and AS4_PATH",
1739 ignore_as4_path
= 1;
1741 /* "New_aggregator shall be taken as aggregator"
1743 attr
->aggregator_as
= as4_aggregator
;
1744 attr
->aggregator_addr
.s_addr
=
1745 as4_aggregator_addr
->s_addr
;
1748 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1749 * That is bogus - but reading the conditions
1750 * we have to handle AS4_AGGREGATOR as if it were
1751 * AGGREGATOR in that case
1753 if (BGP_DEBUG(as4
, AS4
))
1755 "[AS4] %s BGP not AS4 capable peer send"
1756 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1757 " it as if AGGREGATOR with AS_TRANS had been there",
1759 attr
->aggregator_as
= as4_aggregator
;
1760 /* sweep it under the carpet and simulate a "good"
1762 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1766 /* need to reconcile NEW_AS_PATH and AS_PATH */
1767 if (!ignore_as4_path
1768 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1769 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1771 return BGP_ATTR_PARSE_ERROR
;
1773 aspath_unintern(&attr
->aspath
);
1774 attr
->aspath
= aspath_intern(newpath
);
1776 return BGP_ATTR_PARSE_PROCEED
;
1779 /* Community attribute. */
1780 static bgp_attr_parse_ret_t
1781 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1783 struct peer
*const peer
= args
->peer
;
1784 struct attr
*const attr
= args
->attr
;
1785 const bgp_size_t length
= args
->length
;
1788 attr
->community
= NULL
;
1789 return BGP_ATTR_PARSE_PROCEED
;
1793 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1795 /* XXX: fix community_parse to use stream API and remove this */
1796 stream_forward_getp(peer
->curr
, length
);
1798 /* The Community attribute SHALL be considered malformed if its
1799 * length is not a non-zero multiple of 4.
1801 if (!attr
->community
)
1802 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1805 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1807 return BGP_ATTR_PARSE_PROCEED
;
1810 /* Originator ID attribute. */
1811 static bgp_attr_parse_ret_t
1812 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1814 struct peer
*const peer
= args
->peer
;
1815 struct attr
*const attr
= args
->attr
;
1816 const bgp_size_t length
= args
->length
;
1818 /* if received from an internal neighbor, it SHALL be considered
1819 * malformed if its length is not equal to 4. If malformed, the
1820 * UPDATE message SHALL be handled using the approach of "treat-as-
1824 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1827 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1831 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1833 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1835 return BGP_ATTR_PARSE_PROCEED
;
1838 /* Cluster list attribute. */
1839 static bgp_attr_parse_ret_t
1840 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1842 struct peer
*const peer
= args
->peer
;
1843 struct attr
*const attr
= args
->attr
;
1844 const bgp_size_t length
= args
->length
;
1846 /* if received from an internal neighbor, it SHALL be considered
1847 * malformed if its length is not a non-zero multiple of 4. If
1848 * malformed, the UPDATE message SHALL be handled using the approach
1849 * of "treat-as-withdraw".
1852 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
1854 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1859 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1861 /* XXX: Fix cluster_parse to use stream API and then remove this */
1862 stream_forward_getp(peer
->curr
, length
);
1864 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1866 return BGP_ATTR_PARSE_PROCEED
;
1869 /* Multiprotocol reachability information parse. */
1870 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1871 struct bgp_nlri
*mp_update
)
1875 iana_safi_t pkt_safi
;
1877 bgp_size_t nlri_len
;
1880 struct peer
*const peer
= args
->peer
;
1881 struct attr
*const attr
= args
->attr
;
1882 const bgp_size_t length
= args
->length
;
1884 /* Set end of packet. */
1885 s
= BGP_INPUT(peer
);
1886 start
= stream_get_getp(s
);
1888 /* safe to read statically sized header? */
1889 #define BGP_MP_REACH_MIN_SIZE 5
1890 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1891 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1892 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
1893 __func__
, peer
->host
, (unsigned long)length
);
1894 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1897 /* Load AFI, SAFI. */
1898 pkt_afi
= stream_getw(s
);
1899 pkt_safi
= stream_getc(s
);
1901 /* Convert AFI, SAFI to internal values, check. */
1902 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1903 /* Log if AFI or SAFI is unrecognized. This is not an error
1905 * the attribute is otherwise malformed.
1907 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1909 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
1910 peer
->host
, iana_afi2str(pkt_afi
),
1911 iana_safi2str(pkt_safi
));
1912 return BGP_ATTR_PARSE_ERROR
;
1915 /* Get nexthop length. */
1916 attr
->mp_nexthop_len
= stream_getc(s
);
1918 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1920 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
1921 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1922 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1925 /* Nexthop length check. */
1926 switch (attr
->mp_nexthop_len
) {
1928 if (safi
!= SAFI_FLOWSPEC
) {
1929 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
1930 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1931 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1934 case BGP_ATTR_NHLEN_VPNV4
:
1935 stream_getl(s
); /* RD high */
1936 stream_getl(s
); /* RD low */
1938 * NOTE: intentional fall through
1939 * - for consistency in rx processing
1941 * The following comment is to signal GCC this intention
1942 * and suppress the warning
1945 case BGP_ATTR_NHLEN_IPV4
:
1946 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1947 /* Probably needed for RFC 2283 */
1948 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
1949 memcpy(&attr
->nexthop
.s_addr
,
1950 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1952 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1953 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1954 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1955 stream_getl(s
); /* RD high */
1956 stream_getl(s
); /* RD low */
1958 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1959 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1960 if (!peer
->nexthop
.ifp
) {
1961 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
1963 return BGP_ATTR_PARSE_WITHDRAW
;
1965 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1968 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1969 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1970 if (attr
->mp_nexthop_len
1971 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1972 stream_getl(s
); /* RD high */
1973 stream_getl(s
); /* RD low */
1975 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1976 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1977 if (!peer
->nexthop
.ifp
) {
1978 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",
1980 return BGP_ATTR_PARSE_WITHDRAW
;
1982 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1984 if (attr
->mp_nexthop_len
1985 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1986 stream_getl(s
); /* RD high */
1987 stream_getl(s
); /* RD low */
1989 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1990 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1991 char buf1
[INET6_ADDRSTRLEN
];
1992 char buf2
[INET6_ADDRSTRLEN
];
1994 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1996 "%s sent next-hops %s and %s. Ignoring non-LL value",
1999 &attr
->mp_nexthop_global
,
2000 buf1
, INET6_ADDRSTRLEN
),
2002 &attr
->mp_nexthop_local
, buf2
,
2005 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2007 if (!peer
->nexthop
.ifp
) {
2008 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2010 return BGP_ATTR_PARSE_WITHDRAW
;
2012 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2015 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2016 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2017 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2021 zlog_info("%s: %s sent SNPA which couldn't be read",
2022 __func__
, peer
->host
);
2023 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2028 if ((val
= stream_getc(s
)))
2030 EC_BGP_DEFUNCT_SNPA_LEN
,
2031 "%s sent non-zero value, %u, for defunct SNPA-length field",
2035 /* must have nrli_len, what is left of the attribute */
2036 nlri_len
= LEN_LEFT
;
2037 if (nlri_len
> STREAM_READABLE(s
)) {
2038 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2039 __func__
, peer
->host
);
2040 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2044 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2045 __func__
, peer
->host
);
2047 mp_update
->afi
= afi
;
2048 mp_update
->safi
= safi
;
2049 return BGP_ATTR_PARSE_EOR
;
2052 mp_update
->afi
= afi
;
2053 mp_update
->safi
= safi
;
2054 mp_update
->nlri
= stream_pnt(s
);
2055 mp_update
->length
= nlri_len
;
2057 stream_forward_getp(s
, nlri_len
);
2059 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2061 return BGP_ATTR_PARSE_PROCEED
;
2065 /* Multiprotocol unreachable parse */
2066 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2067 struct bgp_nlri
*mp_withdraw
)
2072 iana_safi_t pkt_safi
;
2074 uint16_t withdraw_len
;
2075 struct peer
*const peer
= args
->peer
;
2076 struct attr
*const attr
= args
->attr
;
2077 const bgp_size_t length
= args
->length
;
2081 #define BGP_MP_UNREACH_MIN_SIZE 3
2082 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2083 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2085 pkt_afi
= stream_getw(s
);
2086 pkt_safi
= stream_getc(s
);
2088 /* Convert AFI, SAFI to internal values, check. */
2089 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2090 /* Log if AFI or SAFI is unrecognized. This is not an error
2092 * the attribute is otherwise malformed.
2094 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2096 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2097 peer
->host
, iana_afi2str(pkt_afi
),
2098 iana_safi2str(pkt_safi
));
2099 return BGP_ATTR_PARSE_ERROR
;
2102 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2104 mp_withdraw
->afi
= afi
;
2105 mp_withdraw
->safi
= safi
;
2106 mp_withdraw
->nlri
= stream_pnt(s
);
2107 mp_withdraw
->length
= withdraw_len
;
2109 stream_forward_getp(s
, withdraw_len
);
2111 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2113 return BGP_ATTR_PARSE_PROCEED
;
2116 /* Large Community attribute. */
2117 static bgp_attr_parse_ret_t
2118 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2120 struct peer
*const peer
= args
->peer
;
2121 struct attr
*const attr
= args
->attr
;
2122 const bgp_size_t length
= args
->length
;
2125 * Large community follows new attribute format.
2128 attr
->lcommunity
= NULL
;
2129 /* Empty extcomm doesn't seem to be invalid per se */
2130 return BGP_ATTR_PARSE_PROCEED
;
2134 lcommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
2135 /* XXX: fix ecommunity_parse to use stream API */
2136 stream_forward_getp(peer
->curr
, length
);
2138 if (!attr
->lcommunity
)
2139 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2142 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2144 return BGP_ATTR_PARSE_PROCEED
;
2147 /* Extended Community attribute. */
2148 static bgp_attr_parse_ret_t
2149 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2151 struct peer
*const peer
= args
->peer
;
2152 struct attr
*const attr
= args
->attr
;
2153 const bgp_size_t length
= args
->length
;
2157 attr
->ecommunity
= NULL
;
2158 /* Empty extcomm doesn't seem to be invalid per se */
2159 return BGP_ATTR_PARSE_PROCEED
;
2163 ecommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
2164 /* XXX: fix ecommunity_parse to use stream API */
2165 stream_forward_getp(peer
->curr
, length
);
2167 /* The Extended Community attribute SHALL be considered malformed if
2168 * its length is not a non-zero multiple of 8.
2170 if (!attr
->ecommunity
)
2171 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2174 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2176 /* Extract MAC mobility sequence number, if any. */
2177 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2178 attr
->sticky
= sticky
;
2180 /* Check if this is a Gateway MAC-IP advertisement */
2181 attr
->default_gw
= bgp_attr_default_gw(attr
);
2183 /* Handle scenario where router flag ecommunity is not
2184 * set but default gw ext community is present.
2185 * Use default gateway, set and propogate R-bit.
2187 if (attr
->default_gw
)
2188 attr
->router_flag
= 1;
2190 /* Check EVPN Neighbor advertisement flags, R-bit */
2191 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
);
2193 /* Extract the Rmac, if any */
2194 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2195 if (bgp_debug_update(peer
, NULL
, NULL
, 1) &&
2196 bgp_mac_exist(&attr
->rmac
)) {
2197 char buf1
[ETHER_ADDR_STRLEN
];
2199 zlog_debug("%s: router mac %s is self mac",
2201 prefix_mac2str(&attr
->rmac
, buf1
,
2207 /* Get the tunnel type from encap extended community */
2208 bgp_attr_extcom_tunnel_type(attr
,
2209 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2211 return BGP_ATTR_PARSE_PROCEED
;
2214 /* Parse Tunnel Encap attribute in an UPDATE */
2215 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2216 bgp_size_t length
, /* IN: attr's length field */
2217 struct attr
*attr
, /* IN: caller already allocated */
2218 uint8_t flag
, /* IN: attr's flags field */
2222 uint16_t tunneltype
= 0;
2224 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2226 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2227 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2229 "Tunnel Encap attribute flag isn't optional and transitive %d",
2231 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2232 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2237 if (BGP_ATTR_ENCAP
== type
) {
2238 /* read outer TLV type and length */
2239 uint16_t tlv_length
;
2243 "Tunnel Encap attribute not long enough to contain outer T,L");
2244 bgp_notify_send_with_data(
2245 peer
, BGP_NOTIFY_UPDATE_ERR
,
2246 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2249 tunneltype
= stream_getw(BGP_INPUT(peer
));
2250 tlv_length
= stream_getw(BGP_INPUT(peer
));
2253 if (tlv_length
!= length
) {
2254 zlog_info("%s: tlv_length(%d) != length(%d)",
2255 __func__
, tlv_length
, length
);
2259 while (length
>= 4) {
2260 uint16_t subtype
= 0;
2261 uint16_t sublength
= 0;
2262 struct bgp_attr_encap_subtlv
*tlv
;
2264 if (BGP_ATTR_ENCAP
== type
) {
2265 subtype
= stream_getc(BGP_INPUT(peer
));
2266 sublength
= stream_getc(BGP_INPUT(peer
));
2270 subtype
= stream_getw(BGP_INPUT(peer
));
2271 sublength
= stream_getw(BGP_INPUT(peer
));
2276 if (sublength
> length
) {
2278 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2280 bgp_notify_send_with_data(
2281 peer
, BGP_NOTIFY_UPDATE_ERR
,
2282 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2286 /* alloc and copy sub-tlv */
2287 /* TBD make sure these are freed when attributes are released */
2288 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2289 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2290 tlv
->type
= subtype
;
2291 tlv
->length
= sublength
;
2292 stream_get(tlv
->value
, peer
->curr
, sublength
);
2293 length
-= sublength
;
2295 /* attach tlv to encap chain */
2296 if (BGP_ATTR_ENCAP
== type
) {
2297 struct bgp_attr_encap_subtlv
*stlv_last
;
2298 for (stlv_last
= attr
->encap_subtlvs
;
2299 stlv_last
&& stlv_last
->next
;
2300 stlv_last
= stlv_last
->next
)
2303 stlv_last
->next
= tlv
;
2305 attr
->encap_subtlvs
= tlv
;
2309 struct bgp_attr_encap_subtlv
*stlv_last
;
2310 for (stlv_last
= attr
->vnc_subtlvs
;
2311 stlv_last
&& stlv_last
->next
;
2312 stlv_last
= stlv_last
->next
)
2315 stlv_last
->next
= tlv
;
2317 attr
->vnc_subtlvs
= tlv
;
2323 if (BGP_ATTR_ENCAP
== type
) {
2324 attr
->encap_tunneltype
= tunneltype
;
2328 /* spurious leftover data */
2330 "Tunnel Encap attribute length is bad: %d leftover octets",
2332 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2333 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2342 * Read an individual SID value returning how much data we have read
2343 * Returns 0 if there was an error that needs to be passed up the stack
2345 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2346 struct bgp_attr_parser_args
*args
,
2347 struct bgp_nlri
*mp_update
)
2349 struct peer
*const peer
= args
->peer
;
2350 struct attr
*const attr
= args
->attr
;
2351 uint32_t label_index
;
2352 struct in6_addr ipv6_sid
;
2354 uint32_t srgb_range
;
2356 uint8_t sid_type
, sid_flags
;
2357 uint16_t endpoint_behavior
;
2360 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2361 if (STREAM_READABLE(peer
->curr
) < length
2362 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2363 flog_err(EC_BGP_ATTR_LEN
,
2364 "Prefix SID label index length is %" PRIu16
2366 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2367 return bgp_attr_malformed(args
,
2368 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2372 /* Ignore flags and reserved */
2373 stream_getc(peer
->curr
);
2374 stream_getw(peer
->curr
);
2376 /* Fetch the label index and see if it is valid. */
2377 label_index
= stream_getl(peer
->curr
);
2378 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2379 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2382 /* Store label index; subsequently, we'll check on
2384 attr
->label_index
= label_index
;
2387 * Ignore the Label index attribute unless received for
2391 if (!mp_update
->length
2392 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2393 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2396 /* Placeholder code for the IPv6 SID type */
2397 else if (type
== BGP_PREFIX_SID_IPV6
) {
2398 if (STREAM_READABLE(peer
->curr
) < length
2399 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2400 flog_err(EC_BGP_ATTR_LEN
,
2401 "Prefix SID IPv6 length is %" PRIu16
2403 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2404 return bgp_attr_malformed(args
,
2405 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2409 /* Ignore reserved */
2410 stream_getc(peer
->curr
);
2411 stream_getw(peer
->curr
);
2413 stream_get(&ipv6_sid
, peer
->curr
, 16);
2416 /* Placeholder code for the Originator SRGB type */
2417 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2419 * ietf-idr-bgp-prefix-sid-05:
2420 * Length is the total length of the value portion of the
2421 * TLV: 2 + multiple of 6.
2423 * peer->curr stream readp should be at the beginning of the 16
2424 * bit flag field at this point in the code.
2428 * Check that the TLV length field is sane: at least 2 bytes of
2429 * flag, and at least 1 SRGB (these are 6 bytes each)
2431 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2434 "Prefix SID Originator SRGB length field claims length of %" PRIu16
" bytes, but the minimum for this TLV type is %u",
2436 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2437 return bgp_attr_malformed(
2438 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2443 * Check that we actually have at least as much data as
2444 * specified by the length field
2446 if (STREAM_READABLE(peer
->curr
) < length
) {
2447 flog_err(EC_BGP_ATTR_LEN
,
2448 "Prefix SID Originator SRGB specifies length %" PRIu16
", but only %zu bytes remain",
2449 length
, STREAM_READABLE(peer
->curr
));
2450 return bgp_attr_malformed(
2451 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2456 * Check that the portion of the TLV containing the sequence of
2457 * SRGBs corresponds to a multiple of the SRGB size; to get
2458 * that length, we skip the 16 bit flags field
2460 stream_getw(peer
->curr
);
2462 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2465 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %" PRIu16
"bytes, but it must be a multiple of %u",
2466 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2467 return bgp_attr_malformed(
2468 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2472 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2474 for (int i
= 0; i
< srgb_count
; i
++) {
2475 stream_get(&srgb_base
, peer
->curr
, 3);
2476 stream_get(&srgb_range
, peer
->curr
, 3);
2480 /* Placeholder code for the VPN-SID Service type */
2481 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2482 if (STREAM_READABLE(peer
->curr
) < length
2483 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2484 flog_err(EC_BGP_ATTR_LEN
,
2485 "Prefix SID VPN SID length is %" PRIu16
2487 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2488 return bgp_attr_malformed(args
,
2489 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2493 /* Parse VPN-SID Sub-TLV */
2494 stream_getc(peer
->curr
); /* reserved */
2495 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2496 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2497 stream_get(&ipv6_sid
, peer
->curr
,
2498 sizeof(ipv6_sid
)); /* sid_value */
2500 /* Log VPN-SID Sub-TLV */
2501 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2502 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2504 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2505 __func__
, buf
, sid_type
, sid_flags
);
2508 /* Configure from Info */
2509 if (attr
->srv6_vpn
) {
2510 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2511 "Prefix SID SRv6 VPN field repeated");
2512 return bgp_attr_malformed(
2513 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2515 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2516 sizeof(struct bgp_attr_srv6_vpn
));
2517 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2518 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2521 /* Placeholder code for the SRv6 L3 Service type */
2522 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2523 if (STREAM_READABLE(peer
->curr
) < length
2524 || length
!= BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
) {
2525 flog_err(EC_BGP_ATTR_LEN
,
2526 "Prefix SID SRv6 L3-Service length is %" PRIu16
2528 length
, BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
);
2529 return bgp_attr_malformed(args
,
2530 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2534 /* Parse L3-SERVICE Sub-TLV */
2535 stream_getc(peer
->curr
); /* reserved */
2536 stream_get(&ipv6_sid
, peer
->curr
,
2537 sizeof(ipv6_sid
)); /* sid_value */
2538 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2539 endpoint_behavior
= stream_getw(peer
->curr
); /* endpoint */
2540 stream_getc(peer
->curr
); /* reserved */
2542 /* Log L3-SERVICE Sub-TLV */
2543 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2544 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2546 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2547 __func__
, buf
, sid_flags
, endpoint_behavior
);
2550 /* Configure from Info */
2551 if (attr
->srv6_l3vpn
) {
2552 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2553 "Prefix SID SRv6 L3VPN field repeated");
2554 return bgp_attr_malformed(
2555 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2557 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2558 sizeof(struct bgp_attr_srv6_l3vpn
));
2559 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2560 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2561 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2564 /* Placeholder code for Unsupported TLV */
2567 if (STREAM_READABLE(peer
->curr
) < length
) {
2570 "Prefix SID SRv6 length is %" PRIu16
2571 " - too long, only %zu remaining in this UPDATE",
2572 length
, STREAM_READABLE(peer
->curr
));
2573 return bgp_attr_malformed(
2574 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2578 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2580 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2583 stream_forward_getp(peer
->curr
, length
);
2586 return BGP_ATTR_PARSE_PROCEED
;
2589 /* Prefix SID attribute
2590 * draft-ietf-idr-bgp-prefix-sid-05
2592 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
,
2593 struct bgp_nlri
*mp_update
)
2595 struct peer
*const peer
= args
->peer
;
2596 struct attr
*const attr
= args
->attr
;
2597 bgp_attr_parse_ret_t ret
;
2599 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2603 size_t headersz
= sizeof(type
) + sizeof(length
);
2605 while (STREAM_READABLE(peer
->curr
) > 0) {
2607 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2610 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2611 headersz
, STREAM_READABLE(peer
->curr
));
2612 return bgp_attr_malformed(
2613 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2617 type
= stream_getc(peer
->curr
);
2618 length
= stream_getw(peer
->curr
);
2620 if (STREAM_READABLE(peer
->curr
) < length
) {
2623 "Malformed Prefix SID attribute - insufficient data (need %" PRIu8
2624 " for attribute body, have %zu remaining in UPDATE)",
2625 length
, STREAM_READABLE(peer
->curr
));
2626 return bgp_attr_malformed(args
,
2627 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2631 ret
= bgp_attr_psid_sub(type
, length
, args
, mp_update
);
2633 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2637 return BGP_ATTR_PARSE_PROCEED
;
2640 /* PMSI tunnel attribute (RFC 6514)
2641 * Basic validation checks done here.
2643 static bgp_attr_parse_ret_t
2644 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2646 struct peer
*const peer
= args
->peer
;
2647 struct attr
*const attr
= args
->attr
;
2648 const bgp_size_t length
= args
->length
;
2650 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2652 /* Verify that the receiver is expecting "ingress replication" as we
2653 * can only support that.
2655 if (length
< attr_parse_len
) {
2656 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2658 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2661 stream_getc(peer
->curr
); /* Flags */
2662 tnl_type
= stream_getc(peer
->curr
);
2663 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2664 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2665 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2666 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2669 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2671 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2672 "Bad PMSI tunnel attribute length %d for IR",
2674 return bgp_attr_malformed(
2675 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2680 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2681 attr
->pmsi_tnl_type
= tnl_type
;
2682 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2684 /* Forward read pointer of input stream. */
2685 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2687 return BGP_ATTR_PARSE_PROCEED
;
2690 /* BGP unknown attribute treatment. */
2691 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2693 bgp_size_t total
= args
->total
;
2694 struct transit
*transit
;
2695 struct peer
*const peer
= args
->peer
;
2696 struct attr
*const attr
= args
->attr
;
2697 uint8_t *const startp
= args
->startp
;
2698 const uint8_t type
= args
->type
;
2699 const uint8_t flag
= args
->flags
;
2700 const bgp_size_t length
= args
->length
;
2702 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2704 "%s Unknown attribute is received (type %d, length %d)",
2705 peer
->host
, type
, length
);
2707 /* Forward read pointer of input stream. */
2708 stream_forward_getp(peer
->curr
, length
);
2710 /* If any of the mandatory well-known attributes are not recognized,
2711 then the Error Subcode is set to Unrecognized Well-known
2712 Attribute. The Data field contains the unrecognized attribute
2713 (type, length and value). */
2714 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2715 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2719 /* Unrecognized non-transitive optional attributes must be quietly
2720 ignored and not passed along to other BGP peers. */
2721 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2722 return BGP_ATTR_PARSE_PROCEED
;
2724 /* If a path with recognized transitive optional attribute is
2725 accepted and passed along to other BGP peers and the Partial bit
2726 in the Attribute Flags octet is set to 1 by some previous AS, it
2727 is not set back to 0 by the current AS. */
2728 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2730 /* Store transitive attribute to the end of attr->transit. */
2732 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2734 transit
= attr
->transit
;
2737 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2738 transit
->length
+ total
);
2740 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2742 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2743 transit
->length
+= total
;
2745 return BGP_ATTR_PARSE_PROCEED
;
2748 /* Well-known attribute check. */
2749 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2753 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2755 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2756 return BGP_ATTR_PARSE_PROCEED
;
2758 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2759 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2760 are present, it should. Check for any other attribute being present
2763 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2764 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2765 return BGP_ATTR_PARSE_PROCEED
;
2767 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2768 type
= BGP_ATTR_ORIGIN
;
2770 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2771 type
= BGP_ATTR_AS_PATH
;
2773 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2775 * NLRI is empty. We can't easily check NLRI empty here though.
2777 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2778 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2779 type
= BGP_ATTR_NEXT_HOP
;
2781 if (peer
->sort
== BGP_PEER_IBGP
2782 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2783 type
= BGP_ATTR_LOCAL_PREF
;
2785 /* If any of the well-known mandatory attributes are not present
2786 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
2789 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2790 "%s Missing well-known attribute %s.", peer
->host
,
2791 lookup_msg(attr_str
, type
, NULL
));
2792 return BGP_ATTR_PARSE_WITHDRAW
;
2794 return BGP_ATTR_PARSE_PROCEED
;
2797 /* Read attribute of update packet. This function is called from
2798 bgp_update_receive() in bgp_packet.c. */
2799 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2800 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2801 struct bgp_nlri
*mp_withdraw
)
2803 bgp_attr_parse_ret_t ret
;
2807 uint8_t *startp
, *endp
;
2809 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2810 /* we need the as4_path only until we have synthesized the as_path with
2812 /* same goes for as4_aggregator */
2813 struct aspath
*as4_path
= NULL
;
2814 as_t as4_aggregator
= 0;
2815 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2817 /* Initialize bitmap. */
2818 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2820 /* End pointer of BGP attribute. */
2821 endp
= BGP_INPUT_PNT(peer
) + size
;
2823 /* Get attributes to the end of attribute length. */
2824 while (BGP_INPUT_PNT(peer
) < endp
) {
2825 /* Check remaining length check.*/
2826 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2827 /* XXX warning: long int format, int arg (arg 5) */
2829 EC_BGP_ATTRIBUTE_TOO_SMALL
,
2830 "%s: error BGP attribute length %lu is smaller than min len",
2832 (unsigned long)(endp
2833 - stream_pnt(BGP_INPUT(peer
))));
2835 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2836 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2837 ret
= BGP_ATTR_PARSE_ERROR
;
2841 /* Fetch attribute flag and type. */
2842 startp
= BGP_INPUT_PNT(peer
);
2843 /* "The lower-order four bits of the Attribute Flags octet are
2844 unused. They MUST be zero when sent and MUST be ignored when
2846 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2847 type
= stream_getc(BGP_INPUT(peer
));
2849 /* Check whether Extended-Length applies and is in bounds */
2850 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2851 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2853 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
2854 "%s: Extended length set, but just %lu bytes of attr header",
2856 (unsigned long)(endp
2857 - stream_pnt(BGP_INPUT(peer
))));
2859 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2860 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2861 ret
= BGP_ATTR_PARSE_ERROR
;
2865 /* Check extended attribue length bit. */
2866 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2867 length
= stream_getw(BGP_INPUT(peer
));
2869 length
= stream_getc(BGP_INPUT(peer
));
2871 /* If any attribute appears more than once in the UPDATE
2872 message, then the Error Subcode is set to Malformed Attribute
2875 if (CHECK_BITMAP(seen
, type
)) {
2877 EC_BGP_ATTRIBUTE_REPEATED
,
2878 "%s: error BGP attribute type %d appears twice in a message",
2881 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2882 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2883 ret
= BGP_ATTR_PARSE_ERROR
;
2887 /* Set type to bitmap to check duplicate attribute. `type' is
2888 unsigned char so it never overflow bitmap range. */
2890 SET_BITMAP(seen
, type
);
2892 /* Overflow check. */
2893 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2895 if (attr_endp
> endp
) {
2897 EC_BGP_ATTRIBUTE_TOO_LARGE
,
2898 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2899 peer
->host
, type
, length
, size
, attr_endp
,
2903 * If any recognized attribute has an Attribute
2904 * Length that conflicts with the expected length
2905 * (based on the attribute type code), then the
2906 * Error Subcode MUST be set to Attribute Length
2907 * Error. The Data field MUST contain the erroneous
2908 * attribute (type, length, and value).
2910 * We do not currently have a good way to determine the
2911 * length of the attribute independent of the length
2912 * received in the message. Instead we send the
2913 * minimum between the amount of data we have and the
2914 * amount specified by the attribute length field.
2916 * Instead of directly passing in the packet buffer and
2917 * offset we use the stream_get* functions to read into
2918 * a stack buffer, since they perform bounds checking
2919 * and we are working with untrusted data.
2921 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
2922 memset(ndata
, 0x00, sizeof(ndata
));
2924 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
2925 /* Rewind to end of flag field */
2926 stream_forward_getp(BGP_INPUT(peer
), -(1 + lfl
));
2928 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
2930 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
2932 size_t atl
= attr_endp
- startp
;
2933 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
2934 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
2936 bgp_notify_send_with_data(
2937 peer
, BGP_NOTIFY_UPDATE_ERR
,
2938 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
2941 ret
= BGP_ATTR_PARSE_ERROR
;
2945 struct bgp_attr_parser_args attr_args
= {
2952 .total
= attr_endp
- startp
,
2956 /* If any recognized attribute has Attribute Flags that conflict
2957 with the Attribute Type Code, then the Error Subcode is set
2959 Attribute Flags Error. The Data field contains the erroneous
2960 attribute (type, length and value). */
2961 if (bgp_attr_flag_invalid(&attr_args
)) {
2962 ret
= bgp_attr_malformed(
2963 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2965 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2970 /* OK check attribute and store it's value. */
2972 case BGP_ATTR_ORIGIN
:
2973 ret
= bgp_attr_origin(&attr_args
);
2975 case BGP_ATTR_AS_PATH
:
2976 ret
= bgp_attr_aspath(&attr_args
);
2978 case BGP_ATTR_AS4_PATH
:
2979 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2981 case BGP_ATTR_NEXT_HOP
:
2982 ret
= bgp_attr_nexthop(&attr_args
);
2984 case BGP_ATTR_MULTI_EXIT_DISC
:
2985 ret
= bgp_attr_med(&attr_args
);
2987 case BGP_ATTR_LOCAL_PREF
:
2988 ret
= bgp_attr_local_pref(&attr_args
);
2990 case BGP_ATTR_ATOMIC_AGGREGATE
:
2991 ret
= bgp_attr_atomic(&attr_args
);
2993 case BGP_ATTR_AGGREGATOR
:
2994 ret
= bgp_attr_aggregator(&attr_args
);
2996 case BGP_ATTR_AS4_AGGREGATOR
:
2997 ret
= bgp_attr_as4_aggregator(&attr_args
,
2999 &as4_aggregator_addr
);
3001 case BGP_ATTR_COMMUNITIES
:
3002 ret
= bgp_attr_community(&attr_args
);
3004 case BGP_ATTR_LARGE_COMMUNITIES
:
3005 ret
= bgp_attr_large_community(&attr_args
);
3007 case BGP_ATTR_ORIGINATOR_ID
:
3008 ret
= bgp_attr_originator_id(&attr_args
);
3010 case BGP_ATTR_CLUSTER_LIST
:
3011 ret
= bgp_attr_cluster_list(&attr_args
);
3013 case BGP_ATTR_MP_REACH_NLRI
:
3014 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3016 case BGP_ATTR_MP_UNREACH_NLRI
:
3017 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3019 case BGP_ATTR_EXT_COMMUNITIES
:
3020 ret
= bgp_attr_ext_communities(&attr_args
);
3022 #if ENABLE_BGP_VNC_ATTR
3025 case BGP_ATTR_ENCAP
:
3026 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3029 case BGP_ATTR_PREFIX_SID
:
3030 ret
= bgp_attr_prefix_sid(&attr_args
, mp_update
);
3032 case BGP_ATTR_PMSI_TUNNEL
:
3033 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3036 ret
= bgp_attr_unknown(&attr_args
);
3040 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3041 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3042 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3043 ret
= BGP_ATTR_PARSE_ERROR
;
3047 if (ret
== BGP_ATTR_PARSE_EOR
) {
3051 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3052 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3053 "%s: Attribute %s, parse error", peer
->host
,
3054 lookup_msg(attr_str
, type
, NULL
));
3057 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3059 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3060 "%s: Attribute %s, parse error - treating as withdrawal",
3061 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3065 /* Check the fetched length. */
3066 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3067 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3068 "%s: BGP attribute %s, fetch error",
3069 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3070 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3071 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3072 ret
= BGP_ATTR_PARSE_ERROR
;
3077 /* Check final read pointer is same as end pointer. */
3078 if (BGP_INPUT_PNT(peer
) != endp
) {
3079 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3080 "%s: BGP attribute %s, length mismatch", peer
->host
,
3081 lookup_msg(attr_str
, type
, NULL
));
3082 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3083 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3085 ret
= BGP_ATTR_PARSE_ERROR
;
3090 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3091 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3092 * This is implemented below and will result in a NOTIFICATION. If the
3093 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3094 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3095 * message SHOULD NOT be sent. This is implemented elsewhere.
3097 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3098 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3099 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3100 * speaker that receives the message SHOULD ignore this attribute.
3102 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3103 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3104 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3105 ret
= BGP_ATTR_PARSE_ERROR
;
3110 /* Check all mandatory well-known attributes are present */
3111 if ((ret
= bgp_attr_check(peer
, attr
)) < 0)
3115 * At this place we can see whether we got AS4_PATH and/or
3116 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3117 * We can not do this before we've read all attributes because
3118 * the as4 handling does not say whether AS4_PATH has to be sent
3119 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3120 * in relationship to AGGREGATOR.
3121 * So, to be defensive, we are not relying on any order and read
3122 * all attributes first, including these 32bit ones, and now,
3123 * afterwards, we look what and if something is to be done for as4.
3125 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3128 /* actually... this doesn't ever return failure currently, but
3129 * better safe than sorry */
3130 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3131 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3132 &as4_aggregator_addr
)) {
3133 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3134 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3135 ret
= BGP_ATTR_PARSE_ERROR
;
3140 * Finally do the checks on the aspath we did not do yet
3141 * because we waited for a potentially synthesized aspath.
3143 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3144 ret
= bgp_attr_aspath_check(peer
, attr
);
3145 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3149 ret
= BGP_ATTR_PARSE_PROCEED
;
3153 * At this stage, we have done all fiddling with as4, and the
3154 * resulting info is in attr->aggregator resp. attr->aspath so
3155 * we can chuck as4_aggregator and as4_path alltogether in order
3160 * unintern - it is in the hash
3161 * The flag that we got this is still there, but that
3162 * does not do any trouble
3164 aspath_unintern(&as4_path
);
3167 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3168 /* Finally intern unknown attribute. */
3170 attr
->transit
= transit_intern(attr
->transit
);
3171 if (attr
->encap_subtlvs
)
3172 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3175 if (attr
->vnc_subtlvs
)
3176 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
3180 if (attr
->transit
) {
3181 transit_free(attr
->transit
);
3182 attr
->transit
= NULL
;
3185 bgp_attr_flush_encap(attr
);
3190 assert(attr
->transit
->refcnt
> 0);
3191 if (attr
->encap_subtlvs
)
3192 assert(attr
->encap_subtlvs
->refcnt
> 0);
3194 if (attr
->vnc_subtlvs
)
3195 assert(attr
->vnc_subtlvs
->refcnt
> 0);
3202 * Extract the tunnel type from extended community
3204 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3205 bgp_encap_types
*tunnel_type
)
3207 struct ecommunity
*ecom
;
3212 ecom
= attr
->ecommunity
;
3213 if (!ecom
|| !ecom
->size
)
3216 for (i
= 0; i
< ecom
->size
; i
++) {
3218 uint8_t type
, sub_type
;
3220 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3223 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3224 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3226 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3233 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3234 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3239 iana_safi_t pkt_safi
;
3242 /* Set extended bit always to encode the attribute length as 2 bytes */
3243 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3244 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3245 sizep
= stream_get_endp(s
);
3246 stream_putw(s
, 0); /* Marker: Attribute length. */
3249 /* Convert AFI, SAFI to values for packet. */
3250 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3252 stream_putw(s
, pkt_afi
); /* AFI */
3253 stream_putc(s
, pkt_safi
); /* SAFI */
3257 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3258 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3259 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3260 else if (safi
== SAFI_FLOWSPEC
)
3263 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3266 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3271 case SAFI_MULTICAST
:
3272 case SAFI_LABELED_UNICAST
:
3274 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3278 stream_putl(s
, 0); /* RD = 0, per RFC */
3280 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3285 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3288 if (attr
->mp_nexthop_len
== 0)
3289 stream_putc(s
, 0); /* no nexthop for flowspec */
3291 stream_putc(s
, attr
->mp_nexthop_len
);
3292 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3301 case SAFI_MULTICAST
:
3302 case SAFI_LABELED_UNICAST
:
3304 if (attr
->mp_nexthop_len
3305 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3307 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3308 stream_put(s
, &attr
->mp_nexthop_global
,
3310 stream_put(s
, &attr
->mp_nexthop_local
,
3313 stream_putc(s
, IPV6_MAX_BYTELEN
);
3314 stream_put(s
, &attr
->mp_nexthop_global
,
3318 case SAFI_MPLS_VPN
: {
3319 if (attr
->mp_nexthop_len
3320 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3322 stream_putl(s
, 0); /* RD = 0, per RFC */
3324 stream_put(s
, &attr
->mp_nexthop_global
,
3326 } else if (attr
->mp_nexthop_len
3327 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3329 stream_putl(s
, 0); /* RD = 0, per RFC */
3331 stream_put(s
, &attr
->mp_nexthop_global
,
3333 stream_putl(s
, 0); /* RD = 0, per RFC */
3335 stream_put(s
, &attr
->mp_nexthop_local
,
3340 stream_putc(s
, IPV6_MAX_BYTELEN
);
3341 stream_put(s
, &attr
->mp_nexthop_global
,
3345 stream_putc(s
, 0); /* no nexthop for flowspec */
3351 if (safi
!= SAFI_FLOWSPEC
)
3353 EC_BGP_ATTR_NH_SEND_LEN
,
3354 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3355 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3364 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3365 struct prefix
*p
, struct prefix_rd
*prd
,
3366 mpls_label_t
*label
, uint32_t num_labels
,
3367 int addpath_encode
, uint32_t addpath_tx_id
,
3370 if (safi
== SAFI_MPLS_VPN
) {
3372 stream_putl(s
, addpath_tx_id
);
3373 /* Label, RD, Prefix write. */
3374 stream_putc(s
, p
->prefixlen
+ 88);
3375 stream_put(s
, label
, BGP_LABEL_BYTES
);
3376 stream_put(s
, prd
->val
, 8);
3377 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3378 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3379 /* EVPN prefix - contents depend on type */
3380 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3381 addpath_encode
, addpath_tx_id
);
3382 } else if (safi
== SAFI_LABELED_UNICAST
) {
3383 /* Prefix write with label. */
3384 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3386 } else if (safi
== SAFI_FLOWSPEC
) {
3387 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3388 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3389 p
->u
.prefix_flowspec
.prefixlen
);
3391 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3394 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
3396 int size
= PSIZE(p
->prefixlen
);
3397 if (safi
== SAFI_MPLS_VPN
)
3399 else if (safi
== SAFI_LABELED_UNICAST
)
3400 size
+= BGP_LABEL_BYTES
;
3401 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3402 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3408 * Encodes the tunnel encapsulation attribute,
3409 * and with ENABLE_BGP_VNC the VNC attribute which uses
3410 * almost the same TLV format
3412 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3413 struct stream
*s
, struct attr
*attr
,
3416 unsigned int attrlenfield
= 0;
3417 unsigned int attrhdrlen
= 0;
3418 struct bgp_attr_encap_subtlv
*subtlvs
;
3419 struct bgp_attr_encap_subtlv
*st
;
3420 const char *attrname
;
3422 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3423 && (!attr
->encap_tunneltype
3424 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3428 case BGP_ATTR_ENCAP
:
3429 attrname
= "Tunnel Encap";
3430 subtlvs
= attr
->encap_subtlvs
;
3431 if (subtlvs
== NULL
) /* nothing to do */
3434 * The tunnel encap attr has an "outer" tlv.
3436 * L = total length of subtlvs,
3437 * V = concatenated subtlvs.
3439 attrlenfield
= 2 + 2; /* T + L */
3440 attrhdrlen
= 1 + 1; /* subTLV T + L */
3443 #if ENABLE_BGP_VNC_ATTR
3446 subtlvs
= attr
->vnc_subtlvs
;
3447 if (subtlvs
== NULL
) /* nothing to do */
3449 attrlenfield
= 0; /* no outer T + L */
3450 attrhdrlen
= 2 + 2; /* subTLV T + L */
3458 /* compute attr length */
3459 for (st
= subtlvs
; st
; st
= st
->next
) {
3460 attrlenfield
+= (attrhdrlen
+ st
->length
);
3463 if (attrlenfield
> 0xffff) {
3464 zlog_info("%s attribute is too long (length=%d), can't send it",
3465 attrname
, attrlenfield
);
3469 if (attrlenfield
> 0xff) {
3470 /* 2-octet length field */
3472 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3473 | BGP_ATTR_FLAG_EXTLEN
);
3474 stream_putc(s
, attrtype
);
3475 stream_putw(s
, attrlenfield
& 0xffff);
3477 /* 1-octet length field */
3478 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3479 stream_putc(s
, attrtype
);
3480 stream_putc(s
, attrlenfield
& 0xff);
3483 if (attrtype
== BGP_ATTR_ENCAP
) {
3484 /* write outer T+L */
3485 stream_putw(s
, attr
->encap_tunneltype
);
3486 stream_putw(s
, attrlenfield
- 4);
3489 /* write each sub-tlv */
3490 for (st
= subtlvs
; st
; st
= st
->next
) {
3491 if (attrtype
== BGP_ATTR_ENCAP
) {
3492 stream_putc(s
, st
->type
);
3493 stream_putc(s
, st
->length
);
3496 stream_putw(s
, st
->type
);
3497 stream_putw(s
, st
->length
);
3500 stream_put(s
, st
->value
, st
->length
);
3504 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3506 /* Set MP attribute length. Don't count the (2) bytes used to encode
3508 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3511 static int bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3513 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3514 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3515 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3516 PEER_FLAG_REMOVE_PRIVATE_AS
)
3517 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3518 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3519 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3520 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3521 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3522 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3527 /* Make attribute packet. */
3528 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3529 struct stream
*s
, struct attr
*attr
,
3530 struct bpacket_attr_vec_arr
*vecarr
,
3531 struct prefix
*p
, afi_t afi
, safi_t safi
,
3532 struct peer
*from
, struct prefix_rd
*prd
,
3533 mpls_label_t
*label
, uint32_t num_labels
,
3534 int addpath_encode
, uint32_t addpath_tx_id
)
3537 size_t aspath_sizep
;
3538 struct aspath
*aspath
;
3539 int send_as4_path
= 0;
3540 int send_as4_aggregator
= 0;
3541 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3546 /* Remember current pointer. */
3547 cp
= stream_get_endp(s
);
3550 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3551 && !peer_cap_enhe(peer
, afi
, safi
))) {
3552 size_t mpattrlen_pos
= 0;
3554 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3556 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3557 num_labels
, addpath_encode
,
3558 addpath_tx_id
, attr
);
3559 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3562 /* Origin attribute. */
3563 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3564 stream_putc(s
, BGP_ATTR_ORIGIN
);
3566 stream_putc(s
, attr
->origin
);
3568 /* AS path attribute. */
3570 /* If remote-peer is EBGP */
3571 if (peer
->sort
== BGP_PEER_EBGP
3572 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3573 PEER_FLAG_AS_PATH_UNCHANGED
)
3574 || attr
->aspath
->segments
== NULL
)
3575 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3576 PEER_FLAG_RSERVER_CLIENT
))) {
3577 aspath
= aspath_dup(attr
->aspath
);
3579 /* Even though we may not be configured for confederations we
3581 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3582 aspath
= aspath_delete_confed_seq(aspath
);
3584 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3585 /* Stuff our path CONFED_ID on the front */
3586 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3588 if (peer
->change_local_as
) {
3589 /* If replace-as is specified, we only use the
3590 change_local_as when
3591 advertising routes. */
3592 if (!CHECK_FLAG(peer
->flags
,
3593 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3594 if (bgp_append_local_as(peer
, afi
,
3596 aspath
= aspath_add_seq(
3597 aspath
, peer
->local_as
);
3598 aspath
= aspath_add_seq(aspath
,
3599 peer
->change_local_as
);
3601 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3604 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3605 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3607 aspath
= aspath_dup(attr
->aspath
);
3608 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3610 aspath
= attr
->aspath
;
3612 /* If peer is not AS4 capable, then:
3613 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3614 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3616 * types are in it (i.e. exclude them if they are there)
3617 * AND do this only if there is at least one asnum > 65535 in the
3619 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3621 * all ASnums > 65535 to BGP_AS_TRANS
3624 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3625 stream_putc(s
, BGP_ATTR_AS_PATH
);
3626 aspath_sizep
= stream_get_endp(s
);
3628 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3630 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3633 if (!use32bit
&& aspath_has_as4(aspath
))
3635 1; /* we'll do this later, at the correct place */
3637 /* Nexthop attribute. */
3638 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3639 && !peer_cap_enhe(peer
, afi
, safi
)) {
3640 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3642 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3643 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3644 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3645 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3648 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3649 } else if (peer_cap_enhe(from
, afi
, safi
)
3650 || (nh_afi
== AFI_IP6
)) {
3652 * Likely this is the case when an IPv4 prefix was
3653 * received with Extended Next-hop capability in this
3654 * or another vrf and is now being advertised to
3655 * non-ENHE peers. Since peer_cap_enhe only checks
3656 * peers in this vrf, also check the nh_afi to catch
3657 * the case where the originator was in another vrf.
3658 * Setting the mandatory (ipv4) next-hop attribute here
3659 * to enable implicit next-hop self with correct A-F
3660 * (ipv4 address family).
3662 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3663 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3664 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3667 stream_put_ipv4(s
, 0);
3671 /* MED attribute. */
3672 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3673 || bgp
->maxmed_active
) {
3674 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3675 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3677 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3681 /* Local preference. */
3682 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3683 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3684 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3686 stream_putl(s
, attr
->local_pref
);
3689 /* Atomic aggregate. */
3690 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3691 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3692 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3697 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3698 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3699 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3700 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3703 /* AS4 capable peer */
3705 stream_putl(s
, attr
->aggregator_as
);
3707 /* 2-byte AS peer */
3710 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3712 if (attr
->aggregator_as
> 65535) {
3713 stream_putw(s
, BGP_AS_TRANS
);
3715 /* we have to send AS4_AGGREGATOR, too.
3716 * we'll do that later in order to send
3717 * attributes in ascending
3720 send_as4_aggregator
= 1;
3722 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3724 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3727 /* Community attribute. */
3728 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3729 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3730 if (attr
->community
->size
* 4 > 255) {
3732 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3733 | BGP_ATTR_FLAG_EXTLEN
);
3734 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3735 stream_putw(s
, attr
->community
->size
* 4);
3738 BGP_ATTR_FLAG_OPTIONAL
3739 | BGP_ATTR_FLAG_TRANS
);
3740 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3741 stream_putc(s
, attr
->community
->size
* 4);
3743 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3747 * Large Community attribute.
3749 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3750 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3751 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3752 if (lcom_length(attr
->lcommunity
) > 255) {
3754 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3755 | BGP_ATTR_FLAG_EXTLEN
);
3756 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3757 stream_putw(s
, lcom_length(attr
->lcommunity
));
3760 BGP_ATTR_FLAG_OPTIONAL
3761 | BGP_ATTR_FLAG_TRANS
);
3762 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3763 stream_putc(s
, lcom_length(attr
->lcommunity
));
3765 stream_put(s
, attr
->lcommunity
->val
,
3766 lcom_length(attr
->lcommunity
));
3769 /* Route Reflector. */
3770 if (peer
->sort
== BGP_PEER_IBGP
&& from
3771 && from
->sort
== BGP_PEER_IBGP
) {
3772 /* Originator ID. */
3773 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3774 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3777 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3778 stream_put_in_addr(s
, &attr
->originator_id
);
3780 stream_put_in_addr(s
, &from
->remote_id
);
3783 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3784 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3786 if (attr
->cluster
) {
3787 stream_putc(s
, attr
->cluster
->length
+ 4);
3788 /* If this peer configuration's parent BGP has
3790 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3791 stream_put_in_addr(s
, &bgp
->cluster_id
);
3793 stream_put_in_addr(s
, &bgp
->router_id
);
3794 stream_put(s
, attr
->cluster
->list
,
3795 attr
->cluster
->length
);
3798 /* If this peer configuration's parent BGP has
3800 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3801 stream_put_in_addr(s
, &bgp
->cluster_id
);
3803 stream_put_in_addr(s
, &bgp
->router_id
);
3807 /* Extended Communities attribute. */
3808 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3809 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3810 if (peer
->sort
== BGP_PEER_IBGP
3811 || peer
->sort
== BGP_PEER_CONFED
) {
3812 if (attr
->ecommunity
->size
* 8 > 255) {
3814 BGP_ATTR_FLAG_OPTIONAL
3815 | BGP_ATTR_FLAG_TRANS
3816 | BGP_ATTR_FLAG_EXTLEN
);
3817 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3818 stream_putw(s
, attr
->ecommunity
->size
* 8);
3821 BGP_ATTR_FLAG_OPTIONAL
3822 | BGP_ATTR_FLAG_TRANS
);
3823 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3824 stream_putc(s
, attr
->ecommunity
->size
* 8);
3826 stream_put(s
, attr
->ecommunity
->val
,
3827 attr
->ecommunity
->size
* 8);
3831 int ecom_tr_size
= 0;
3834 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3835 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3838 if (CHECK_FLAG(tbit
,
3839 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3846 if (ecom_tr_size
* 8 > 255) {
3849 BGP_ATTR_FLAG_OPTIONAL
3850 | BGP_ATTR_FLAG_TRANS
3851 | BGP_ATTR_FLAG_EXTLEN
);
3853 BGP_ATTR_EXT_COMMUNITIES
);
3854 stream_putw(s
, ecom_tr_size
* 8);
3858 BGP_ATTR_FLAG_OPTIONAL
3859 | BGP_ATTR_FLAG_TRANS
);
3861 BGP_ATTR_EXT_COMMUNITIES
);
3862 stream_putc(s
, ecom_tr_size
* 8);
3865 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3866 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3871 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3874 stream_put(s
, pnt
, 8);
3880 /* Label index attribute. */
3881 if (safi
== SAFI_LABELED_UNICAST
) {
3882 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3883 uint32_t label_index
;
3885 label_index
= attr
->label_index
;
3887 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3889 BGP_ATTR_FLAG_OPTIONAL
3890 | BGP_ATTR_FLAG_TRANS
);
3891 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3893 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3895 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3896 stream_putc(s
, 0); // reserved
3897 stream_putw(s
, 0); // flags
3898 stream_putl(s
, label_index
);
3903 /* SRv6 Service Information Attribute. */
3904 if (afi
== AFI_IP
&& safi
== SAFI_MPLS_VPN
) {
3905 if (attr
->srv6_l3vpn
) {
3906 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
3907 | BGP_ATTR_FLAG_TRANS
);
3908 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3909 stream_putc(s
, 24); /* tlv len */
3910 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
3911 stream_putw(s
, 21); /* sub-tlv len */
3912 stream_putc(s
, 0); /* reserved */
3913 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
3914 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
3915 stream_putc(s
, 0); /* sid_flags */
3916 stream_putw(s
, 0xffff); /* endpoint */
3917 stream_putc(s
, 0); /* reserved */
3918 } else if (attr
->srv6_vpn
) {
3919 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
3920 | BGP_ATTR_FLAG_TRANS
);
3921 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3922 stream_putc(s
, 22); /* tlv len */
3923 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
3924 stream_putw(s
, 0x13); /* tlv len */
3925 stream_putc(s
, 0x00); /* reserved */
3926 stream_putc(s
, 0x01); /* sid_type */
3927 stream_putc(s
, 0x00); /* sif_flags */
3928 stream_put(s
, &attr
->srv6_vpn
->sid
,
3929 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
3933 if (send_as4_path
) {
3934 /* If the peer is NOT As4 capable, AND */
3935 /* there are ASnums > 65535 in path THEN
3936 * give out AS4_PATH */
3938 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3940 * Hm, I wonder... confederation things *should* only be at
3941 * the beginning of an aspath, right? Then we should use
3942 * aspath_delete_confed_seq for this, because it is already
3944 * Folks, talk to me: what is reasonable here!?
3946 aspath
= aspath_delete_confed_seq(aspath
);
3949 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3950 | BGP_ATTR_FLAG_EXTLEN
);
3951 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3952 aspath_sizep
= stream_get_endp(s
);
3954 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3957 if (aspath
!= attr
->aspath
)
3958 aspath_free(aspath
);
3960 if (send_as4_aggregator
) {
3961 /* send AS4_AGGREGATOR, at this place */
3962 /* this section of code moved here in order to ensure the
3964 * *ascending* order of attributes
3966 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3967 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3969 stream_putl(s
, attr
->aggregator_as
);
3970 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3973 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3974 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3975 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3976 /* Tunnel Encap attribute */
3977 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3979 #if ENABLE_BGP_VNC_ATTR
3981 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3986 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
3987 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3988 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
3989 stream_putc(s
, 9); // Length
3990 stream_putc(s
, 0); // Flags
3991 stream_putc(s
, attr
->pmsi_tnl_type
);
3992 stream_put(s
, &(attr
->label
),
3993 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
3994 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3995 // Unicast tunnel endpoint IP address
3998 /* Unknown transit attribute. */
4000 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
4002 /* Return total size of attribute. */
4003 return stream_get_endp(s
) - cp
;
4006 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4008 unsigned long attrlen_pnt
;
4010 iana_safi_t pkt_safi
;
4012 /* Set extended bit always to encode the attribute length as 2 bytes */
4013 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4014 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4016 attrlen_pnt
= stream_get_endp(s
);
4017 stream_putw(s
, 0); /* Length of this attribute. */
4019 /* Convert AFI, SAFI to values for packet. */
4020 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4022 stream_putw(s
, pkt_afi
);
4023 stream_putc(s
, pkt_safi
);
4028 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
4029 safi_t safi
, struct prefix_rd
*prd
,
4030 mpls_label_t
*label
, uint32_t num_labels
,
4031 int addpath_encode
, uint32_t addpath_tx_id
,
4034 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4036 if (safi
== SAFI_LABELED_UNICAST
) {
4037 label
= (mpls_label_t
*)wlabel
;
4041 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4042 addpath_encode
, addpath_tx_id
, attr
);
4045 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4047 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4050 /* Initialization of attribute. */
4051 void bgp_attr_init(void)
4064 void bgp_attr_finish(void)
4069 ecommunity_finish();
4070 lcommunity_finish();
4077 /* Make attribute packet. */
4078 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4079 struct prefix
*prefix
)
4084 struct aspath
*aspath
;
4085 int addpath_encode
= 0;
4086 uint32_t addpath_tx_id
= 0;
4088 /* Remember current pointer. */
4089 cp
= stream_get_endp(s
);
4091 /* Place holder of length. */
4094 /* Origin attribute. */
4095 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4096 stream_putc(s
, BGP_ATTR_ORIGIN
);
4098 stream_putc(s
, attr
->origin
);
4100 aspath
= attr
->aspath
;
4102 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4103 stream_putc(s
, BGP_ATTR_AS_PATH
);
4104 aspath_lenp
= stream_get_endp(s
);
4107 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4109 /* Nexthop attribute. */
4110 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4111 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4112 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4113 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4115 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4118 /* MED attribute. */
4119 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4120 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4121 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4123 stream_putl(s
, attr
->med
);
4126 /* Local preference. */
4127 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4128 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4129 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4131 stream_putl(s
, attr
->local_pref
);
4134 /* Atomic aggregate. */
4135 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4136 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4137 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4142 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4143 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4144 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4146 stream_putl(s
, attr
->aggregator_as
);
4147 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4150 /* Community attribute. */
4151 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4152 if (attr
->community
->size
* 4 > 255) {
4154 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4155 | BGP_ATTR_FLAG_EXTLEN
);
4156 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4157 stream_putw(s
, attr
->community
->size
* 4);
4160 BGP_ATTR_FLAG_OPTIONAL
4161 | BGP_ATTR_FLAG_TRANS
);
4162 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4163 stream_putc(s
, attr
->community
->size
* 4);
4165 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4168 /* Large Community attribute. */
4169 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4170 if (lcom_length(attr
->lcommunity
) > 255) {
4172 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4173 | BGP_ATTR_FLAG_EXTLEN
);
4174 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4175 stream_putw(s
, lcom_length(attr
->lcommunity
));
4178 BGP_ATTR_FLAG_OPTIONAL
4179 | BGP_ATTR_FLAG_TRANS
);
4180 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4181 stream_putc(s
, lcom_length(attr
->lcommunity
));
4184 stream_put(s
, attr
->lcommunity
->val
,
4185 lcom_length(attr
->lcommunity
));
4188 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4189 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4190 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4191 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4194 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4195 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4196 sizep
= stream_get_endp(s
);
4199 stream_putc(s
, 0); /* Marker: Attribute length. */
4200 stream_putw(s
, AFI_IP6
); /* AFI */
4201 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4204 stream_putc(s
, attr
->mp_nexthop_len
);
4205 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4206 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4207 stream_put(s
, &attr
->mp_nexthop_local
,
4214 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
4217 /* Set MP attribute length. */
4218 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4222 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4223 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4225 BGP_ATTR_FLAG_OPTIONAL
4226 | BGP_ATTR_FLAG_TRANS
);
4227 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4229 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4230 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4231 stream_putc(s
, 0); // reserved
4232 stream_putw(s
, 0); // flags
4233 stream_putl(s
, attr
->label_index
);
4237 /* Return total size of attribute. */
4238 len
= stream_get_endp(s
) - cp
- 2;
4239 stream_putw_at(s
, cp
, len
);