1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_label.h"
43 #include "bgpd/bgp_packet.h"
44 #include "bgpd/bgp_ecommunity.h"
45 #include "bgpd/bgp_lcommunity.h"
46 #include "bgpd/bgp_updgrp.h"
47 #include "bgpd/bgp_encap_types.h"
49 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
50 #include "bgp_encap_types.h"
51 #include "bgp_vnc_types.h"
53 #include "bgp_encap_types.h"
56 /* Attribute strings for logging. */
57 static const struct message attr_str
[] = {
58 {BGP_ATTR_ORIGIN
, "ORIGIN"},
59 {BGP_ATTR_AS_PATH
, "AS_PATH"},
60 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
61 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
62 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
63 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
64 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
65 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
66 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
67 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
68 {BGP_ATTR_DPA
, "DPA"},
69 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
70 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
71 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
72 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
73 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
74 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
75 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
76 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
77 {BGP_ATTR_ENCAP
, "ENCAP"},
79 {BGP_ATTR_VNC
, "VNC"},
81 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
82 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
85 static const struct message attr_flag_str
[] =
87 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
88 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
89 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
90 /* bgp_attr_flags_diagnose() relies on this bit being last in
92 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
95 static struct hash
*cluster_hash
;
97 static void *cluster_hash_alloc(void *p
)
99 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
100 struct cluster_list
*cluster
;
102 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
103 cluster
->length
= val
->length
;
105 if (cluster
->length
) {
106 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
107 memcpy(cluster
->list
, val
->list
, val
->length
);
109 cluster
->list
= NULL
;
116 /* Cluster list related functions. */
117 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
119 struct cluster_list tmp
;
120 struct cluster_list
*cluster
;
125 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
130 int cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
134 for (i
= 0; i
< cluster
->length
/ 4; i
++)
135 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
140 static unsigned int cluster_hash_key_make(void *p
)
142 const struct cluster_list
*cluster
= p
;
144 return jhash(cluster
->list
, cluster
->length
, 0);
147 static int cluster_hash_cmp(const void *p1
, const void *p2
)
149 const struct cluster_list
*cluster1
= p1
;
150 const struct cluster_list
*cluster2
= p2
;
152 return (cluster1
->length
== cluster2
->length
153 && memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
)
157 static void cluster_free(struct cluster_list
*cluster
)
160 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
161 XFREE(MTYPE_CLUSTER
, cluster
);
164 static struct cluster_list
*cluster_dup(struct cluster_list
*cluster
)
166 struct cluster_list
*new;
168 new = XCALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
169 new->length
= cluster
->length
;
171 if (cluster
->length
) {
172 new->list
= XMALLOC(MTYPE_CLUSTER_VAL
, cluster
->length
);
173 memcpy(new->list
, cluster
->list
, cluster
->length
);
180 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
182 struct cluster_list
*find
;
184 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
190 void cluster_unintern(struct cluster_list
*cluster
)
195 if (cluster
->refcnt
== 0) {
196 hash_release(cluster_hash
, cluster
);
197 cluster_free(cluster
);
201 static void cluster_init(void)
204 hash_create(cluster_hash_key_make
, cluster_hash_cmp
, NULL
);
207 static void cluster_finish(void)
209 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
210 hash_free(cluster_hash
);
214 static struct hash
*encap_hash
= NULL
;
216 static struct hash
*vnc_hash
= NULL
;
219 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
221 struct bgp_attr_encap_subtlv
*new;
222 struct bgp_attr_encap_subtlv
*tail
;
223 struct bgp_attr_encap_subtlv
*p
;
225 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
226 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
228 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
231 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
234 memcpy(tail
, p
, size
);
241 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
243 struct bgp_attr_encap_subtlv
*next
;
247 XFREE(MTYPE_ENCAP_TLV
, p
);
252 void bgp_attr_flush_encap(struct attr
*attr
)
257 if (attr
->encap_subtlvs
) {
258 encap_free(attr
->encap_subtlvs
);
259 attr
->encap_subtlvs
= NULL
;
262 if (attr
->vnc_subtlvs
) {
263 encap_free(attr
->vnc_subtlvs
);
264 attr
->vnc_subtlvs
= NULL
;
270 * Compare encap sub-tlv chains
275 * This algorithm could be made faster if needed
277 static int encap_same(struct bgp_attr_encap_subtlv
*h1
,
278 struct bgp_attr_encap_subtlv
*h2
)
280 struct bgp_attr_encap_subtlv
*p
;
281 struct bgp_attr_encap_subtlv
*q
;
285 if (h1
== NULL
|| h2
== NULL
)
288 for (p
= h1
; p
; p
= p
->next
) {
289 for (q
= h2
; q
; q
= q
->next
) {
290 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
291 && !memcmp(p
->value
, q
->value
, p
->length
)) {
300 for (p
= h2
; p
; p
= p
->next
) {
301 for (q
= h1
; q
; q
= q
->next
) {
302 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
303 && !memcmp(p
->value
, q
->value
, p
->length
)) {
315 static void *encap_hash_alloc(void *p
)
317 /* Encap structure is already allocated. */
328 static struct bgp_attr_encap_subtlv
*
329 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
331 struct bgp_attr_encap_subtlv
*find
;
332 struct hash
*hash
= encap_hash
;
334 if (type
== VNC_SUBTLV_TYPE
)
338 find
= hash_get(hash
, encap
, encap_hash_alloc
);
346 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
347 encap_subtlv_type type
)
349 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
353 if (encap
->refcnt
== 0) {
354 struct hash
*hash
= encap_hash
;
356 if (type
== VNC_SUBTLV_TYPE
)
359 hash_release(hash
, encap
);
365 static unsigned int encap_hash_key_make(void *p
)
367 const struct bgp_attr_encap_subtlv
*encap
= p
;
369 return jhash(encap
->value
, encap
->length
, 0);
372 static int encap_hash_cmp(const void *p1
, const void *p2
)
374 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
375 (struct bgp_attr_encap_subtlv
*)p2
);
378 static void encap_init(void)
380 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
, NULL
);
382 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
, NULL
);
386 static void encap_finish(void)
388 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
389 hash_free(encap_hash
);
392 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
398 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
406 return !memcmp(&(a1
->evpn_overlay
), &(a2
->evpn_overlay
),
407 sizeof(struct overlay_index
));
410 /* Unknown transit attribute. */
411 static struct hash
*transit_hash
;
413 static void transit_free(struct transit
*transit
)
416 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
417 XFREE(MTYPE_TRANSIT
, transit
);
420 static struct transit
*transit_dup(struct transit
*transit
)
424 new = XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
425 new->length
= transit
->length
;
427 new->val
= XMALLOC(MTYPE_TRANSIT_VAL
, transit
->length
);
428 memcpy(new->val
, transit
->val
, transit
->length
);
435 static void *transit_hash_alloc(void *p
)
437 /* Transit structure is already allocated. */
441 static struct transit
*transit_intern(struct transit
*transit
)
443 struct transit
*find
;
445 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
447 transit_free(transit
);
453 void transit_unintern(struct transit
*transit
)
458 if (transit
->refcnt
== 0) {
459 hash_release(transit_hash
, transit
);
460 transit_free(transit
);
464 static unsigned int transit_hash_key_make(void *p
)
466 const struct transit
*transit
= p
;
468 return jhash(transit
->val
, transit
->length
, 0);
471 static int transit_hash_cmp(const void *p1
, const void *p2
)
473 const struct transit
*transit1
= p1
;
474 const struct transit
*transit2
= p2
;
476 return (transit1
->length
== transit2
->length
477 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
480 static void transit_init(void)
483 hash_create(transit_hash_key_make
, transit_hash_cmp
, NULL
);
486 static void transit_finish(void)
488 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
489 hash_free(transit_hash
);
493 /* Attribute hash routines. */
494 static struct hash
*attrhash
;
496 /* Shallow copy of an attribute
497 * Though, not so shallow that it doesn't copy the contents
498 * of the attr_extra pointed to by 'extra'
500 void bgp_attr_dup(struct attr
*new, struct attr
*orig
)
505 void bgp_attr_deep_dup(struct attr
*new, struct attr
*orig
)
508 new->aspath
= aspath_dup(orig
->aspath
);
511 new->community
= community_dup(orig
->community
);
513 if (orig
->ecommunity
)
514 new->ecommunity
= ecommunity_dup(orig
->ecommunity
);
516 new->cluster
= cluster_dup(orig
->cluster
);
518 new->transit
= transit_dup(orig
->transit
);
519 if (orig
->encap_subtlvs
)
520 new->encap_subtlvs
= encap_tlv_dup(orig
->encap_subtlvs
);
522 if (orig
->vnc_subtlvs
)
523 new->vnc_subtlvs
= encap_tlv_dup(orig
->vnc_subtlvs
);
527 void bgp_attr_deep_free(struct attr
*attr
)
530 aspath_free(attr
->aspath
);
533 community_free(attr
->community
);
535 if (attr
->ecommunity
)
536 ecommunity_free(&attr
->ecommunity
);
538 cluster_free(attr
->cluster
);
540 transit_free(attr
->transit
);
541 if (attr
->encap_subtlvs
)
542 encap_free(attr
->encap_subtlvs
);
544 if (attr
->vnc_subtlvs
)
545 encap_free(attr
->vnc_subtlvs
);
549 unsigned long int attr_count(void)
551 return attrhash
->count
;
554 unsigned long int attr_unknown_count(void)
556 return transit_hash
->count
;
559 unsigned int attrhash_key_make(void *p
)
561 const struct attr
*attr
= (struct attr
*)p
;
563 #define MIX(val) key = jhash_1word(val, key)
566 MIX(attr
->nexthop
.s_addr
);
568 MIX(attr
->local_pref
);
571 key
+= attr
->nexthop
.s_addr
;
573 key
+= attr
->local_pref
;
575 MIX(attr
->aggregator_as
);
576 MIX(attr
->aggregator_addr
.s_addr
);
578 MIX(attr
->mp_nexthop_global_in
.s_addr
);
579 MIX(attr
->originator_id
.s_addr
);
582 MIX(attr
->label_index
);
585 MIX(aspath_key_make(attr
->aspath
));
587 MIX(community_hash_make(attr
->community
));
589 if (attr
->lcommunity
)
590 MIX(lcommunity_hash_make(attr
->lcommunity
));
591 if (attr
->ecommunity
)
592 MIX(ecommunity_hash_make(attr
->ecommunity
));
594 MIX(cluster_hash_key_make(attr
->cluster
));
596 MIX(transit_hash_key_make(attr
->transit
));
597 if (attr
->encap_subtlvs
)
598 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
600 if (attr
->vnc_subtlvs
)
601 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
603 MIX(attr
->mp_nexthop_len
);
604 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
605 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
610 int attrhash_cmp(const void *p1
, const void *p2
)
612 const struct attr
*attr1
= p1
;
613 const struct attr
*attr2
= p2
;
615 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
616 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
617 && attr1
->aspath
== attr2
->aspath
618 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
619 && attr1
->local_pref
== attr2
->local_pref
620 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
621 if (attr1
->aggregator_as
== attr2
->aggregator_as
622 && attr1
->aggregator_addr
.s_addr
623 == attr2
->aggregator_addr
.s_addr
624 && attr1
->weight
== attr2
->weight
625 && attr1
->tag
== attr2
->tag
626 && attr1
->label_index
== attr2
->label_index
627 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
628 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
629 &attr2
->mp_nexthop_global
)
630 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
631 &attr2
->mp_nexthop_local
)
632 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
633 &attr2
->mp_nexthop_global_in
)
634 && attr1
->ecommunity
== attr2
->ecommunity
635 && attr1
->lcommunity
== attr2
->lcommunity
636 && attr1
->cluster
== attr2
->cluster
637 && attr1
->transit
== attr2
->transit
638 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
639 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
641 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
643 && IPV4_ADDR_SAME(&attr1
->originator_id
,
644 &attr2
->originator_id
)
645 && overlay_index_same(attr1
, attr2
))
652 static void attrhash_init(void)
655 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
659 * special for hash_clean below
661 static void attr_vfree(void *attr
)
663 XFREE(MTYPE_ATTR
, attr
);
666 static void attrhash_finish(void)
668 hash_clean(attrhash
, attr_vfree
);
673 static void attr_show_all_iterator(struct hash_backet
*backet
, struct vty
*vty
)
675 struct attr
*attr
= backet
->data
;
677 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
678 inet_ntoa(attr
->nexthop
));
681 void attr_show_all(struct vty
*vty
)
683 hash_iterate(attrhash
, (void (*)(struct hash_backet
*,
684 void *))attr_show_all_iterator
,
688 static void *bgp_attr_hash_alloc(void *p
)
690 struct attr
*val
= (struct attr
*)p
;
693 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
695 if (val
->encap_subtlvs
) {
696 val
->encap_subtlvs
= NULL
;
699 if (val
->vnc_subtlvs
) {
700 val
->vnc_subtlvs
= NULL
;
707 /* Internet argument attribute. */
708 struct attr
*bgp_attr_intern(struct attr
*attr
)
712 /* Intern referenced strucutre. */
714 if (!attr
->aspath
->refcnt
)
715 attr
->aspath
= aspath_intern(attr
->aspath
);
717 attr
->aspath
->refcnt
++;
719 if (attr
->community
) {
720 if (!attr
->community
->refcnt
)
721 attr
->community
= community_intern(attr
->community
);
723 attr
->community
->refcnt
++;
726 if (attr
->ecommunity
) {
727 if (!attr
->ecommunity
->refcnt
)
728 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
730 attr
->ecommunity
->refcnt
++;
732 if (attr
->lcommunity
) {
733 if (!attr
->lcommunity
->refcnt
)
734 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
736 attr
->lcommunity
->refcnt
++;
739 if (!attr
->cluster
->refcnt
)
740 attr
->cluster
= cluster_intern(attr
->cluster
);
742 attr
->cluster
->refcnt
++;
745 if (!attr
->transit
->refcnt
)
746 attr
->transit
= transit_intern(attr
->transit
);
748 attr
->transit
->refcnt
++;
750 if (attr
->encap_subtlvs
) {
751 if (!attr
->encap_subtlvs
->refcnt
)
752 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
755 attr
->encap_subtlvs
->refcnt
++;
758 if (attr
->vnc_subtlvs
) {
759 if (!attr
->vnc_subtlvs
->refcnt
)
760 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
763 attr
->vnc_subtlvs
->refcnt
++;
767 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
774 * Increment the refcount on various structures that attr holds.
775 * Note on usage: call _only_ when the 'attr' object has already
776 * been 'intern'ed and exists in 'attrhash' table. The function
777 * serves to hold a reference to that (real) object.
778 * Note also that the caller can safely call bgp_attr_unintern()
779 * after calling bgp_attr_refcount(). That would release the
780 * reference and could result in a free() of the attr object.
782 struct attr
*bgp_attr_refcount(struct attr
*attr
)
784 /* Intern referenced strucutre. */
786 attr
->aspath
->refcnt
++;
789 attr
->community
->refcnt
++;
791 if (attr
->ecommunity
)
792 attr
->ecommunity
->refcnt
++;
795 attr
->cluster
->refcnt
++;
798 attr
->transit
->refcnt
++;
800 if (attr
->encap_subtlvs
)
801 attr
->encap_subtlvs
->refcnt
++;
804 if (attr
->vnc_subtlvs
)
805 attr
->vnc_subtlvs
->refcnt
++;
812 /* Make network statement's attribute. */
813 struct attr
*bgp_attr_default_set(struct attr
*attr
, u_char origin
)
815 memset(attr
, 0, sizeof(struct attr
));
817 attr
->origin
= origin
;
818 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
819 attr
->aspath
= aspath_empty();
820 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
821 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
823 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
824 attr
->label
= MPLS_INVALID_LABEL
;
825 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
826 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
831 /* Create the attributes for an aggregate */
832 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, u_char origin
,
833 struct aspath
*aspath
,
834 struct community
*community
, int as_set
,
835 u_char atomic_aggregate
)
840 memset(&attr
, 0, sizeof(struct attr
));
842 /* Origin attribute. */
843 attr
.origin
= origin
;
844 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
846 /* AS path attribute. */
848 attr
.aspath
= aspath_intern(aspath
);
850 attr
.aspath
= aspath_empty();
851 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
853 /* Next hop attribute. */
854 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
857 attr
.community
= community
;
858 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
861 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
862 attr
.label
= MPLS_INVALID_LABEL
;
863 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
864 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
865 if (!as_set
|| atomic_aggregate
)
866 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
867 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
868 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
869 attr
.aggregator_as
= bgp
->confed_id
;
871 attr
.aggregator_as
= bgp
->as
;
872 attr
.aggregator_addr
= bgp
->router_id
;
873 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
874 attr
.label
= MPLS_INVALID_LABEL
;
876 new = bgp_attr_intern(&attr
);
878 aspath_unintern(&new->aspath
);
882 /* Unintern just the sub-components of the attr, but not the attr */
883 void bgp_attr_unintern_sub(struct attr
*attr
)
885 /* aspath refcount shoud be decrement. */
887 aspath_unintern(&attr
->aspath
);
888 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
891 community_unintern(&attr
->community
);
892 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
894 if (attr
->ecommunity
)
895 ecommunity_unintern(&attr
->ecommunity
);
896 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
898 if (attr
->lcommunity
)
899 lcommunity_unintern(&attr
->lcommunity
);
900 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
903 cluster_unintern(attr
->cluster
);
904 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
907 transit_unintern(attr
->transit
);
909 if (attr
->encap_subtlvs
)
910 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
913 if (attr
->vnc_subtlvs
)
914 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
918 /* Free bgp attribute and aspath. */
919 void bgp_attr_unintern(struct attr
**pattr
)
921 struct attr
*attr
= *pattr
;
925 /* Decrement attribute reference. */
930 /* If reference becomes zero then free attribute object. */
931 if (attr
->refcnt
== 0) {
932 ret
= hash_release(attrhash
, attr
);
934 XFREE(MTYPE_ATTR
, attr
);
938 bgp_attr_unintern_sub(&tmp
);
941 void bgp_attr_flush(struct attr
*attr
)
943 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
944 aspath_free(attr
->aspath
);
947 if (attr
->community
&& !attr
->community
->refcnt
) {
948 community_free(attr
->community
);
949 attr
->community
= NULL
;
952 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
953 ecommunity_free(&attr
->ecommunity
);
954 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
955 lcommunity_free(&attr
->lcommunity
);
956 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
957 cluster_free(attr
->cluster
);
958 attr
->cluster
= NULL
;
960 if (attr
->transit
&& !attr
->transit
->refcnt
) {
961 transit_free(attr
->transit
);
962 attr
->transit
= NULL
;
964 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
965 encap_free(attr
->encap_subtlvs
);
966 attr
->encap_subtlvs
= NULL
;
969 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
970 encap_free(attr
->vnc_subtlvs
);
971 attr
->vnc_subtlvs
= NULL
;
976 /* Implement draft-scudder-idr-optional-transitive behaviour and
977 * avoid resetting sessions for malformed attributes which are
978 * are partial/optional and hence where the error likely was not
979 * introduced by the sending neighbour.
981 static bgp_attr_parse_ret_t
982 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, u_char subcode
,
985 struct peer
*const peer
= args
->peer
;
986 const u_int8_t flags
= args
->flags
;
987 /* startp and length must be special-cased, as whether or not to
988 * send the attribute data with the NOTIFY depends on the error,
989 * the caller therefore signals this with the seperate length argument
991 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
993 /* Only relax error handling for eBGP peers */
994 if (peer
->sort
!= BGP_PEER_EBGP
) {
995 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
996 notify_datap
, length
);
997 return BGP_ATTR_PARSE_ERROR
;
1000 /* Adjust the stream getp to the end of the attribute, in case we can
1001 * still proceed but the caller hasn't read all the attribute.
1003 stream_set_getp(BGP_INPUT(peer
),
1004 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1007 switch (args
->type
) {
1008 /* where an attribute is relatively inconsequential, e.g. it does not
1009 * affect route selection, and can be safely ignored, then any such
1010 * attributes which are malformed should just be ignored and the route
1011 * processed as normal.
1013 case BGP_ATTR_AS4_AGGREGATOR
:
1014 case BGP_ATTR_AGGREGATOR
:
1015 case BGP_ATTR_ATOMIC_AGGREGATE
:
1016 return BGP_ATTR_PARSE_PROCEED
;
1018 /* Core attributes, particularly ones which may influence route
1019 * selection, should always cause session resets
1021 case BGP_ATTR_ORIGIN
:
1022 case BGP_ATTR_AS_PATH
:
1023 case BGP_ATTR_NEXT_HOP
:
1024 case BGP_ATTR_MULTI_EXIT_DISC
:
1025 case BGP_ATTR_LOCAL_PREF
:
1026 case BGP_ATTR_COMMUNITIES
:
1027 case BGP_ATTR_ORIGINATOR_ID
:
1028 case BGP_ATTR_CLUSTER_LIST
:
1029 case BGP_ATTR_MP_REACH_NLRI
:
1030 case BGP_ATTR_MP_UNREACH_NLRI
:
1031 case BGP_ATTR_EXT_COMMUNITIES
:
1032 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1033 notify_datap
, length
);
1034 return BGP_ATTR_PARSE_ERROR
;
1037 /* Partial optional attributes that are malformed should not cause
1038 * the whole session to be reset. Instead treat it as a withdrawal
1039 * of the routes, if possible.
1041 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1042 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1043 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1044 return BGP_ATTR_PARSE_WITHDRAW
;
1046 /* default to reset */
1047 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1050 /* Find out what is wrong with the path attribute flag bits and log the error.
1051 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1052 Extended Length. Checking O/T/P bits at once implies, that the attribute
1053 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1054 non-transitive" attribute. */
1056 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1057 u_int8_t desired_flags
/* how RFC says it must be */
1061 u_char real_flags
= args
->flags
;
1062 const u_int8_t attr_code
= args
->type
;
1064 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1065 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1066 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1067 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1068 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1069 zlog_err("%s attribute must%s be flagged as \"%s\"",
1070 lookup_msg(attr_str
, attr_code
, NULL
),
1071 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1074 attr_flag_str
[i
].str
);
1079 "Strange, %s called for attr %s, but no problem found with flags"
1080 " (real flags 0x%x, desired 0x%x)",
1081 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1082 real_flags
, desired_flags
);
1086 /* Required flags for attributes. EXTLEN will be masked off when testing,
1087 * as will PARTIAL for optional+transitive attributes.
1089 const u_int8_t attr_flags_values
[] = {
1090 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1091 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1092 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1093 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1094 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1095 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1096 [BGP_ATTR_AGGREGATOR
] =
1097 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1098 [BGP_ATTR_COMMUNITIES
] =
1099 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1100 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1101 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1102 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1103 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1104 [BGP_ATTR_EXT_COMMUNITIES
] =
1105 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1106 [BGP_ATTR_AS4_PATH
] =
1107 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1108 [BGP_ATTR_AS4_AGGREGATOR
] =
1109 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1110 [BGP_ATTR_LARGE_COMMUNITIES
] =
1111 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1112 [BGP_ATTR_PREFIX_SID
] =
1113 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1115 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1117 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1119 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1120 const u_int8_t flags
= args
->flags
;
1121 const u_int8_t attr_code
= args
->type
;
1123 /* there may be attributes we don't know about */
1124 if (attr_code
> attr_flags_values_max
)
1126 if (attr_flags_values
[attr_code
] == 0)
1129 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1133 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1134 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1136 "%s well-known attributes must have transitive flag set (%x)",
1137 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1141 /* "For well-known attributes and for optional non-transitive
1143 * the Partial bit MUST be set to 0."
1145 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1146 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1148 "%s well-known attribute "
1149 "must NOT have the partial flag set (%x)",
1150 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1153 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1154 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1156 "%s optional + transitive attribute "
1157 "must NOT have the partial flag set (%x)",
1158 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1163 /* Optional transitive attributes may go through speakers that don't
1164 * reocgnise them and set the Partial bit.
1166 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1167 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1168 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1170 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1173 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1177 /* Get origin attribute of the update message. */
1178 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1180 struct peer
*const peer
= args
->peer
;
1181 struct attr
*const attr
= args
->attr
;
1182 const bgp_size_t length
= args
->length
;
1184 /* If any recognized attribute has Attribute Length that conflicts
1185 with the expected length (based on the attribute type code), then
1186 the Error Subcode is set to Attribute Length Error. The Data
1187 field contains the erroneous attribute (type, length and
1190 zlog_err("Origin attribute length is not one %d", length
);
1191 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1195 /* Fetch origin attribute. */
1196 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1198 /* If the ORIGIN attribute has an undefined value, then the Error
1199 Subcode is set to Invalid Origin Attribute. The Data field
1200 contains the unrecognized attribute (type, length and value). */
1201 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1202 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1203 zlog_err("Origin attribute value is invalid %d", attr
->origin
);
1204 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1208 /* Set oring attribute flag. */
1209 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1214 /* Parse AS path information. This function is wrapper of
1216 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1218 struct attr
*const attr
= args
->attr
;
1219 struct peer
*const peer
= args
->peer
;
1220 const bgp_size_t length
= args
->length
;
1223 * peer with AS4 => will get 4Byte ASnums
1224 * otherwise, will get 16 Bit
1226 attr
->aspath
= aspath_parse(peer
->ibuf
, length
,
1227 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1229 /* In case of IBGP, length will be zero. */
1230 if (!attr
->aspath
) {
1231 zlog_err("Malformed AS path from %s, length is %d", peer
->host
,
1233 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1237 /* Set aspath attribute flag. */
1238 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1240 return BGP_ATTR_PARSE_PROCEED
;
1243 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1244 struct attr
*const attr
)
1246 /* These checks were part of bgp_attr_aspath, but with
1247 * as4 we should to check aspath things when
1248 * aspath synthesizing with as4_path has already taken place.
1249 * Otherwise we check ASPATH and use the synthesized thing, and that is
1251 * So do the checks later, i.e. here
1253 struct bgp
*bgp
= peer
->bgp
;
1254 struct aspath
*aspath
;
1256 /* Confederation sanity check. */
1257 if ((peer
->sort
== BGP_PEER_CONFED
1258 && !aspath_left_confed_check(attr
->aspath
))
1259 || (peer
->sort
== BGP_PEER_EBGP
1260 && aspath_confed_check(attr
->aspath
))) {
1261 zlog_err("Malformed AS path from %s", peer
->host
);
1262 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1263 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1264 return BGP_ATTR_PARSE_ERROR
;
1267 /* First AS check for EBGP. */
1268 if (bgp
!= NULL
&& bgp_flag_check(bgp
, BGP_FLAG_ENFORCE_FIRST_AS
)) {
1269 if (peer
->sort
== BGP_PEER_EBGP
1270 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1271 zlog_err("%s incorrect first AS (must be %u)",
1272 peer
->host
, peer
->as
);
1273 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1274 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1275 return BGP_ATTR_PARSE_ERROR
;
1279 /* local-as prepend */
1280 if (peer
->change_local_as
1281 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1282 aspath
= aspath_dup(attr
->aspath
);
1283 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1284 aspath_unintern(&attr
->aspath
);
1285 attr
->aspath
= aspath_intern(aspath
);
1288 return BGP_ATTR_PARSE_PROCEED
;
1291 /* Parse AS4 path information. This function is another wrapper of
1293 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1294 struct aspath
**as4_path
)
1296 struct peer
*const peer
= args
->peer
;
1297 struct attr
*const attr
= args
->attr
;
1298 const bgp_size_t length
= args
->length
;
1300 *as4_path
= aspath_parse(peer
->ibuf
, length
, 1);
1302 /* In case of IBGP, length will be zero. */
1304 zlog_err("Malformed AS4 path from %s, length is %d", peer
->host
,
1306 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1310 /* Set aspath attribute flag. */
1311 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1313 return BGP_ATTR_PARSE_PROCEED
;
1316 /* Nexthop attribute. */
1317 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1319 struct peer
*const peer
= args
->peer
;
1320 struct attr
*const attr
= args
->attr
;
1321 const bgp_size_t length
= args
->length
;
1323 in_addr_t nexthop_h
, nexthop_n
;
1325 /* Check nexthop attribute length. */
1327 zlog_err("Nexthop attribute length isn't four [%d]", length
);
1329 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1333 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1334 attribute must result in a NOTIFICATION message (this is implemented
1336 At the same time, semantically incorrect NEXT_HOP is more likely to
1338 logged locally (this is implemented somewhere else). The UPDATE
1340 gets ignored in any of these cases. */
1341 nexthop_n
= stream_get_ipv4(peer
->ibuf
);
1342 nexthop_h
= ntohl(nexthop_n
);
1343 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1344 || IPV4_CLASS_DE(nexthop_h
))
1347 ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1349 char buf
[INET_ADDRSTRLEN
];
1350 inet_ntop(AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1351 zlog_err("Martian nexthop %s", buf
);
1352 return bgp_attr_malformed(
1353 args
, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
, args
->total
);
1356 attr
->nexthop
.s_addr
= nexthop_n
;
1357 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1359 return BGP_ATTR_PARSE_PROCEED
;
1362 /* MED atrribute. */
1363 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1365 struct peer
*const peer
= args
->peer
;
1366 struct attr
*const attr
= args
->attr
;
1367 const bgp_size_t length
= args
->length
;
1371 zlog_err("MED attribute length isn't four [%d]", length
);
1373 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1377 attr
->med
= stream_getl(peer
->ibuf
);
1379 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1381 return BGP_ATTR_PARSE_PROCEED
;
1384 /* Local preference attribute. */
1385 static bgp_attr_parse_ret_t
1386 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1388 struct peer
*const peer
= args
->peer
;
1389 struct attr
*const attr
= args
->attr
;
1390 const bgp_size_t length
= args
->length
;
1394 zlog_err("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1395 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1399 /* If it is contained in an UPDATE message that is received from an
1400 external peer, then this attribute MUST be ignored by the
1401 receiving speaker. */
1402 if (peer
->sort
== BGP_PEER_EBGP
) {
1403 stream_forward_getp(peer
->ibuf
, length
);
1404 return BGP_ATTR_PARSE_PROCEED
;
1407 attr
->local_pref
= stream_getl(peer
->ibuf
);
1409 /* Set atomic aggregate flag. */
1410 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1412 return BGP_ATTR_PARSE_PROCEED
;
1415 /* Atomic aggregate. */
1416 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1418 struct attr
*const attr
= args
->attr
;
1419 const bgp_size_t length
= args
->length
;
1423 zlog_err("ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1425 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1429 /* Set atomic aggregate flag. */
1430 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1432 return BGP_ATTR_PARSE_PROCEED
;
1435 /* Aggregator attribute */
1436 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1438 struct peer
*const peer
= args
->peer
;
1439 struct attr
*const attr
= args
->attr
;
1440 const bgp_size_t length
= args
->length
;
1444 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1445 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1448 if (length
!= wantedlen
) {
1449 zlog_err("AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1451 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1455 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1456 attr
->aggregator_as
= stream_getl(peer
->ibuf
);
1458 attr
->aggregator_as
= stream_getw(peer
->ibuf
);
1459 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->ibuf
);
1461 /* Set atomic aggregate flag. */
1462 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1464 return BGP_ATTR_PARSE_PROCEED
;
1467 /* New Aggregator attribute */
1468 static bgp_attr_parse_ret_t
1469 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1470 as_t
*as4_aggregator_as
,
1471 struct in_addr
*as4_aggregator_addr
)
1473 struct peer
*const peer
= args
->peer
;
1474 struct attr
*const attr
= args
->attr
;
1475 const bgp_size_t length
= args
->length
;
1478 zlog_err("New Aggregator length is not 8 [%d]", length
);
1479 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1483 *as4_aggregator_as
= stream_getl(peer
->ibuf
);
1484 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->ibuf
);
1486 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1488 return BGP_ATTR_PARSE_PROCEED
;
1491 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1493 static bgp_attr_parse_ret_t
1494 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1495 struct aspath
*as4_path
, as_t as4_aggregator
,
1496 struct in_addr
*as4_aggregator_addr
)
1498 int ignore_as4_path
= 0;
1499 struct aspath
*newpath
;
1501 if (!attr
->aspath
) {
1502 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1504 * checked that all well-known, mandatory attributes were
1507 * Can only be a problem with peer itself - hard error
1509 return BGP_ATTR_PARSE_ERROR
;
1512 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1513 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1515 * It is worth a warning though, because the peer really
1516 * should not send them
1518 if (BGP_DEBUG(as4
, AS4
)) {
1519 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1520 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1521 "AS4 capable peer, yet it sent");
1524 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1525 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1527 "AS4 capable peer, yet it sent");
1530 return BGP_ATTR_PARSE_PROCEED
;
1533 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1534 * because that may override AS4_PATH
1536 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1537 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1539 * if the as_number in aggregator is not AS_TRANS,
1540 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1541 * and the Aggregator shall be taken as
1542 * info on the aggregating node, and the AS_PATH
1543 * shall be taken as the AS_PATH
1545 * the Aggregator shall be ignored and the
1546 * AS4_AGGREGATOR shall be taken as the
1547 * Aggregating node and the AS_PATH is to be
1548 * constructed "as in all other cases"
1550 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1552 if (BGP_DEBUG(as4
, AS4
))
1554 "[AS4] %s BGP not AS4 capable peer"
1555 " send AGGREGATOR != AS_TRANS and"
1556 " AS4_AGGREGATOR, so ignore"
1557 " AS4_AGGREGATOR and AS4_PATH",
1559 ignore_as4_path
= 1;
1561 /* "New_aggregator shall be taken as aggregator"
1563 attr
->aggregator_as
= as4_aggregator
;
1564 attr
->aggregator_addr
.s_addr
=
1565 as4_aggregator_addr
->s_addr
;
1568 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1569 * That is bogus - but reading the conditions
1570 * we have to handle AS4_AGGREGATOR as if it were
1571 * AGGREGATOR in that case
1573 if (BGP_DEBUG(as4
, AS4
))
1575 "[AS4] %s BGP not AS4 capable peer send"
1576 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1577 " it as if AGGREGATOR with AS_TRANS had been there",
1579 attr
->aggregator_as
= as4_aggregator
;
1580 /* sweep it under the carpet and simulate a "good"
1582 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1586 /* need to reconcile NEW_AS_PATH and AS_PATH */
1587 if (!ignore_as4_path
1588 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1589 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1590 aspath_unintern(&attr
->aspath
);
1591 attr
->aspath
= aspath_intern(newpath
);
1593 return BGP_ATTR_PARSE_PROCEED
;
1596 /* Community attribute. */
1597 static bgp_attr_parse_ret_t
1598 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1600 struct peer
*const peer
= args
->peer
;
1601 struct attr
*const attr
= args
->attr
;
1602 const bgp_size_t length
= args
->length
;
1605 attr
->community
= NULL
;
1606 return BGP_ATTR_PARSE_PROCEED
;
1610 community_parse((u_int32_t
*)stream_pnt(peer
->ibuf
), length
);
1612 /* XXX: fix community_parse to use stream API and remove this */
1613 stream_forward_getp(peer
->ibuf
, length
);
1615 if (!attr
->community
)
1616 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1619 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1621 return BGP_ATTR_PARSE_PROCEED
;
1624 /* Originator ID attribute. */
1625 static bgp_attr_parse_ret_t
1626 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1628 struct peer
*const peer
= args
->peer
;
1629 struct attr
*const attr
= args
->attr
;
1630 const bgp_size_t length
= args
->length
;
1634 zlog_err("Bad originator ID length %d", length
);
1636 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1640 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->ibuf
);
1642 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1644 return BGP_ATTR_PARSE_PROCEED
;
1647 /* Cluster list attribute. */
1648 static bgp_attr_parse_ret_t
1649 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1651 struct peer
*const peer
= args
->peer
;
1652 struct attr
*const attr
= args
->attr
;
1653 const bgp_size_t length
= args
->length
;
1657 zlog_err("Bad cluster list length %d", length
);
1659 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1664 cluster_parse((struct in_addr
*)stream_pnt(peer
->ibuf
), length
);
1666 /* XXX: Fix cluster_parse to use stream API and then remove this */
1667 stream_forward_getp(peer
->ibuf
, length
);
1669 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1671 return BGP_ATTR_PARSE_PROCEED
;
1674 /* Multiprotocol reachability information parse. */
1675 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1676 struct bgp_nlri
*mp_update
)
1680 safi_t pkt_safi
, safi
;
1681 bgp_size_t nlri_len
;
1684 struct peer
*const peer
= args
->peer
;
1685 struct attr
*const attr
= args
->attr
;
1686 const bgp_size_t length
= args
->length
;
1688 /* Set end of packet. */
1689 s
= BGP_INPUT(peer
);
1690 start
= stream_get_getp(s
);
1692 /* safe to read statically sized header? */
1693 #define BGP_MP_REACH_MIN_SIZE 5
1694 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1695 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1696 zlog_info("%s: %s sent invalid length, %lu", __func__
,
1697 peer
->host
, (unsigned long)length
);
1698 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1701 /* Load AFI, SAFI. */
1702 pkt_afi
= stream_getw(s
);
1703 pkt_safi
= stream_getc(s
);
1705 /* Convert AFI, SAFI to internal values, check. */
1706 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1707 /* Log if AFI or SAFI is unrecognized. This is not an error
1709 * the attribute is otherwise malformed.
1711 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1713 "%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1714 peer
->host
, pkt_afi
, pkt_safi
);
1715 return BGP_ATTR_PARSE_ERROR
;
1718 /* Get nexthop length. */
1719 attr
->mp_nexthop_len
= stream_getc(s
);
1721 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1723 "%s: %s, MP nexthop length, %u, goes past end of attribute",
1724 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1725 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1728 /* Nexthop length check. */
1729 switch (attr
->mp_nexthop_len
) {
1730 case BGP_ATTR_NHLEN_IPV4
:
1731 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1732 /* Probably needed for RFC 2283 */
1733 if (attr
->nexthop
.s_addr
== 0)
1734 memcpy(&attr
->nexthop
.s_addr
,
1735 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1737 case BGP_ATTR_NHLEN_VPNV4
:
1738 stream_getl(s
); /* RD high */
1739 stream_getl(s
); /* RD low */
1740 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1742 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1743 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1744 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1745 stream_getl(s
); /* RD high */
1746 stream_getl(s
); /* RD low */
1748 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1750 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1751 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1752 if (attr
->mp_nexthop_len
1753 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1754 stream_getl(s
); /* RD high */
1755 stream_getl(s
); /* RD low */
1757 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1758 if (attr
->mp_nexthop_len
1759 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1760 stream_getl(s
); /* RD high */
1761 stream_getl(s
); /* RD low */
1763 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1764 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1765 char buf1
[INET6_ADDRSTRLEN
];
1766 char buf2
[INET6_ADDRSTRLEN
];
1768 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1770 "%s rcvd nexthops %s, %s -- ignoring non-LL value",
1773 &attr
->mp_nexthop_global
,
1774 buf1
, INET6_ADDRSTRLEN
),
1776 &attr
->mp_nexthop_local
, buf2
,
1779 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1783 zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
1784 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1785 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1789 zlog_info("%s: (%s) Failed to read SNPA and NLRI(s)", __func__
,
1791 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1796 if ((val
= stream_getc(s
)))
1798 "%s sent non-zero value, %u, for defunct SNPA-length field",
1802 /* must have nrli_len, what is left of the attribute */
1803 nlri_len
= LEN_LEFT
;
1804 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
))) {
1805 zlog_info("%s: (%s) Failed to read NLRI", __func__
, peer
->host
);
1806 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1809 mp_update
->afi
= afi
;
1810 mp_update
->safi
= safi
;
1811 mp_update
->nlri
= stream_pnt(s
);
1812 mp_update
->length
= nlri_len
;
1814 stream_forward_getp(s
, nlri_len
);
1816 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
1818 return BGP_ATTR_PARSE_PROCEED
;
1822 /* Multiprotocol unreachable parse */
1823 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
1824 struct bgp_nlri
*mp_withdraw
)
1829 safi_t pkt_safi
, safi
;
1830 u_int16_t withdraw_len
;
1831 struct peer
*const peer
= args
->peer
;
1832 struct attr
*const attr
= args
->attr
;
1833 const bgp_size_t length
= args
->length
;
1837 #define BGP_MP_UNREACH_MIN_SIZE 3
1838 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1839 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1841 pkt_afi
= stream_getw(s
);
1842 pkt_safi
= stream_getc(s
);
1844 /* Convert AFI, SAFI to internal values, check. */
1845 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1846 /* Log if AFI or SAFI is unrecognized. This is not an error
1848 * the attribute is otherwise malformed.
1850 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1852 "%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
1853 peer
->host
, pkt_afi
, pkt_safi
);
1854 return BGP_ATTR_PARSE_ERROR
;
1857 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1859 mp_withdraw
->afi
= afi
;
1860 mp_withdraw
->safi
= safi
;
1861 mp_withdraw
->nlri
= stream_pnt(s
);
1862 mp_withdraw
->length
= withdraw_len
;
1864 stream_forward_getp(s
, withdraw_len
);
1866 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
1868 return BGP_ATTR_PARSE_PROCEED
;
1871 /* Large Community attribute. */
1872 static bgp_attr_parse_ret_t
1873 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
1875 struct peer
*const peer
= args
->peer
;
1876 struct attr
*const attr
= args
->attr
;
1877 const bgp_size_t length
= args
->length
;
1880 * Large community follows new attribute format.
1883 attr
->lcommunity
= NULL
;
1884 /* Empty extcomm doesn't seem to be invalid per se */
1885 return BGP_ATTR_PARSE_PROCEED
;
1889 lcommunity_parse((u_int8_t
*)stream_pnt(peer
->ibuf
), length
);
1890 /* XXX: fix ecommunity_parse to use stream API */
1891 stream_forward_getp(peer
->ibuf
, length
);
1893 if (!attr
->lcommunity
)
1894 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1897 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1899 return BGP_ATTR_PARSE_PROCEED
;
1902 /* Extended Community attribute. */
1903 static bgp_attr_parse_ret_t
1904 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
1906 struct peer
*const peer
= args
->peer
;
1907 struct attr
*const attr
= args
->attr
;
1908 const bgp_size_t length
= args
->length
;
1912 attr
->ecommunity
= NULL
;
1913 /* Empty extcomm doesn't seem to be invalid per se */
1914 return BGP_ATTR_PARSE_PROCEED
;
1918 ecommunity_parse((u_int8_t
*)stream_pnt(peer
->ibuf
), length
);
1919 /* XXX: fix ecommunity_parse to use stream API */
1920 stream_forward_getp(peer
->ibuf
, length
);
1922 if (!attr
->ecommunity
)
1923 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1926 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1928 /* Extract MAC mobility sequence number, if any. */
1929 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
1930 attr
->sticky
= sticky
;
1932 return BGP_ATTR_PARSE_PROCEED
;
1935 /* Parse Tunnel Encap attribute in an UPDATE */
1936 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
1937 bgp_size_t length
, /* IN: attr's length field */
1938 struct attr
*attr
, /* IN: caller already allocated */
1939 u_char flag
, /* IN: attr's flags field */
1943 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
1944 uint16_t tunneltype
= 0;
1946 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
1948 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
1949 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
1951 "Tunnel Encap attribute flag isn't optional and transitive %d",
1953 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1954 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
1959 if (BGP_ATTR_ENCAP
== type
) {
1960 /* read outer TLV type and length */
1961 uint16_t tlv_length
;
1965 "Tunnel Encap attribute not long enough to contain outer T,L");
1966 bgp_notify_send_with_data(
1967 peer
, BGP_NOTIFY_UPDATE_ERR
,
1968 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
1971 tunneltype
= stream_getw(BGP_INPUT(peer
));
1972 tlv_length
= stream_getw(BGP_INPUT(peer
));
1975 if (tlv_length
!= length
) {
1976 zlog_info("%s: tlv_length(%d) != length(%d)", __func__
,
1977 tlv_length
, length
);
1981 while (length
>= 4) {
1982 uint16_t subtype
= 0;
1983 uint16_t sublength
= 0;
1984 struct bgp_attr_encap_subtlv
*tlv
;
1986 if (BGP_ATTR_ENCAP
== type
) {
1987 subtype
= stream_getc(BGP_INPUT(peer
));
1988 sublength
= stream_getc(BGP_INPUT(peer
));
1992 subtype
= stream_getw(BGP_INPUT(peer
));
1993 sublength
= stream_getw(BGP_INPUT(peer
));
1998 if (sublength
> length
) {
2000 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2002 bgp_notify_send_with_data(
2003 peer
, BGP_NOTIFY_UPDATE_ERR
,
2004 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2008 /* alloc and copy sub-tlv */
2009 /* TBD make sure these are freed when attributes are released */
2010 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2011 sizeof(struct bgp_attr_encap_subtlv
) - 1
2013 tlv
->type
= subtype
;
2014 tlv
->length
= sublength
;
2015 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2016 length
-= sublength
;
2018 /* attach tlv to encap chain */
2019 if (BGP_ATTR_ENCAP
== type
) {
2020 for (stlv_last
= attr
->encap_subtlvs
;
2021 stlv_last
&& stlv_last
->next
;
2022 stlv_last
= stlv_last
->next
)
2025 stlv_last
->next
= tlv
;
2027 attr
->encap_subtlvs
= tlv
;
2031 for (stlv_last
= attr
->vnc_subtlvs
;
2032 stlv_last
&& stlv_last
->next
;
2033 stlv_last
= stlv_last
->next
)
2036 stlv_last
->next
= tlv
;
2038 attr
->vnc_subtlvs
= tlv
;
2042 stlv_last
->next
= tlv
;
2045 if (BGP_ATTR_ENCAP
== type
) {
2046 attr
->encap_tunneltype
= tunneltype
;
2050 /* spurious leftover data */
2052 "Tunnel Encap attribute length is bad: %d leftover octets",
2054 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2055 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2063 /* Prefix SID attribute
2064 * draft-ietf-idr-bgp-prefix-sid-05
2066 static bgp_attr_parse_ret_t
2067 bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
,
2068 struct bgp_nlri
*mp_update
)
2070 struct peer
*const peer
= args
->peer
;
2071 struct attr
*const attr
= args
->attr
;
2074 u_int32_t label_index
;
2075 struct in6_addr ipv6_sid
;
2076 u_int32_t srgb_base
;
2077 u_int32_t srgb_range
;
2080 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2082 type
= stream_getc(peer
->ibuf
);
2083 length
= stream_getw(peer
->ibuf
);
2085 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2086 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2088 "Prefix SID label index length is %d instead of %d",
2089 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2090 return bgp_attr_malformed(
2091 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2095 /* Ignore flags and reserved */
2096 stream_getc(peer
->ibuf
);
2097 stream_getw(peer
->ibuf
);
2099 /* Fetch the label index and see if it is valid. */
2100 label_index
= stream_getl(peer
->ibuf
);
2101 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2102 return bgp_attr_malformed(
2103 args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2106 /* Store label index; subsequently, we'll check on
2108 attr
->label_index
= label_index
;
2111 * Ignore the Label index attribute unless received for
2115 if (!mp_update
->length
2116 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2117 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2120 /* Placeholder code for the IPv6 SID type */
2121 else if (type
== BGP_PREFIX_SID_IPV6
) {
2122 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2123 zlog_err("Prefix SID IPv6 length is %d instead of %d",
2124 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2125 return bgp_attr_malformed(
2126 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2130 /* Ignore reserved */
2131 stream_getc(peer
->ibuf
);
2132 stream_getw(peer
->ibuf
);
2134 stream_get(&ipv6_sid
, peer
->ibuf
, 16);
2137 /* Placeholder code for the Originator SRGB type */
2138 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2140 stream_getw(peer
->ibuf
);
2144 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2146 "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2147 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2148 return bgp_attr_malformed(
2149 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2153 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2155 for (int i
= 0; i
< srgb_count
; i
++) {
2156 stream_get(&srgb_base
, peer
->ibuf
, 3);
2157 stream_get(&srgb_range
, peer
->ibuf
, 3);
2161 return BGP_ATTR_PARSE_PROCEED
;
2164 /* BGP unknown attribute treatment. */
2165 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2167 bgp_size_t total
= args
->total
;
2168 struct transit
*transit
;
2169 struct peer
*const peer
= args
->peer
;
2170 struct attr
*const attr
= args
->attr
;
2171 u_char
*const startp
= args
->startp
;
2172 const u_char type
= args
->type
;
2173 const u_char flag
= args
->flags
;
2174 const bgp_size_t length
= args
->length
;
2176 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2178 "%s Unknown attribute is received (type %d, length %d)",
2179 peer
->host
, type
, length
);
2181 /* Forward read pointer of input stream. */
2182 stream_forward_getp(peer
->ibuf
, length
);
2184 /* If any of the mandatory well-known attributes are not recognized,
2185 then the Error Subcode is set to Unrecognized Well-known
2186 Attribute. The Data field contains the unrecognized attribute
2187 (type, length and value). */
2188 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2189 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2193 /* Unrecognized non-transitive optional attributes must be quietly
2194 ignored and not passed along to other BGP peers. */
2195 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2196 return BGP_ATTR_PARSE_PROCEED
;
2198 /* If a path with recognized transitive optional attribute is
2199 accepted and passed along to other BGP peers and the Partial bit
2200 in the Attribute Flags octet is set to 1 by some previous AS, it
2201 is not set back to 0 by the current AS. */
2202 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2204 /* Store transitive attribute to the end of attr->transit. */
2206 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2208 transit
= attr
->transit
;
2211 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2212 transit
->length
+ total
);
2214 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2216 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2217 transit
->length
+= total
;
2219 return BGP_ATTR_PARSE_PROCEED
;
2222 /* Well-known attribute check. */
2223 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2227 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2229 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2230 return BGP_ATTR_PARSE_PROCEED
;
2232 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2233 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2234 are present, it should. Check for any other attribute being present
2237 if (attr
->flag
== ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))
2238 return BGP_ATTR_PARSE_PROCEED
;
2240 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2241 type
= BGP_ATTR_ORIGIN
;
2243 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2244 type
= BGP_ATTR_AS_PATH
;
2246 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2248 * NLRI is empty. We can't easily check NLRI empty here though.
2250 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2251 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2252 type
= BGP_ATTR_NEXT_HOP
;
2254 if (peer
->sort
== BGP_PEER_IBGP
2255 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2256 type
= BGP_ATTR_LOCAL_PREF
;
2259 zlog_warn("%s Missing well-known attribute %s.", peer
->host
,
2260 lookup_msg(attr_str
, type
, NULL
));
2261 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2262 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2264 return BGP_ATTR_PARSE_ERROR
;
2266 return BGP_ATTR_PARSE_PROCEED
;
2269 /* Read attribute of update packet. This function is called from
2270 bgp_update_receive() in bgp_packet.c. */
2271 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2272 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2273 struct bgp_nlri
*mp_withdraw
)
2279 u_char
*startp
, *endp
;
2281 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2282 /* we need the as4_path only until we have synthesized the as_path with
2284 /* same goes for as4_aggregator */
2285 struct aspath
*as4_path
= NULL
;
2286 as_t as4_aggregator
= 0;
2287 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2289 /* Initialize bitmap. */
2290 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2292 /* End pointer of BGP attribute. */
2293 endp
= BGP_INPUT_PNT(peer
) + size
;
2295 /* Get attributes to the end of attribute length. */
2296 while (BGP_INPUT_PNT(peer
) < endp
) {
2297 /* Check remaining length check.*/
2298 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2299 /* XXX warning: long int format, int arg (arg 5) */
2301 "%s: error BGP attribute length %lu is smaller than min len",
2303 (unsigned long)(endp
2304 - STREAM_PNT(BGP_INPUT(peer
))));
2306 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2307 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2308 return BGP_ATTR_PARSE_ERROR
;
2311 /* Fetch attribute flag and type. */
2312 startp
= BGP_INPUT_PNT(peer
);
2313 /* "The lower-order four bits of the Attribute Flags octet are
2314 unused. They MUST be zero when sent and MUST be ignored when
2316 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2317 type
= stream_getc(BGP_INPUT(peer
));
2319 /* Check whether Extended-Length applies and is in bounds */
2320 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2321 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2323 "%s: Extended length set, but just %lu bytes of attr header",
2325 (unsigned long)(endp
2326 - STREAM_PNT(BGP_INPUT(peer
))));
2328 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2329 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2330 return BGP_ATTR_PARSE_ERROR
;
2333 /* Check extended attribue length bit. */
2334 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2335 length
= stream_getw(BGP_INPUT(peer
));
2337 length
= stream_getc(BGP_INPUT(peer
));
2339 /* If any attribute appears more than once in the UPDATE
2340 message, then the Error Subcode is set to Malformed Attribute
2343 if (CHECK_BITMAP(seen
, type
)) {
2345 "%s: error BGP attribute type %d appears twice in a message",
2348 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2349 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2350 return BGP_ATTR_PARSE_ERROR
;
2353 /* Set type to bitmap to check duplicate attribute. `type' is
2354 unsigned char so it never overflow bitmap range. */
2356 SET_BITMAP(seen
, type
);
2358 /* Overflow check. */
2359 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2361 if (attr_endp
> endp
) {
2363 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2364 peer
->host
, type
, length
, size
, attr_endp
,
2366 bgp_notify_send_with_data(
2367 peer
, BGP_NOTIFY_UPDATE_ERR
,
2368 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, startp
,
2369 attr_endp
- startp
);
2370 return BGP_ATTR_PARSE_ERROR
;
2373 struct bgp_attr_parser_args attr_args
= {
2380 .total
= attr_endp
- startp
,
2384 /* If any recognized attribute has Attribute Flags that conflict
2385 with the Attribute Type Code, then the Error Subcode is set
2387 Attribute Flags Error. The Data field contains the erroneous
2388 attribute (type, length and value). */
2389 if (bgp_attr_flag_invalid(&attr_args
)) {
2390 bgp_attr_parse_ret_t ret
;
2391 ret
= bgp_attr_malformed(
2392 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2394 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2399 /* OK check attribute and store it's value. */
2401 case BGP_ATTR_ORIGIN
:
2402 ret
= bgp_attr_origin(&attr_args
);
2404 case BGP_ATTR_AS_PATH
:
2405 ret
= bgp_attr_aspath(&attr_args
);
2407 case BGP_ATTR_AS4_PATH
:
2408 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2410 case BGP_ATTR_NEXT_HOP
:
2411 ret
= bgp_attr_nexthop(&attr_args
);
2413 case BGP_ATTR_MULTI_EXIT_DISC
:
2414 ret
= bgp_attr_med(&attr_args
);
2416 case BGP_ATTR_LOCAL_PREF
:
2417 ret
= bgp_attr_local_pref(&attr_args
);
2419 case BGP_ATTR_ATOMIC_AGGREGATE
:
2420 ret
= bgp_attr_atomic(&attr_args
);
2422 case BGP_ATTR_AGGREGATOR
:
2423 ret
= bgp_attr_aggregator(&attr_args
);
2425 case BGP_ATTR_AS4_AGGREGATOR
:
2426 ret
= bgp_attr_as4_aggregator(&attr_args
,
2428 &as4_aggregator_addr
);
2430 case BGP_ATTR_COMMUNITIES
:
2431 ret
= bgp_attr_community(&attr_args
);
2433 case BGP_ATTR_LARGE_COMMUNITIES
:
2434 ret
= bgp_attr_large_community(&attr_args
);
2436 case BGP_ATTR_ORIGINATOR_ID
:
2437 ret
= bgp_attr_originator_id(&attr_args
);
2439 case BGP_ATTR_CLUSTER_LIST
:
2440 ret
= bgp_attr_cluster_list(&attr_args
);
2442 case BGP_ATTR_MP_REACH_NLRI
:
2443 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2445 case BGP_ATTR_MP_UNREACH_NLRI
:
2446 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2448 case BGP_ATTR_EXT_COMMUNITIES
:
2449 ret
= bgp_attr_ext_communities(&attr_args
);
2454 case BGP_ATTR_ENCAP
:
2455 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
2458 case BGP_ATTR_PREFIX_SID
:
2459 ret
= bgp_attr_prefix_sid(&attr_args
, mp_update
);
2462 ret
= bgp_attr_unknown(&attr_args
);
2466 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
2467 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2468 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2469 ret
= BGP_ATTR_PARSE_ERROR
;
2472 /* If hard error occured immediately return to the caller. */
2473 if (ret
== BGP_ATTR_PARSE_ERROR
) {
2474 zlog_warn("%s: Attribute %s, parse error", peer
->host
,
2475 lookup_msg(attr_str
, type
, NULL
));
2477 aspath_unintern(&as4_path
);
2480 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
2483 "%s: Attribute %s, parse error - treating as withdrawal",
2484 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2486 aspath_unintern(&as4_path
);
2490 /* Check the fetched length. */
2491 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
2492 zlog_warn("%s: BGP attribute %s, fetch error",
2493 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2494 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2495 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2497 aspath_unintern(&as4_path
);
2498 return BGP_ATTR_PARSE_ERROR
;
2502 /* Check final read pointer is same as end pointer. */
2503 if (BGP_INPUT_PNT(peer
) != endp
) {
2504 zlog_warn("%s: BGP attribute %s, length mismatch", peer
->host
,
2505 lookup_msg(attr_str
, type
, NULL
));
2506 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2507 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2509 aspath_unintern(&as4_path
);
2510 return BGP_ATTR_PARSE_ERROR
;
2513 /* Check all mandatory well-known attributes are present */
2515 bgp_attr_parse_ret_t ret
;
2516 if ((ret
= bgp_attr_check(peer
, attr
)) < 0) {
2518 aspath_unintern(&as4_path
);
2524 * At this place we can see whether we got AS4_PATH and/or
2525 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2526 * We can not do this before we've read all attributes because
2527 * the as4 handling does not say whether AS4_PATH has to be sent
2528 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2529 * in relationship to AGGREGATOR.
2530 * So, to be defensive, we are not relying on any order and read
2531 * all attributes first, including these 32bit ones, and now,
2532 * afterwards, we look what and if something is to be done for as4.
2534 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2537 /* actually... this doesn't ever return failure currently, but
2538 * better safe than sorry */
2539 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
2540 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
2541 &as4_aggregator_addr
)) {
2542 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2543 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2545 aspath_unintern(&as4_path
);
2546 return BGP_ATTR_PARSE_ERROR
;
2549 /* At this stage, we have done all fiddling with as4, and the
2550 * resulting info is in attr->aggregator resp. attr->aspath
2551 * so we can chuck as4_aggregator and as4_path alltogether in
2552 * order to save memory
2555 aspath_unintern(&as4_path
); /* unintern - it is in the hash */
2556 /* The flag that we got this is still there, but that does not
2561 * The "rest" of the code does nothing with as4_aggregator.
2562 * there is no memory attached specifically which is not part
2564 * so ignoring just means do nothing.
2567 * Finally do the checks on the aspath we did not do yet
2568 * because we waited for a potentially synthesized aspath.
2570 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
2571 ret
= bgp_attr_aspath_check(peer
, attr
);
2572 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2575 /* Finally intern unknown attribute. */
2577 attr
->transit
= transit_intern(attr
->transit
);
2578 if (attr
->encap_subtlvs
)
2579 attr
->encap_subtlvs
=
2580 encap_intern(attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2582 if (attr
->vnc_subtlvs
)
2584 encap_intern(attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2587 return BGP_ATTR_PARSE_PROCEED
;
2590 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
2591 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
2599 /* Set extended bit always to encode the attribute length as 2 bytes */
2600 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
2601 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2602 sizep
= stream_get_endp(s
);
2603 stream_putw(s
, 0); /* Marker: Attribute length. */
2606 /* Convert AFI, SAFI to values for packet. */
2607 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
2609 stream_putw(s
, pkt_afi
); /* AFI */
2610 stream_putc(s
, pkt_safi
); /* SAFI */
2613 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
2614 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
2615 } else if (safi
== SAFI_LABELED_UNICAST
)
2618 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
2621 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2626 case SAFI_MULTICAST
:
2627 case SAFI_LABELED_UNICAST
:
2629 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2633 stream_putl(s
, 0); /* RD = 0, per RFC */
2635 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2640 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2649 case SAFI_MULTICAST
:
2650 case SAFI_LABELED_UNICAST
:
2652 if (attr
->mp_nexthop_len
2653 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2655 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2656 stream_put(s
, &attr
->mp_nexthop_global
,
2658 stream_put(s
, &attr
->mp_nexthop_local
,
2661 stream_putc(s
, IPV6_MAX_BYTELEN
);
2662 stream_put(s
, &attr
->mp_nexthop_global
,
2666 case SAFI_MPLS_VPN
: {
2667 if (attr
->mp_nexthop_len
2668 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2670 stream_putl(s
, 0); /* RD = 0, per RFC */
2672 stream_put(s
, &attr
->mp_nexthop_global
,
2674 } else if (attr
->mp_nexthop_len
2675 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2677 stream_putl(s
, 0); /* RD = 0, per RFC */
2679 stream_put(s
, &attr
->mp_nexthop_global
,
2681 stream_putl(s
, 0); /* RD = 0, per RFC */
2683 stream_put(s
, &attr
->mp_nexthop_local
,
2688 stream_putc(s
, IPV6_MAX_BYTELEN
);
2689 stream_put(s
, &attr
->mp_nexthop_global
,
2698 "Bad nexthop when sening to %s, AFI %u SAFI %u nhlen %d",
2699 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
2708 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
2709 struct prefix
*p
, struct prefix_rd
*prd
,
2710 mpls_label_t
*label
, int addpath_encode
,
2711 u_int32_t addpath_tx_id
, struct attr
*attr
)
2713 if (safi
== SAFI_MPLS_VPN
) {
2715 stream_putl(s
, addpath_tx_id
);
2716 /* Label, RD, Prefix write. */
2717 stream_putc(s
, p
->prefixlen
+ 88);
2718 stream_put(s
, label
, BGP_LABEL_BYTES
);
2719 stream_put(s
, prd
->val
, 8);
2720 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
2721 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
2722 /* EVPN prefix - contents depend on type */
2723 bgp_evpn_encode_prefix(s
, p
, prd
, label
, attr
, addpath_encode
,
2725 } else if (safi
== SAFI_LABELED_UNICAST
) {
2726 /* Prefix write with label. */
2727 stream_put_labeled_prefix(s
, p
, label
);
2729 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
2732 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
2734 int size
= PSIZE(p
->prefixlen
);
2735 if (safi
== SAFI_MPLS_VPN
)
2737 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2738 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
2744 * Encodes the tunnel encapsulation attribute,
2745 * and with ENABLE_BGP_VNC the VNC attribute which uses
2746 * almost the same TLV format
2748 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
2749 struct stream
*s
, struct attr
*attr
,
2752 unsigned int attrlenfield
= 0;
2753 unsigned int attrhdrlen
= 0;
2754 struct bgp_attr_encap_subtlv
*subtlvs
;
2755 struct bgp_attr_encap_subtlv
*st
;
2756 const char *attrname
;
2758 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
2759 && (!attr
->encap_tunneltype
2760 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
2764 case BGP_ATTR_ENCAP
:
2765 attrname
= "Tunnel Encap";
2766 subtlvs
= attr
->encap_subtlvs
;
2767 if (subtlvs
== NULL
) /* nothing to do */
2770 * The tunnel encap attr has an "outer" tlv.
2772 * L = total length of subtlvs,
2773 * V = concatenated subtlvs.
2775 attrlenfield
= 2 + 2; /* T + L */
2776 attrhdrlen
= 1 + 1; /* subTLV T + L */
2782 subtlvs
= attr
->vnc_subtlvs
;
2783 if (subtlvs
== NULL
) /* nothing to do */
2785 attrlenfield
= 0; /* no outer T + L */
2786 attrhdrlen
= 2 + 2; /* subTLV T + L */
2794 /* compute attr length */
2795 for (st
= subtlvs
; st
; st
= st
->next
) {
2796 attrlenfield
+= (attrhdrlen
+ st
->length
);
2799 if (attrlenfield
> 0xffff) {
2800 zlog_info("%s attribute is too long (length=%d), can't send it",
2801 attrname
, attrlenfield
);
2805 if (attrlenfield
> 0xff) {
2806 /* 2-octet length field */
2808 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
2809 | BGP_ATTR_FLAG_EXTLEN
);
2810 stream_putc(s
, attrtype
);
2811 stream_putw(s
, attrlenfield
& 0xffff);
2813 /* 1-octet length field */
2814 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
2815 stream_putc(s
, attrtype
);
2816 stream_putc(s
, attrlenfield
& 0xff);
2819 if (attrtype
== BGP_ATTR_ENCAP
) {
2820 /* write outer T+L */
2821 stream_putw(s
, attr
->encap_tunneltype
);
2822 stream_putw(s
, attrlenfield
- 4);
2825 /* write each sub-tlv */
2826 for (st
= subtlvs
; st
; st
= st
->next
) {
2827 if (attrtype
== BGP_ATTR_ENCAP
) {
2828 stream_putc(s
, st
->type
);
2829 stream_putc(s
, st
->length
);
2832 stream_putw(s
, st
->type
);
2833 stream_putw(s
, st
->length
);
2836 stream_put(s
, st
->value
, st
->length
);
2840 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
2842 /* Set MP attribute length. Don't count the (2) bytes used to encode
2844 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
2847 /* Make attribute packet. */
2848 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
2849 struct stream
*s
, struct attr
*attr
,
2850 struct bpacket_attr_vec_arr
*vecarr
,
2851 struct prefix
*p
, afi_t afi
, safi_t safi
,
2852 struct peer
*from
, struct prefix_rd
*prd
,
2853 mpls_label_t
*label
, int addpath_encode
,
2854 u_int32_t addpath_tx_id
)
2857 size_t aspath_sizep
;
2858 struct aspath
*aspath
;
2859 int send_as4_path
= 0;
2860 int send_as4_aggregator
= 0;
2861 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2866 /* Remember current pointer. */
2867 cp
= stream_get_endp(s
);
2870 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
2871 && !peer_cap_enhe(peer
, afi
, safi
))) {
2872 size_t mpattrlen_pos
= 0;
2874 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
2876 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
2877 addpath_encode
, addpath_tx_id
, attr
);
2878 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2881 /* Origin attribute. */
2882 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
2883 stream_putc(s
, BGP_ATTR_ORIGIN
);
2885 stream_putc(s
, attr
->origin
);
2887 /* AS path attribute. */
2889 /* If remote-peer is EBGP */
2890 if (peer
->sort
== BGP_PEER_EBGP
2891 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2892 PEER_FLAG_AS_PATH_UNCHANGED
)
2893 || attr
->aspath
->segments
== NULL
)
2894 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2895 PEER_FLAG_RSERVER_CLIENT
))) {
2896 aspath
= aspath_dup(attr
->aspath
);
2898 /* Even though we may not be configured for confederations we
2900 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2901 aspath
= aspath_delete_confed_seq(aspath
);
2903 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2904 /* Stuff our path CONFED_ID on the front */
2905 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
2907 if (peer
->change_local_as
) {
2908 /* If replace-as is specified, we only use the
2909 change_local_as when
2910 advertising routes. */
2913 PEER_FLAG_LOCAL_AS_REPLACE_AS
)) {
2914 aspath
= aspath_add_seq(aspath
,
2917 aspath
= aspath_add_seq(aspath
,
2918 peer
->change_local_as
);
2920 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
2923 } else if (peer
->sort
== BGP_PEER_CONFED
) {
2924 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
2926 aspath
= aspath_dup(attr
->aspath
);
2927 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
2929 aspath
= attr
->aspath
;
2931 /* If peer is not AS4 capable, then:
2932 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2933 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
2935 * types are in it (i.e. exclude them if they are there)
2936 * AND do this only if there is at least one asnum > 65535 in the
2938 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
2940 * all ASnums > 65535 to BGP_AS_TRANS
2943 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
2944 stream_putc(s
, BGP_ATTR_AS_PATH
);
2945 aspath_sizep
= stream_get_endp(s
);
2947 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
2949 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2952 if (!use32bit
&& aspath_has_as4(aspath
))
2954 1; /* we'll do this later, at the correct place */
2956 /* Nexthop attribute. */
2957 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
2958 && !peer_cap_enhe(peer
, afi
, safi
)) {
2959 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2960 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
2961 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
2962 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
2965 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2966 } else if (peer_cap_enhe(from
, afi
, safi
)) {
2968 * Likely this is the case when an IPv4 prefix was
2970 * Extended Next-hop capability and now being advertised
2973 * Setting the mandatory (ipv4) next-hop attribute here
2975 * implicit next-hop self with correct (ipv4 address
2978 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
2979 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
2980 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
2983 stream_put_ipv4(s
, 0);
2987 /* MED attribute. */
2988 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
2989 || bgp
->maxmed_active
) {
2990 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
2991 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
2993 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
2997 /* Local preference. */
2998 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
2999 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3000 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3002 stream_putl(s
, attr
->local_pref
);
3005 /* Atomic aggregate. */
3006 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3007 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3008 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3013 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3014 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3015 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3016 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3019 /* AS4 capable peer */
3021 stream_putl(s
, attr
->aggregator_as
);
3023 /* 2-byte AS peer */
3026 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3028 if (attr
->aggregator_as
> 65535) {
3029 stream_putw(s
, BGP_AS_TRANS
);
3031 /* we have to send AS4_AGGREGATOR, too.
3032 * we'll do that later in order to send
3033 * attributes in ascending
3036 send_as4_aggregator
= 1;
3038 stream_putw(s
, (u_int16_t
)attr
->aggregator_as
);
3040 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3043 /* Community attribute. */
3044 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3045 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3046 if (attr
->community
->size
* 4 > 255) {
3048 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3049 | BGP_ATTR_FLAG_EXTLEN
);
3050 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3051 stream_putw(s
, attr
->community
->size
* 4);
3054 BGP_ATTR_FLAG_OPTIONAL
3055 | BGP_ATTR_FLAG_TRANS
);
3056 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3057 stream_putc(s
, attr
->community
->size
* 4);
3059 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3063 * Large Community attribute.
3065 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3066 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3067 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3068 if (attr
->lcommunity
->size
* 12 > 255) {
3070 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3071 | BGP_ATTR_FLAG_EXTLEN
);
3072 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3073 stream_putw(s
, attr
->lcommunity
->size
* 12);
3076 BGP_ATTR_FLAG_OPTIONAL
3077 | BGP_ATTR_FLAG_TRANS
);
3078 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3079 stream_putc(s
, attr
->lcommunity
->size
* 12);
3081 stream_put(s
, attr
->lcommunity
->val
,
3082 attr
->lcommunity
->size
* 12);
3085 /* Route Reflector. */
3086 if (peer
->sort
== BGP_PEER_IBGP
&& from
3087 && from
->sort
== BGP_PEER_IBGP
) {
3088 /* Originator ID. */
3089 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3090 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3093 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3094 stream_put_in_addr(s
, &attr
->originator_id
);
3096 stream_put_in_addr(s
, &from
->remote_id
);
3099 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3100 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3102 if (attr
->cluster
) {
3103 stream_putc(s
, attr
->cluster
->length
+ 4);
3104 /* If this peer configuration's parent BGP has
3106 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3107 stream_put_in_addr(s
, &bgp
->cluster_id
);
3109 stream_put_in_addr(s
, &bgp
->router_id
);
3110 stream_put(s
, attr
->cluster
->list
,
3111 attr
->cluster
->length
);
3114 /* If this peer configuration's parent BGP has
3116 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3117 stream_put_in_addr(s
, &bgp
->cluster_id
);
3119 stream_put_in_addr(s
, &bgp
->router_id
);
3123 /* Extended Communities attribute. */
3124 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3125 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3126 if (peer
->sort
== BGP_PEER_IBGP
3127 || peer
->sort
== BGP_PEER_CONFED
) {
3128 if (attr
->ecommunity
->size
* 8 > 255) {
3130 BGP_ATTR_FLAG_OPTIONAL
3131 | BGP_ATTR_FLAG_TRANS
3132 | BGP_ATTR_FLAG_EXTLEN
);
3133 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3134 stream_putw(s
, attr
->ecommunity
->size
* 8);
3137 BGP_ATTR_FLAG_OPTIONAL
3138 | BGP_ATTR_FLAG_TRANS
);
3139 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3140 stream_putc(s
, attr
->ecommunity
->size
* 8);
3142 stream_put(s
, attr
->ecommunity
->val
,
3143 attr
->ecommunity
->size
* 8);
3147 int ecom_tr_size
= 0;
3150 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3151 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3154 if (CHECK_FLAG(tbit
,
3155 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3162 if (ecom_tr_size
* 8 > 255) {
3165 BGP_ATTR_FLAG_OPTIONAL
3166 | BGP_ATTR_FLAG_TRANS
3167 | BGP_ATTR_FLAG_EXTLEN
);
3169 BGP_ATTR_EXT_COMMUNITIES
);
3170 stream_putw(s
, ecom_tr_size
* 8);
3174 BGP_ATTR_FLAG_OPTIONAL
3175 | BGP_ATTR_FLAG_TRANS
);
3177 BGP_ATTR_EXT_COMMUNITIES
);
3178 stream_putc(s
, ecom_tr_size
* 8);
3181 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3182 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3187 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3190 stream_put(s
, pnt
, 8);
3196 /* Label index attribute. */
3197 if (safi
== SAFI_LABELED_UNICAST
) {
3198 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3199 u_int32_t label_index
;
3201 label_index
= attr
->label_index
;
3203 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3205 BGP_ATTR_FLAG_OPTIONAL
3206 | BGP_ATTR_FLAG_TRANS
);
3207 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3209 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3211 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3212 stream_putc(s
, 0); // reserved
3213 stream_putw(s
, 0); // flags
3214 stream_putl(s
, label_index
);
3219 if (send_as4_path
) {
3220 /* If the peer is NOT As4 capable, AND */
3221 /* there are ASnums > 65535 in path THEN
3222 * give out AS4_PATH */
3224 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3226 * Hm, I wonder... confederation things *should* only be at
3227 * the beginning of an aspath, right? Then we should use
3228 * aspath_delete_confed_seq for this, because it is already
3230 * Folks, talk to me: what is reasonable here!?
3232 aspath
= aspath_delete_confed_seq(aspath
);
3235 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3236 | BGP_ATTR_FLAG_EXTLEN
);
3237 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3238 aspath_sizep
= stream_get_endp(s
);
3240 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3243 if (aspath
!= attr
->aspath
)
3244 aspath_free(aspath
);
3246 if (send_as4_aggregator
) {
3247 /* send AS4_AGGREGATOR, at this place */
3248 /* this section of code moved here in order to ensure the
3250 * *ascending* order of attributes
3252 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3253 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3255 stream_putl(s
, attr
->aggregator_as
);
3256 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3259 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3260 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3261 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3262 /* Tunnel Encap attribute */
3263 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3267 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3271 /* Unknown transit attribute. */
3273 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
3275 /* Return total size of attribute. */
3276 return stream_get_endp(s
) - cp
;
3279 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3281 unsigned long attrlen_pnt
;
3285 /* Set extended bit always to encode the attribute length as 2 bytes */
3286 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3287 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3289 attrlen_pnt
= stream_get_endp(s
);
3290 stream_putw(s
, 0); /* Length of this attribute. */
3292 /* Convert AFI, SAFI to values for packet. */
3293 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3295 stream_putw(s
, pkt_afi
);
3296 stream_putc(s
, pkt_safi
);
3301 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
3302 safi_t safi
, struct prefix_rd
*prd
,
3303 mpls_label_t
*label
, int addpath_encode
,
3304 u_int32_t addpath_tx_id
, struct attr
*attr
)
3306 u_char wlabel
[3] = {0x80, 0x00, 0x00};
3308 if (safi
== SAFI_LABELED_UNICAST
)
3309 label
= (mpls_label_t
*)wlabel
;
3311 return bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3312 addpath_encode
, addpath_tx_id
, attr
);
3315 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
3317 bgp_packet_mpattr_end(s
, attrlen_pnt
);
3320 /* Initialization of attribute. */
3321 void bgp_attr_init(void)
3333 void bgp_attr_finish(void)
3338 ecommunity_finish();
3339 lcommunity_finish();
3345 /* Make attribute packet. */
3346 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
3347 struct prefix
*prefix
)
3352 struct aspath
*aspath
;
3353 int addpath_encode
= 0;
3354 u_int32_t addpath_tx_id
= 0;
3356 /* Remember current pointer. */
3357 cp
= stream_get_endp(s
);
3359 /* Place holder of length. */
3362 /* Origin attribute. */
3363 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3364 stream_putc(s
, BGP_ATTR_ORIGIN
);
3366 stream_putc(s
, attr
->origin
);
3368 aspath
= attr
->aspath
;
3370 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3371 stream_putc(s
, BGP_ATTR_AS_PATH
);
3372 aspath_lenp
= stream_get_endp(s
);
3375 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
3377 /* Nexthop attribute. */
3378 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3379 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
3380 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3381 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3383 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3386 /* MED attribute. */
3387 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
3388 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3389 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3391 stream_putl(s
, attr
->med
);
3394 /* Local preference. */
3395 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
3396 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3397 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3399 stream_putl(s
, attr
->local_pref
);
3402 /* Atomic aggregate. */
3403 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3404 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3405 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3410 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3411 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3412 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3414 stream_putl(s
, attr
->aggregator_as
);
3415 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3418 /* Community attribute. */
3419 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3420 if (attr
->community
->size
* 4 > 255) {
3422 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3423 | BGP_ATTR_FLAG_EXTLEN
);
3424 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3425 stream_putw(s
, attr
->community
->size
* 4);
3428 BGP_ATTR_FLAG_OPTIONAL
3429 | BGP_ATTR_FLAG_TRANS
);
3430 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3431 stream_putc(s
, attr
->community
->size
* 4);
3433 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3436 /* Large Community attribute. */
3437 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
3438 if (attr
->lcommunity
->size
* 12 > 255) {
3440 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3441 | BGP_ATTR_FLAG_EXTLEN
);
3442 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3443 stream_putw(s
, attr
->lcommunity
->size
* 12);
3446 BGP_ATTR_FLAG_OPTIONAL
3447 | BGP_ATTR_FLAG_TRANS
);
3448 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3449 stream_putc(s
, attr
->lcommunity
->size
* 12);
3452 stream_put(s
, attr
->lcommunity
->val
,
3453 attr
->lcommunity
->size
* 12);
3456 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3457 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
3458 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
3459 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
3462 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3463 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3464 sizep
= stream_get_endp(s
);
3467 stream_putc(s
, 0); /* Marker: Attribute length. */
3468 stream_putw(s
, AFI_IP6
); /* AFI */
3469 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3472 stream_putc(s
, attr
->mp_nexthop_len
);
3473 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3474 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3475 stream_put(s
, &attr
->mp_nexthop_local
,
3482 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
3485 /* Set MP attribute length. */
3486 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
3490 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3491 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3493 BGP_ATTR_FLAG_OPTIONAL
3494 | BGP_ATTR_FLAG_TRANS
);
3495 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3497 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3498 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3499 stream_putc(s
, 0); // reserved
3500 stream_putw(s
, 0); // flags
3501 stream_putl(s
, attr
->label_index
);
3505 /* Return total size of attribute. */
3506 len
= stream_get_endp(s
) - cp
- 2;
3507 stream_putw_at(s
, cp
, len
);