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
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
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_packet.h"
43 #include "bgpd/bgp_ecommunity.h"
44 #include "bgpd/bgp_lcommunity.h"
45 #include "bgpd/bgp_updgrp.h"
46 #include "bgpd/bgp_encap_types.h"
48 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
49 #include "bgp_encap_types.h"
50 #include "bgp_vnc_types.h"
52 #include "bgp_encap_types.h"
55 /* Attribute strings for logging. */
56 static const struct message attr_str
[] = {
57 {BGP_ATTR_ORIGIN
, "ORIGIN"},
58 {BGP_ATTR_AS_PATH
, "AS_PATH"},
59 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
60 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
61 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
62 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
63 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
64 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
65 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
66 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
67 {BGP_ATTR_DPA
, "DPA"},
68 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
69 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
70 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
71 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
72 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
73 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
74 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
75 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
76 {BGP_ATTR_ENCAP
, "ENCAP"},
78 {BGP_ATTR_VNC
, "VNC"},
80 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
83 static const struct message attr_flag_str
[] =
85 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
86 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
87 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
88 /* bgp_attr_flags_diagnose() relies on this bit being last in
90 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
93 static struct hash
*cluster_hash
;
95 static void *cluster_hash_alloc(void *p
)
97 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
98 struct cluster_list
*cluster
;
100 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
101 cluster
->length
= val
->length
;
103 if (cluster
->length
) {
104 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
105 memcpy(cluster
->list
, val
->list
, val
->length
);
107 cluster
->list
= NULL
;
114 /* Cluster list related functions. */
115 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
117 struct cluster_list tmp
;
118 struct cluster_list
*cluster
;
123 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
128 int cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
132 for (i
= 0; i
< cluster
->length
/ 4; i
++)
133 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
138 static unsigned int cluster_hash_key_make(void *p
)
140 const struct cluster_list
*cluster
= p
;
142 return jhash(cluster
->list
, cluster
->length
, 0);
145 static int cluster_hash_cmp(const void *p1
, const void *p2
)
147 const struct cluster_list
*cluster1
= p1
;
148 const struct cluster_list
*cluster2
= p2
;
150 return (cluster1
->length
== cluster2
->length
151 && memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
)
155 static void cluster_free(struct cluster_list
*cluster
)
158 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
159 XFREE(MTYPE_CLUSTER
, cluster
);
162 static struct cluster_list
*cluster_dup(struct cluster_list
*cluster
)
164 struct cluster_list
*new;
166 new = XCALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
167 new->length
= cluster
->length
;
169 if (cluster
->length
) {
170 new->list
= XMALLOC(MTYPE_CLUSTER_VAL
, cluster
->length
);
171 memcpy(new->list
, cluster
->list
, cluster
->length
);
178 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
180 struct cluster_list
*find
;
182 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
188 void cluster_unintern(struct cluster_list
*cluster
)
193 if (cluster
->refcnt
== 0) {
194 hash_release(cluster_hash
, cluster
);
195 cluster_free(cluster
);
199 static void cluster_init(void)
201 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
);
204 static void cluster_finish(void)
206 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
207 hash_free(cluster_hash
);
211 static struct hash
*encap_hash
= NULL
;
213 static struct hash
*vnc_hash
= NULL
;
216 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
218 struct bgp_attr_encap_subtlv
*new;
219 struct bgp_attr_encap_subtlv
*tail
;
220 struct bgp_attr_encap_subtlv
*p
;
222 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
223 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
225 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
228 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
231 memcpy(tail
, p
, size
);
238 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
240 struct bgp_attr_encap_subtlv
*next
;
244 XFREE(MTYPE_ENCAP_TLV
, p
);
249 void bgp_attr_flush_encap(struct attr
*attr
)
251 if (!attr
|| !attr
->extra
)
254 if (attr
->extra
->encap_subtlvs
) {
255 encap_free(attr
->extra
->encap_subtlvs
);
256 attr
->extra
->encap_subtlvs
= NULL
;
259 if (attr
->extra
->vnc_subtlvs
) {
260 encap_free(attr
->extra
->vnc_subtlvs
);
261 attr
->extra
->vnc_subtlvs
= NULL
;
267 * Compare encap sub-tlv chains
272 * This algorithm could be made faster if needed
274 static int encap_same(struct bgp_attr_encap_subtlv
*h1
,
275 struct bgp_attr_encap_subtlv
*h2
)
277 struct bgp_attr_encap_subtlv
*p
;
278 struct bgp_attr_encap_subtlv
*q
;
282 if (h1
== NULL
|| h2
== NULL
)
285 for (p
= h1
; p
; p
= p
->next
) {
286 for (q
= h2
; q
; q
= q
->next
) {
287 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
288 && !memcmp(p
->value
, q
->value
, p
->length
)) {
297 for (p
= h2
; p
; p
= p
->next
) {
298 for (q
= h1
; q
; q
= q
->next
) {
299 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
300 && !memcmp(p
->value
, q
->value
, p
->length
)) {
312 static void *encap_hash_alloc(void *p
)
314 /* Encap structure is already allocated. */
325 static struct bgp_attr_encap_subtlv
*
326 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
328 struct bgp_attr_encap_subtlv
*find
;
329 struct hash
*hash
= encap_hash
;
331 if (type
== VNC_SUBTLV_TYPE
)
335 find
= hash_get(hash
, encap
, encap_hash_alloc
);
343 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
344 encap_subtlv_type type
)
346 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
350 if (encap
->refcnt
== 0) {
351 struct hash
*hash
= encap_hash
;
353 if (type
== VNC_SUBTLV_TYPE
)
356 hash_release(hash
, encap
);
362 static unsigned int encap_hash_key_make(void *p
)
364 const struct bgp_attr_encap_subtlv
*encap
= p
;
366 return jhash(encap
->value
, encap
->length
, 0);
369 static int encap_hash_cmp(const void *p1
, const void *p2
)
371 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
372 (struct bgp_attr_encap_subtlv
*)p2
);
375 static void encap_init(void)
377 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
);
379 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
);
383 static void encap_finish(void)
385 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
386 hash_free(encap_hash
);
389 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
395 static bool overlay_index_same(const struct attr_extra
*ae1
,
396 const struct attr_extra
*ae2
)
404 return !memcmp(&(ae1
->evpn_overlay
), &(ae2
->evpn_overlay
),
405 sizeof(struct overlay_index
));
408 /* Unknown transit attribute. */
409 static struct hash
*transit_hash
;
411 static void transit_free(struct transit
*transit
)
414 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
415 XFREE(MTYPE_TRANSIT
, transit
);
418 static struct transit
*transit_dup(struct transit
*transit
)
422 new = XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
423 new->length
= transit
->length
;
425 new->val
= XMALLOC(MTYPE_TRANSIT_VAL
, transit
->length
);
426 memcpy(new->val
, transit
->val
, transit
->length
);
433 static void *transit_hash_alloc(void *p
)
435 /* Transit structure is already allocated. */
439 static struct transit
*transit_intern(struct transit
*transit
)
441 struct transit
*find
;
443 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
445 transit_free(transit
);
451 void transit_unintern(struct transit
*transit
)
456 if (transit
->refcnt
== 0) {
457 hash_release(transit_hash
, transit
);
458 transit_free(transit
);
462 static unsigned int transit_hash_key_make(void *p
)
464 const struct transit
*transit
= p
;
466 return jhash(transit
->val
, transit
->length
, 0);
469 static int transit_hash_cmp(const void *p1
, const void *p2
)
471 const struct transit
*transit1
= p1
;
472 const struct transit
*transit2
= p2
;
474 return (transit1
->length
== transit2
->length
475 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
478 static void transit_init(void)
480 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
);
483 static void transit_finish(void)
485 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
486 hash_free(transit_hash
);
490 /* Attribute hash routines. */
491 static struct hash
*attrhash
;
493 static struct attr_extra
*bgp_attr_extra_new(void)
495 return XCALLOC(MTYPE_ATTR_EXTRA
, sizeof(struct attr_extra
));
498 void bgp_attr_extra_free(struct attr
*attr
)
501 XFREE(MTYPE_ATTR_EXTRA
, attr
->extra
);
506 struct attr_extra
*bgp_attr_extra_get(struct attr
*attr
)
509 attr
->extra
= bgp_attr_extra_new();
513 /* Shallow copy of an attribute
514 * Though, not so shallow that it doesn't copy the contents
515 * of the attr_extra pointed to by 'extra'
517 void bgp_attr_dup(struct attr
*new, struct attr
*orig
)
519 struct attr_extra
*extra
= new->extra
;
522 /* if caller provided attr_extra space, use it in any case.
524 * This is neccesary even if orig->extra equals NULL, because otherwise
525 * memory may be later allocated on the heap by bgp_attr_extra_get.
527 * That memory would eventually be leaked, because the caller must not
528 * call bgp_attr_extra_free if he provided attr_extra on the stack.
532 memset(new->extra
, 0, sizeof(struct attr_extra
));
534 *new->extra
= *orig
->extra
;
536 } else if (orig
->extra
) {
537 new->extra
= bgp_attr_extra_new();
538 *new->extra
= *orig
->extra
;
542 void bgp_attr_deep_dup(struct attr
*new, struct attr
*orig
)
545 new->aspath
= aspath_dup(orig
->aspath
);
548 new->community
= community_dup(orig
->community
);
551 if (orig
->extra
->ecommunity
)
552 new->extra
->ecommunity
=
553 ecommunity_dup(orig
->extra
->ecommunity
);
554 if (orig
->extra
->cluster
)
555 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
556 if (orig
->extra
->transit
)
557 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
558 if (orig
->extra
->encap_subtlvs
)
559 new->extra
->encap_subtlvs
=
560 encap_tlv_dup(orig
->extra
->encap_subtlvs
);
562 if (orig
->extra
->vnc_subtlvs
)
563 new->extra
->vnc_subtlvs
=
564 encap_tlv_dup(orig
->extra
->vnc_subtlvs
);
569 void bgp_attr_deep_free(struct attr
*attr
)
572 aspath_free(attr
->aspath
);
575 community_free(attr
->community
);
578 if (attr
->extra
->ecommunity
)
579 ecommunity_free(&attr
->extra
->ecommunity
);
580 if (attr
->extra
->cluster
)
581 cluster_free(attr
->extra
->cluster
);
582 if (attr
->extra
->transit
)
583 transit_free(attr
->extra
->transit
);
584 if (attr
->extra
->encap_subtlvs
)
585 encap_free(attr
->extra
->encap_subtlvs
);
587 if (attr
->extra
->vnc_subtlvs
)
588 encap_free(attr
->extra
->vnc_subtlvs
);
593 unsigned long int attr_count(void)
595 return attrhash
->count
;
598 unsigned long int attr_unknown_count(void)
600 return transit_hash
->count
;
603 unsigned int attrhash_key_make(void *p
)
605 const struct attr
*attr
= (struct attr
*)p
;
606 const struct attr_extra
*extra
= attr
->extra
;
608 #define MIX(val) key = jhash_1word(val, key)
611 MIX(attr
->nexthop
.s_addr
);
613 MIX(attr
->local_pref
);
616 key
+= attr
->nexthop
.s_addr
;
618 key
+= attr
->local_pref
;
621 MIX(extra
->aggregator_as
);
622 MIX(extra
->aggregator_addr
.s_addr
);
624 MIX(extra
->mp_nexthop_global_in
.s_addr
);
625 MIX(extra
->originator_id
.s_addr
);
630 MIX(aspath_key_make(attr
->aspath
));
632 MIX(community_hash_make(attr
->community
));
635 if (extra
->lcommunity
)
636 MIX(lcommunity_hash_make(extra
->lcommunity
));
637 if (extra
->ecommunity
)
638 MIX(ecommunity_hash_make(extra
->ecommunity
));
640 MIX(cluster_hash_key_make(extra
->cluster
));
642 MIX(transit_hash_key_make(extra
->transit
));
643 if (extra
->encap_subtlvs
)
644 MIX(encap_hash_key_make(extra
->encap_subtlvs
));
646 if (extra
->vnc_subtlvs
)
647 MIX(encap_hash_key_make(extra
->vnc_subtlvs
));
649 MIX(extra
->mp_nexthop_len
);
650 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
,
652 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
,
659 int attrhash_cmp(const void *p1
, const void *p2
)
661 const struct attr
*attr1
= p1
;
662 const struct attr
*attr2
= p2
;
664 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
665 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
666 && attr1
->aspath
== attr2
->aspath
667 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
668 && attr1
->local_pref
== attr2
->local_pref
669 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
670 const struct attr_extra
*ae1
= attr1
->extra
;
671 const struct attr_extra
*ae2
= attr2
->extra
;
673 if (ae1
&& ae2
&& ae1
->aggregator_as
== ae2
->aggregator_as
674 && ae1
->aggregator_addr
.s_addr
675 == ae2
->aggregator_addr
.s_addr
676 && ae1
->weight
== ae2
->weight
&& ae1
->tag
== ae2
->tag
677 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
678 && IPV6_ADDR_SAME(&ae1
->mp_nexthop_global
,
679 &ae2
->mp_nexthop_global
)
680 && IPV6_ADDR_SAME(&ae1
->mp_nexthop_local
,
681 &ae2
->mp_nexthop_local
)
682 && IPV4_ADDR_SAME(&ae1
->mp_nexthop_global_in
,
683 &ae2
->mp_nexthop_global_in
)
684 && ae1
->ecommunity
== ae2
->ecommunity
685 && ae1
->lcommunity
== ae2
->lcommunity
686 && ae1
->cluster
== ae2
->cluster
687 && ae1
->transit
== ae2
->transit
688 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
689 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
691 && encap_same(ae1
->vnc_subtlvs
, ae2
->vnc_subtlvs
)
693 && IPV4_ADDR_SAME(&ae1
->originator_id
, &ae2
->originator_id
)
694 && overlay_index_same(ae1
, ae2
))
698 /* neither attribute has extra attributes, so they're same */
704 static void attrhash_init(void)
706 attrhash
= hash_create(attrhash_key_make
, attrhash_cmp
);
710 * special for hash_clean below
712 static void attr_vfree(void *attr
)
714 bgp_attr_extra_free((struct attr
*)attr
);
715 XFREE(MTYPE_ATTR
, attr
);
718 static void attrhash_finish(void)
720 hash_clean(attrhash
, attr_vfree
);
725 static void attr_show_all_iterator(struct hash_backet
*backet
, struct vty
*vty
)
727 struct attr
*attr
= backet
->data
;
729 vty_out(vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
730 inet_ntoa(attr
->nexthop
), VTY_NEWLINE
);
733 void attr_show_all(struct vty
*vty
)
735 hash_iterate(attrhash
, (void (*)(struct hash_backet
*,
736 void *))attr_show_all_iterator
,
740 static void *bgp_attr_hash_alloc(void *p
)
742 const struct attr
*val
= (const struct attr
*)p
;
745 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
748 attr
->extra
= bgp_attr_extra_new();
749 *attr
->extra
= *val
->extra
;
750 if (val
->extra
->encap_subtlvs
) {
751 val
->extra
->encap_subtlvs
= NULL
;
754 if (val
->extra
->vnc_subtlvs
) {
755 val
->extra
->vnc_subtlvs
= NULL
;
763 /* Internet argument attribute. */
764 struct attr
*bgp_attr_intern(struct attr
*attr
)
768 /* Intern referenced strucutre. */
770 if (!attr
->aspath
->refcnt
)
771 attr
->aspath
= aspath_intern(attr
->aspath
);
773 attr
->aspath
->refcnt
++;
775 if (attr
->community
) {
776 if (!attr
->community
->refcnt
)
777 attr
->community
= community_intern(attr
->community
);
779 attr
->community
->refcnt
++;
782 struct attr_extra
*attre
= attr
->extra
;
784 if (attre
->ecommunity
) {
785 if (!attre
->ecommunity
->refcnt
)
787 ecommunity_intern(attre
->ecommunity
);
789 attre
->ecommunity
->refcnt
++;
791 if (attre
->lcommunity
) {
792 if (!attre
->lcommunity
->refcnt
)
794 lcommunity_intern(attre
->lcommunity
);
796 attre
->lcommunity
->refcnt
++;
798 if (attre
->cluster
) {
799 if (!attre
->cluster
->refcnt
)
800 attre
->cluster
= cluster_intern(attre
->cluster
);
802 attre
->cluster
->refcnt
++;
804 if (attre
->transit
) {
805 if (!attre
->transit
->refcnt
)
806 attre
->transit
= transit_intern(attre
->transit
);
808 attre
->transit
->refcnt
++;
810 if (attre
->encap_subtlvs
) {
811 if (!attre
->encap_subtlvs
->refcnt
)
812 attre
->encap_subtlvs
=
813 encap_intern(attre
->encap_subtlvs
,
816 attre
->encap_subtlvs
->refcnt
++;
819 if (attre
->vnc_subtlvs
) {
820 if (!attre
->vnc_subtlvs
->refcnt
)
821 attre
->vnc_subtlvs
= encap_intern(
822 attre
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
824 attre
->vnc_subtlvs
->refcnt
++;
829 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
836 * Increment the refcount on various structures that attr holds.
837 * Note on usage: call _only_ when the 'attr' object has already
838 * been 'intern'ed and exists in 'attrhash' table. The function
839 * serves to hold a reference to that (real) object.
840 * Note also that the caller can safely call bgp_attr_unintern()
841 * after calling bgp_attr_refcount(). That would release the
842 * reference and could result in a free() of the attr object.
844 struct attr
*bgp_attr_refcount(struct attr
*attr
)
846 /* Intern referenced strucutre. */
848 attr
->aspath
->refcnt
++;
851 attr
->community
->refcnt
++;
854 struct attr_extra
*attre
= attr
->extra
;
855 if (attre
->ecommunity
)
856 attre
->ecommunity
->refcnt
++;
859 attre
->cluster
->refcnt
++;
862 attre
->transit
->refcnt
++;
864 if (attre
->encap_subtlvs
)
865 attre
->encap_subtlvs
->refcnt
++;
868 if (attre
->vnc_subtlvs
)
869 attre
->vnc_subtlvs
->refcnt
++;
876 /* Make network statement's attribute. */
877 struct attr
*bgp_attr_default_set(struct attr
*attr
, u_char origin
)
879 memset(attr
, 0, sizeof(struct attr
));
880 bgp_attr_extra_get(attr
);
882 attr
->origin
= origin
;
883 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
884 attr
->aspath
= aspath_empty();
885 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
886 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
887 attr
->extra
->tag
= 0;
888 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
889 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
895 /* Make network statement's attribute. */
896 struct attr
*bgp_attr_default_intern(u_char origin
)
901 memset(&attr
, 0, sizeof(struct attr
));
902 bgp_attr_extra_get(&attr
);
904 bgp_attr_default_set(&attr
, origin
);
906 new = bgp_attr_intern(&attr
);
907 bgp_attr_extra_free(&attr
);
909 aspath_unintern(&new->aspath
);
913 /* Create the attributes for an aggregate */
914 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, u_char origin
,
915 struct aspath
*aspath
,
916 struct community
*community
, int as_set
,
917 u_char atomic_aggregate
)
921 struct attr_extra attre
;
923 memset(&attr
, 0, sizeof(struct attr
));
924 memset(&attre
, 0, sizeof(struct attr_extra
));
927 /* Origin attribute. */
928 attr
.origin
= origin
;
929 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
931 /* AS path attribute. */
933 attr
.aspath
= aspath_intern(aspath
);
935 attr
.aspath
= aspath_empty();
936 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
938 /* Next hop attribute. */
939 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
942 attr
.community
= community
;
943 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
946 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
947 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
948 if (!as_set
|| atomic_aggregate
)
949 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
950 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
951 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
952 attre
.aggregator_as
= bgp
->confed_id
;
954 attre
.aggregator_as
= bgp
->as
;
955 attre
.aggregator_addr
= bgp
->router_id
;
957 new = bgp_attr_intern(&attr
);
959 aspath_unintern(&new->aspath
);
963 /* Unintern just the sub-components of the attr, but not the attr */
964 void bgp_attr_unintern_sub(struct attr
*attr
)
966 /* aspath refcount shoud be decrement. */
968 aspath_unintern(&attr
->aspath
);
969 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
972 community_unintern(&attr
->community
);
973 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
976 if (attr
->extra
->ecommunity
)
977 ecommunity_unintern(&attr
->extra
->ecommunity
);
978 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
980 if (attr
->extra
->lcommunity
)
981 lcommunity_unintern(&attr
->extra
->lcommunity
);
982 UNSET_FLAG(attr
->flag
,
983 ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
985 if (attr
->extra
->cluster
)
986 cluster_unintern(attr
->extra
->cluster
);
987 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
989 if (attr
->extra
->transit
)
990 transit_unintern(attr
->extra
->transit
);
992 if (attr
->extra
->encap_subtlvs
)
993 encap_unintern(&attr
->extra
->encap_subtlvs
,
997 if (attr
->extra
->vnc_subtlvs
)
998 encap_unintern(&attr
->extra
->vnc_subtlvs
,
1004 /* Free bgp attribute and aspath. */
1005 void bgp_attr_unintern(struct attr
**pattr
)
1007 struct attr
*attr
= *pattr
;
1010 struct attr_extra tmp_extra
;
1012 /* Decrement attribute reference. */
1018 tmp
.extra
= &tmp_extra
;
1019 memcpy(tmp
.extra
, attr
->extra
, sizeof(struct attr_extra
));
1022 /* If reference becomes zero then free attribute object. */
1023 if (attr
->refcnt
== 0) {
1024 ret
= hash_release(attrhash
, attr
);
1025 assert(ret
!= NULL
);
1026 bgp_attr_extra_free(attr
);
1027 XFREE(MTYPE_ATTR
, attr
);
1031 bgp_attr_unintern_sub(&tmp
);
1034 void bgp_attr_flush(struct attr
*attr
)
1036 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1037 aspath_free(attr
->aspath
);
1038 attr
->aspath
= NULL
;
1040 if (attr
->community
&& !attr
->community
->refcnt
) {
1041 community_free(attr
->community
);
1042 attr
->community
= NULL
;
1045 struct attr_extra
*attre
= attr
->extra
;
1047 if (attre
->ecommunity
&& !attre
->ecommunity
->refcnt
)
1048 ecommunity_free(&attre
->ecommunity
);
1049 if (attre
->lcommunity
&& !attre
->lcommunity
->refcnt
)
1050 lcommunity_free(&attre
->lcommunity
);
1051 if (attre
->cluster
&& !attre
->cluster
->refcnt
) {
1052 cluster_free(attre
->cluster
);
1053 attre
->cluster
= NULL
;
1055 if (attre
->transit
&& !attre
->transit
->refcnt
) {
1056 transit_free(attre
->transit
);
1057 attre
->transit
= NULL
;
1059 if (attre
->encap_subtlvs
&& !attre
->encap_subtlvs
->refcnt
) {
1060 encap_free(attre
->encap_subtlvs
);
1061 attre
->encap_subtlvs
= NULL
;
1064 if (attre
->vnc_subtlvs
&& !attre
->vnc_subtlvs
->refcnt
) {
1065 encap_free(attre
->vnc_subtlvs
);
1066 attre
->vnc_subtlvs
= NULL
;
1072 /* Implement draft-scudder-idr-optional-transitive behaviour and
1073 * avoid resetting sessions for malformed attributes which are
1074 * are partial/optional and hence where the error likely was not
1075 * introduced by the sending neighbour.
1077 static bgp_attr_parse_ret_t
1078 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, u_char subcode
,
1081 struct peer
*const peer
= args
->peer
;
1082 const u_int8_t flags
= args
->flags
;
1083 /* startp and length must be special-cased, as whether or not to
1084 * send the attribute data with the NOTIFY depends on the error,
1085 * the caller therefore signals this with the seperate length argument
1087 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1089 /* Only relax error handling for eBGP peers */
1090 if (peer
->sort
!= BGP_PEER_EBGP
) {
1091 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1092 notify_datap
, length
);
1093 return BGP_ATTR_PARSE_ERROR
;
1096 /* Adjust the stream getp to the end of the attribute, in case we can
1097 * still proceed but the caller hasn't read all the attribute.
1099 stream_set_getp(BGP_INPUT(peer
),
1100 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1103 switch (args
->type
) {
1104 /* where an attribute is relatively inconsequential, e.g. it does not
1105 * affect route selection, and can be safely ignored, then any such
1106 * attributes which are malformed should just be ignored and the route
1107 * processed as normal.
1109 case BGP_ATTR_AS4_AGGREGATOR
:
1110 case BGP_ATTR_AGGREGATOR
:
1111 case BGP_ATTR_ATOMIC_AGGREGATE
:
1112 return BGP_ATTR_PARSE_PROCEED
;
1114 /* Core attributes, particularly ones which may influence route
1115 * selection, should always cause session resets
1117 case BGP_ATTR_ORIGIN
:
1118 case BGP_ATTR_AS_PATH
:
1119 case BGP_ATTR_NEXT_HOP
:
1120 case BGP_ATTR_MULTI_EXIT_DISC
:
1121 case BGP_ATTR_LOCAL_PREF
:
1122 case BGP_ATTR_COMMUNITIES
:
1123 case BGP_ATTR_ORIGINATOR_ID
:
1124 case BGP_ATTR_CLUSTER_LIST
:
1125 case BGP_ATTR_MP_REACH_NLRI
:
1126 case BGP_ATTR_MP_UNREACH_NLRI
:
1127 case BGP_ATTR_EXT_COMMUNITIES
:
1128 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1129 notify_datap
, length
);
1130 return BGP_ATTR_PARSE_ERROR
;
1133 /* Partial optional attributes that are malformed should not cause
1134 * the whole session to be reset. Instead treat it as a withdrawal
1135 * of the routes, if possible.
1137 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1138 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1139 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1140 return BGP_ATTR_PARSE_WITHDRAW
;
1142 /* default to reset */
1143 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1146 /* Find out what is wrong with the path attribute flag bits and log the error.
1147 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1148 Extended Length. Checking O/T/P bits at once implies, that the attribute
1149 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1150 non-transitive" attribute. */
1152 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1153 u_int8_t desired_flags
/* how RFC says it must be */
1157 u_char real_flags
= args
->flags
;
1158 const u_int8_t attr_code
= args
->type
;
1160 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1161 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1162 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1163 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1164 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1165 zlog_err("%s attribute must%s be flagged as \"%s\"",
1166 lookup_msg(attr_str
, attr_code
, NULL
),
1167 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1170 attr_flag_str
[i
].str
);
1175 "Strange, %s called for attr %s, but no problem found with flags"
1176 " (real flags 0x%x, desired 0x%x)",
1177 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1178 real_flags
, desired_flags
);
1182 /* Required flags for attributes. EXTLEN will be masked off when testing,
1183 * as will PARTIAL for optional+transitive attributes.
1185 const u_int8_t attr_flags_values
[] = {
1186 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1187 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1188 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1189 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1190 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1191 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1192 [BGP_ATTR_AGGREGATOR
] =
1193 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1194 [BGP_ATTR_COMMUNITIES
] =
1195 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1196 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1197 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1198 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1199 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1200 [BGP_ATTR_EXT_COMMUNITIES
] =
1201 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1202 [BGP_ATTR_AS4_PATH
] =
1203 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1204 [BGP_ATTR_AS4_AGGREGATOR
] =
1205 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1206 [BGP_ATTR_LARGE_COMMUNITIES
] =
1207 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1209 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1211 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1213 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1214 const u_int8_t flags
= args
->flags
;
1215 const u_int8_t attr_code
= args
->type
;
1217 /* there may be attributes we don't know about */
1218 if (attr_code
> attr_flags_values_max
)
1220 if (attr_flags_values
[attr_code
] == 0)
1223 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1227 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1228 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1230 "%s well-known attributes must have transitive flag set (%x)",
1231 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1235 /* "For well-known attributes and for optional non-transitive
1237 * the Partial bit MUST be set to 0."
1239 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1240 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1242 "%s well-known attribute "
1243 "must NOT have the partial flag set (%x)",
1244 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1247 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1248 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1250 "%s optional + transitive attribute "
1251 "must NOT have the partial flag set (%x)",
1252 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1257 /* Optional transitive attributes may go through speakers that don't
1258 * reocgnise them and set the Partial bit.
1260 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1261 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1262 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1264 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1267 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1271 /* Get origin attribute of the update message. */
1272 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1274 struct peer
*const peer
= args
->peer
;
1275 struct attr
*const attr
= args
->attr
;
1276 const bgp_size_t length
= args
->length
;
1278 /* If any recognized attribute has Attribute Length that conflicts
1279 with the expected length (based on the attribute type code), then
1280 the Error Subcode is set to Attribute Length Error. The Data
1281 field contains the erroneous attribute (type, length and
1284 zlog_err("Origin attribute length is not one %d", length
);
1285 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1289 /* Fetch origin attribute. */
1290 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1292 /* If the ORIGIN attribute has an undefined value, then the Error
1293 Subcode is set to Invalid Origin Attribute. The Data field
1294 contains the unrecognized attribute (type, length and value). */
1295 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1296 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1297 zlog_err("Origin attribute value is invalid %d", attr
->origin
);
1298 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1302 /* Set oring attribute flag. */
1303 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1308 /* Parse AS path information. This function is wrapper of
1310 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1312 struct attr
*const attr
= args
->attr
;
1313 struct peer
*const peer
= args
->peer
;
1314 const bgp_size_t length
= args
->length
;
1317 * peer with AS4 => will get 4Byte ASnums
1318 * otherwise, will get 16 Bit
1320 attr
->aspath
= aspath_parse(peer
->ibuf
, length
,
1321 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1323 /* In case of IBGP, length will be zero. */
1324 if (!attr
->aspath
) {
1325 zlog_err("Malformed AS path from %s, length is %d", peer
->host
,
1327 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1331 /* Set aspath attribute flag. */
1332 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1334 return BGP_ATTR_PARSE_PROCEED
;
1337 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1338 struct attr
*const attr
)
1340 /* These checks were part of bgp_attr_aspath, but with
1341 * as4 we should to check aspath things when
1342 * aspath synthesizing with as4_path has already taken place.
1343 * Otherwise we check ASPATH and use the synthesized thing, and that is
1345 * So do the checks later, i.e. here
1347 struct bgp
*bgp
= peer
->bgp
;
1348 struct aspath
*aspath
;
1350 /* Confederation sanity check. */
1351 if ((peer
->sort
== BGP_PEER_CONFED
1352 && !aspath_left_confed_check(attr
->aspath
))
1353 || (peer
->sort
== BGP_PEER_EBGP
1354 && aspath_confed_check(attr
->aspath
))) {
1355 zlog_err("Malformed AS path from %s", peer
->host
);
1356 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1357 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1358 return BGP_ATTR_PARSE_ERROR
;
1361 /* First AS check for EBGP. */
1362 if (bgp
!= NULL
&& bgp_flag_check(bgp
, BGP_FLAG_ENFORCE_FIRST_AS
)) {
1363 if (peer
->sort
== BGP_PEER_EBGP
1364 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1365 zlog_err("%s incorrect first AS (must be %u)",
1366 peer
->host
, peer
->as
);
1367 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1368 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1369 return BGP_ATTR_PARSE_ERROR
;
1373 /* local-as prepend */
1374 if (peer
->change_local_as
1375 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1376 aspath
= aspath_dup(attr
->aspath
);
1377 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1378 aspath_unintern(&attr
->aspath
);
1379 attr
->aspath
= aspath_intern(aspath
);
1382 return BGP_ATTR_PARSE_PROCEED
;
1385 /* Parse AS4 path information. This function is another wrapper of
1387 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1388 struct aspath
**as4_path
)
1390 struct peer
*const peer
= args
->peer
;
1391 struct attr
*const attr
= args
->attr
;
1392 const bgp_size_t length
= args
->length
;
1394 *as4_path
= aspath_parse(peer
->ibuf
, length
, 1);
1396 /* In case of IBGP, length will be zero. */
1398 zlog_err("Malformed AS4 path from %s, length is %d", peer
->host
,
1400 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1404 /* Set aspath attribute flag. */
1406 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1408 return BGP_ATTR_PARSE_PROCEED
;
1411 /* Nexthop attribute. */
1412 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1414 struct peer
*const peer
= args
->peer
;
1415 struct attr
*const attr
= args
->attr
;
1416 const bgp_size_t length
= args
->length
;
1418 in_addr_t nexthop_h
, nexthop_n
;
1420 /* Check nexthop attribute length. */
1422 zlog_err("Nexthop attribute length isn't four [%d]", length
);
1424 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1428 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1429 attribute must result in a NOTIFICATION message (this is implemented
1431 At the same time, semantically incorrect NEXT_HOP is more likely to
1433 logged locally (this is implemented somewhere else). The UPDATE
1435 gets ignored in any of these cases. */
1436 nexthop_n
= stream_get_ipv4(peer
->ibuf
);
1437 nexthop_h
= ntohl(nexthop_n
);
1438 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1439 || IPV4_CLASS_DE(nexthop_h
))
1442 ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1444 char buf
[INET_ADDRSTRLEN
];
1445 inet_ntop(AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1446 zlog_err("Martian nexthop %s", buf
);
1447 return bgp_attr_malformed(
1448 args
, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
, args
->total
);
1451 attr
->nexthop
.s_addr
= nexthop_n
;
1452 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1454 return BGP_ATTR_PARSE_PROCEED
;
1457 /* MED atrribute. */
1458 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1460 struct peer
*const peer
= args
->peer
;
1461 struct attr
*const attr
= args
->attr
;
1462 const bgp_size_t length
= args
->length
;
1466 zlog_err("MED attribute length isn't four [%d]", length
);
1468 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1472 attr
->med
= stream_getl(peer
->ibuf
);
1474 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1476 return BGP_ATTR_PARSE_PROCEED
;
1479 /* Local preference attribute. */
1480 static bgp_attr_parse_ret_t
1481 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1483 struct peer
*const peer
= args
->peer
;
1484 struct attr
*const attr
= args
->attr
;
1485 const bgp_size_t length
= args
->length
;
1489 zlog_err("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1490 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1494 /* If it is contained in an UPDATE message that is received from an
1495 external peer, then this attribute MUST be ignored by the
1496 receiving speaker. */
1497 if (peer
->sort
== BGP_PEER_EBGP
) {
1498 stream_forward_getp(peer
->ibuf
, length
);
1499 return BGP_ATTR_PARSE_PROCEED
;
1502 attr
->local_pref
= stream_getl(peer
->ibuf
);
1504 /* Set atomic aggregate flag. */
1505 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1507 return BGP_ATTR_PARSE_PROCEED
;
1510 /* Atomic aggregate. */
1511 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1513 struct attr
*const attr
= args
->attr
;
1514 const bgp_size_t length
= args
->length
;
1518 zlog_err("ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1520 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1524 /* Set atomic aggregate flag. */
1525 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1527 return BGP_ATTR_PARSE_PROCEED
;
1530 /* Aggregator attribute */
1531 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1533 struct peer
*const peer
= args
->peer
;
1534 struct attr
*const attr
= args
->attr
;
1535 const bgp_size_t length
= args
->length
;
1538 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1540 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1541 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1544 if (length
!= wantedlen
) {
1545 zlog_err("AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1547 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1551 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1552 attre
->aggregator_as
= stream_getl(peer
->ibuf
);
1554 attre
->aggregator_as
= stream_getw(peer
->ibuf
);
1555 attre
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->ibuf
);
1557 /* Set atomic aggregate flag. */
1558 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1560 return BGP_ATTR_PARSE_PROCEED
;
1563 /* New Aggregator attribute */
1564 static bgp_attr_parse_ret_t
1565 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1566 as_t
*as4_aggregator_as
,
1567 struct in_addr
*as4_aggregator_addr
)
1569 struct peer
*const peer
= args
->peer
;
1570 struct attr
*const attr
= args
->attr
;
1571 const bgp_size_t length
= args
->length
;
1574 zlog_err("New Aggregator length is not 8 [%d]", length
);
1575 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1579 *as4_aggregator_as
= stream_getl(peer
->ibuf
);
1580 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->ibuf
);
1582 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1584 return BGP_ATTR_PARSE_PROCEED
;
1587 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1589 static bgp_attr_parse_ret_t
1590 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1591 struct aspath
*as4_path
, as_t as4_aggregator
,
1592 struct in_addr
*as4_aggregator_addr
)
1594 int ignore_as4_path
= 0;
1595 struct aspath
*newpath
;
1596 struct attr_extra
*attre
= attr
->extra
;
1598 if (!attr
->aspath
) {
1599 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1601 * checked that all well-known, mandatory attributes were
1604 * Can only be a problem with peer itself - hard error
1606 return BGP_ATTR_PARSE_ERROR
;
1609 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1610 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1612 * It is worth a warning though, because the peer really
1613 * should not send them
1615 if (BGP_DEBUG(as4
, AS4
)) {
1616 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1617 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1618 "AS4 capable peer, yet it sent");
1621 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1622 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1624 "AS4 capable peer, yet it sent");
1627 return BGP_ATTR_PARSE_PROCEED
;
1630 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1631 * because that may override AS4_PATH
1633 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1634 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1638 * if the as_number in aggregator is not AS_TRANS,
1639 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1640 * and the Aggregator shall be taken as
1641 * info on the aggregating node, and the AS_PATH
1642 * shall be taken as the AS_PATH
1644 * the Aggregator shall be ignored and the
1645 * AS4_AGGREGATOR shall be taken as the
1646 * Aggregating node and the AS_PATH is to be
1647 * constructed "as in all other cases"
1649 if (attre
->aggregator_as
!= BGP_AS_TRANS
) {
1651 if (BGP_DEBUG(as4
, AS4
))
1653 "[AS4] %s BGP not AS4 capable peer"
1654 " send AGGREGATOR != AS_TRANS and"
1655 " AS4_AGGREGATOR, so ignore"
1656 " AS4_AGGREGATOR and AS4_PATH",
1658 ignore_as4_path
= 1;
1660 /* "New_aggregator shall be taken as aggregator"
1662 attre
->aggregator_as
= as4_aggregator
;
1663 attre
->aggregator_addr
.s_addr
=
1664 as4_aggregator_addr
->s_addr
;
1667 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1668 * That is bogus - but reading the conditions
1669 * we have to handle AS4_AGGREGATOR as if it were
1670 * AGGREGATOR in that case
1672 if (BGP_DEBUG(as4
, AS4
))
1674 "[AS4] %s BGP not AS4 capable peer send"
1675 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1676 " it as if AGGREGATOR with AS_TRANS had been there",
1678 (attre
= bgp_attr_extra_get(attr
))->aggregator_as
=
1680 /* sweep it under the carpet and simulate a "good"
1682 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1686 /* need to reconcile NEW_AS_PATH and AS_PATH */
1687 if (!ignore_as4_path
1688 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1689 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1690 aspath_unintern(&attr
->aspath
);
1691 attr
->aspath
= aspath_intern(newpath
);
1693 return BGP_ATTR_PARSE_PROCEED
;
1696 /* Community attribute. */
1697 static bgp_attr_parse_ret_t
1698 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1700 struct peer
*const peer
= args
->peer
;
1701 struct attr
*const attr
= args
->attr
;
1702 const bgp_size_t length
= args
->length
;
1705 attr
->community
= NULL
;
1706 return BGP_ATTR_PARSE_PROCEED
;
1710 community_parse((u_int32_t
*)stream_pnt(peer
->ibuf
), length
);
1712 /* XXX: fix community_parse to use stream API and remove this */
1713 stream_forward_getp(peer
->ibuf
, length
);
1715 if (!attr
->community
)
1716 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1719 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1721 return BGP_ATTR_PARSE_PROCEED
;
1724 /* Originator ID attribute. */
1725 static bgp_attr_parse_ret_t
1726 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1728 struct peer
*const peer
= args
->peer
;
1729 struct attr
*const attr
= args
->attr
;
1730 const bgp_size_t length
= args
->length
;
1734 zlog_err("Bad originator ID length %d", length
);
1736 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1740 (bgp_attr_extra_get(attr
))->originator_id
.s_addr
=
1741 stream_get_ipv4(peer
->ibuf
);
1743 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1745 return BGP_ATTR_PARSE_PROCEED
;
1748 /* Cluster list attribute. */
1749 static bgp_attr_parse_ret_t
1750 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1752 struct peer
*const peer
= args
->peer
;
1753 struct attr
*const attr
= args
->attr
;
1754 const bgp_size_t length
= args
->length
;
1758 zlog_err("Bad cluster list length %d", length
);
1760 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1764 (bgp_attr_extra_get(attr
))->cluster
=
1765 cluster_parse((struct in_addr
*)stream_pnt(peer
->ibuf
), length
);
1767 /* XXX: Fix cluster_parse to use stream API and then remove this */
1768 stream_forward_getp(peer
->ibuf
, length
);
1770 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1772 return BGP_ATTR_PARSE_PROCEED
;
1775 /* Multiprotocol reachability information parse. */
1776 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1777 struct bgp_nlri
*mp_update
)
1781 safi_t pkt_safi
, safi
;
1782 bgp_size_t nlri_len
;
1785 struct peer
*const peer
= args
->peer
;
1786 struct attr
*const attr
= args
->attr
;
1787 const bgp_size_t length
= args
->length
;
1788 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1790 /* Set end of packet. */
1791 s
= BGP_INPUT(peer
);
1792 start
= stream_get_getp(s
);
1794 /* safe to read statically sized header? */
1795 #define BGP_MP_REACH_MIN_SIZE 5
1796 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1797 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1798 zlog_info("%s: %s sent invalid length, %lu", __func__
,
1799 peer
->host
, (unsigned long)length
);
1800 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1803 /* Load AFI, SAFI. */
1804 pkt_afi
= stream_getw(s
);
1805 pkt_safi
= stream_getc(s
);
1807 /* Convert AFI, SAFI to internal values, check. */
1808 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1809 /* Log if AFI or SAFI is unrecognized. This is not an error
1811 * the attribute is otherwise malformed.
1813 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1815 "%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1816 peer
->host
, pkt_afi
, pkt_safi
);
1817 return BGP_ATTR_PARSE_ERROR
;
1820 /* Get nexthop length. */
1821 attre
->mp_nexthop_len
= stream_getc(s
);
1823 if (LEN_LEFT
< attre
->mp_nexthop_len
) {
1825 "%s: %s, MP nexthop length, %u, goes past end of attribute",
1826 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1827 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1830 /* Nexthop length check. */
1831 switch (attre
->mp_nexthop_len
) {
1832 case BGP_ATTR_NHLEN_IPV4
:
1833 stream_get(&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1834 /* Probably needed for RFC 2283 */
1835 if (attr
->nexthop
.s_addr
== 0)
1836 memcpy(&attr
->nexthop
.s_addr
,
1837 &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1839 case BGP_ATTR_NHLEN_VPNV4
:
1840 stream_getl(s
); /* RD high */
1841 stream_getl(s
); /* RD low */
1842 stream_get(&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1844 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1845 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1846 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1847 stream_getl(s
); /* RD high */
1848 stream_getl(s
); /* RD low */
1850 stream_get(&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1852 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1853 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1854 if (attre
->mp_nexthop_len
1855 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1856 stream_getl(s
); /* RD high */
1857 stream_getl(s
); /* RD low */
1859 stream_get(&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1860 if (attre
->mp_nexthop_len
1861 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1862 stream_getl(s
); /* RD high */
1863 stream_getl(s
); /* RD low */
1865 stream_get(&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1866 if (!IN6_IS_ADDR_LINKLOCAL(&attre
->mp_nexthop_local
)) {
1867 char buf1
[INET6_ADDRSTRLEN
];
1868 char buf2
[INET6_ADDRSTRLEN
];
1870 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1872 "%s rcvd nexthops %s, %s -- ignoring non-LL value",
1875 &attre
->mp_nexthop_global
,
1876 buf1
, INET6_ADDRSTRLEN
),
1878 &attre
->mp_nexthop_local
,
1879 buf2
, INET6_ADDRSTRLEN
));
1881 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1885 zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
1886 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1887 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1891 zlog_info("%s: (%s) Failed to read SNPA and NLRI(s)", __func__
,
1893 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1898 if ((val
= stream_getc(s
)))
1900 "%s sent non-zero value, %u, for defunct SNPA-length field",
1904 /* must have nrli_len, what is left of the attribute */
1905 nlri_len
= LEN_LEFT
;
1906 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
))) {
1907 zlog_info("%s: (%s) Failed to read NLRI", __func__
, peer
->host
);
1908 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1911 mp_update
->afi
= afi
;
1912 mp_update
->safi
= safi
;
1913 mp_update
->nlri
= stream_pnt(s
);
1914 mp_update
->length
= nlri_len
;
1916 stream_forward_getp(s
, nlri_len
);
1918 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
1920 return BGP_ATTR_PARSE_PROCEED
;
1924 /* Multiprotocol unreachable parse */
1925 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
1926 struct bgp_nlri
*mp_withdraw
)
1931 safi_t pkt_safi
, safi
;
1932 u_int16_t withdraw_len
;
1933 struct peer
*const peer
= args
->peer
;
1934 struct attr
*const attr
= args
->attr
;
1935 const bgp_size_t length
= args
->length
;
1939 #define BGP_MP_UNREACH_MIN_SIZE 3
1940 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1941 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1943 pkt_afi
= stream_getw(s
);
1944 pkt_safi
= stream_getc(s
);
1946 /* Convert AFI, SAFI to internal values, check. */
1947 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1948 /* Log if AFI or SAFI is unrecognized. This is not an error
1950 * the attribute is otherwise malformed.
1952 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1954 "%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
1955 peer
->host
, pkt_afi
, pkt_safi
);
1956 return BGP_ATTR_PARSE_ERROR
;
1959 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1961 mp_withdraw
->afi
= afi
;
1962 mp_withdraw
->safi
= safi
;
1963 mp_withdraw
->nlri
= stream_pnt(s
);
1964 mp_withdraw
->length
= withdraw_len
;
1966 stream_forward_getp(s
, withdraw_len
);
1968 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
1970 return BGP_ATTR_PARSE_PROCEED
;
1973 /* Large Community attribute. */
1974 static bgp_attr_parse_ret_t
1975 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
1977 struct peer
*const peer
= args
->peer
;
1978 struct attr
*const attr
= args
->attr
;
1979 const bgp_size_t length
= args
->length
;
1982 * Large community follows new attribute format.
1986 attr
->extra
->lcommunity
= NULL
;
1987 /* Empty extcomm doesn't seem to be invalid per se */
1988 return BGP_ATTR_PARSE_PROCEED
;
1991 (bgp_attr_extra_get(attr
))->lcommunity
=
1992 lcommunity_parse((u_int8_t
*)stream_pnt(peer
->ibuf
), length
);
1993 /* XXX: fix ecommunity_parse to use stream API */
1994 stream_forward_getp(peer
->ibuf
, length
);
1996 if (attr
->extra
&& !attr
->extra
->lcommunity
)
1997 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2000 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2002 return BGP_ATTR_PARSE_PROCEED
;
2005 /* Extended Community attribute. */
2006 static bgp_attr_parse_ret_t
2007 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2009 struct peer
*const peer
= args
->peer
;
2010 struct attr
*const attr
= args
->attr
;
2011 const bgp_size_t length
= args
->length
;
2015 attr
->extra
->ecommunity
= NULL
;
2016 /* Empty extcomm doesn't seem to be invalid per se */
2017 return BGP_ATTR_PARSE_PROCEED
;
2020 (bgp_attr_extra_get(attr
))->ecommunity
=
2021 ecommunity_parse((u_int8_t
*)stream_pnt(peer
->ibuf
), length
);
2022 /* XXX: fix ecommunity_parse to use stream API */
2023 stream_forward_getp(peer
->ibuf
, length
);
2025 if (attr
->extra
&& !attr
->extra
->ecommunity
)
2026 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2029 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2031 return BGP_ATTR_PARSE_PROCEED
;
2034 /* Parse Tunnel Encap attribute in an UPDATE */
2035 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2036 bgp_size_t length
, /* IN: attr's length field */
2037 struct attr
*attr
, /* IN: caller already allocated */
2038 u_char flag
, /* IN: attr's flags field */
2042 struct attr_extra
*attre
= NULL
;
2043 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2044 uint16_t tunneltype
= 0;
2046 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2048 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2049 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2051 "Tunnel Encap attribute flag isn't optional and transitive %d",
2053 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2054 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2059 if (BGP_ATTR_ENCAP
== type
) {
2060 /* read outer TLV type and length */
2061 uint16_t tlv_length
;
2065 "Tunnel Encap attribute not long enough to contain outer T,L");
2066 bgp_notify_send_with_data(
2067 peer
, BGP_NOTIFY_UPDATE_ERR
,
2068 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2071 tunneltype
= stream_getw(BGP_INPUT(peer
));
2072 tlv_length
= stream_getw(BGP_INPUT(peer
));
2075 if (tlv_length
!= length
) {
2076 zlog_info("%s: tlv_length(%d) != length(%d)", __func__
,
2077 tlv_length
, length
);
2081 while (length
>= 4) {
2082 uint16_t subtype
= 0;
2083 uint16_t sublength
= 0;
2084 struct bgp_attr_encap_subtlv
*tlv
;
2086 if (BGP_ATTR_ENCAP
== type
) {
2087 subtype
= stream_getc(BGP_INPUT(peer
));
2088 sublength
= stream_getc(BGP_INPUT(peer
));
2092 subtype
= stream_getw(BGP_INPUT(peer
));
2093 sublength
= stream_getw(BGP_INPUT(peer
));
2098 if (sublength
> length
) {
2100 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2102 bgp_notify_send_with_data(
2103 peer
, BGP_NOTIFY_UPDATE_ERR
,
2104 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2108 /* alloc and copy sub-tlv */
2109 /* TBD make sure these are freed when attributes are released */
2110 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2111 sizeof(struct bgp_attr_encap_subtlv
) - 1
2113 tlv
->type
= subtype
;
2114 tlv
->length
= sublength
;
2115 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2116 length
-= sublength
;
2118 /* attach tlv to encap chain */
2120 attre
= bgp_attr_extra_get(attr
);
2121 if (BGP_ATTR_ENCAP
== type
) {
2122 for (stlv_last
= attre
->encap_subtlvs
;
2123 stlv_last
&& stlv_last
->next
;
2124 stlv_last
= stlv_last
->next
)
2127 stlv_last
->next
= tlv
;
2129 attre
->encap_subtlvs
= tlv
;
2133 for (stlv_last
= attre
->vnc_subtlvs
;
2134 stlv_last
&& stlv_last
->next
;
2135 stlv_last
= stlv_last
->next
)
2138 stlv_last
->next
= tlv
;
2140 attre
->vnc_subtlvs
= tlv
;
2145 stlv_last
->next
= tlv
;
2150 if (BGP_ATTR_ENCAP
== type
) {
2152 attre
= bgp_attr_extra_get(attr
);
2153 attre
->encap_tunneltype
= tunneltype
;
2157 /* spurious leftover data */
2159 "Tunnel Encap attribute length is bad: %d leftover octets",
2161 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2162 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2170 /* BGP unknown attribute treatment. */
2171 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2173 bgp_size_t total
= args
->total
;
2174 struct transit
*transit
;
2175 struct attr_extra
*attre
;
2176 struct peer
*const peer
= args
->peer
;
2177 struct attr
*const attr
= args
->attr
;
2178 u_char
*const startp
= args
->startp
;
2179 const u_char type
= args
->type
;
2180 const u_char flag
= args
->flags
;
2181 const bgp_size_t length
= args
->length
;
2183 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2185 "%s Unknown attribute is received (type %d, length %d)",
2186 peer
->host
, type
, length
);
2188 /* Forward read pointer of input stream. */
2189 stream_forward_getp(peer
->ibuf
, length
);
2191 /* If any of the mandatory well-known attributes are not recognized,
2192 then the Error Subcode is set to Unrecognized Well-known
2193 Attribute. The Data field contains the unrecognized attribute
2194 (type, length and value). */
2195 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2196 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2200 /* Unrecognized non-transitive optional attributes must be quietly
2201 ignored and not passed along to other BGP peers. */
2202 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2203 return BGP_ATTR_PARSE_PROCEED
;
2205 /* If a path with recognized transitive optional attribute is
2206 accepted and passed along to other BGP peers and the Partial bit
2207 in the Attribute Flags octet is set to 1 by some previous AS, it
2208 is not set back to 0 by the current AS. */
2209 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2211 /* Store transitive attribute to the end of attr->transit. */
2212 if (!((attre
= bgp_attr_extra_get(attr
))->transit
))
2213 attre
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2215 transit
= attre
->transit
;
2218 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2219 transit
->length
+ total
);
2221 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2223 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2224 transit
->length
+= total
;
2226 return BGP_ATTR_PARSE_PROCEED
;
2229 /* Well-known attribute check. */
2230 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2234 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2236 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2237 return BGP_ATTR_PARSE_PROCEED
;
2239 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2240 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2241 are present, it should. Check for any other attribute being present
2244 if (attr
->flag
== ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))
2245 return BGP_ATTR_PARSE_PROCEED
;
2247 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2248 type
= BGP_ATTR_ORIGIN
;
2250 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2251 type
= BGP_ATTR_AS_PATH
;
2253 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2255 * NLRI is empty. We can't easily check NLRI empty here though.
2257 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2258 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2259 type
= BGP_ATTR_NEXT_HOP
;
2261 if (peer
->sort
== BGP_PEER_IBGP
2262 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2263 type
= BGP_ATTR_LOCAL_PREF
;
2266 zlog_warn("%s Missing well-known attribute %s.", peer
->host
,
2267 lookup_msg(attr_str
, type
, NULL
));
2268 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2269 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2271 return BGP_ATTR_PARSE_ERROR
;
2273 return BGP_ATTR_PARSE_PROCEED
;
2276 /* Read attribute of update packet. This function is called from
2277 bgp_update_receive() in bgp_packet.c. */
2278 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2279 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2280 struct bgp_nlri
*mp_withdraw
)
2286 u_char
*startp
, *endp
;
2288 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2289 /* we need the as4_path only until we have synthesized the as_path with
2291 /* same goes for as4_aggregator */
2292 struct aspath
*as4_path
= NULL
;
2293 as_t as4_aggregator
= 0;
2294 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2296 /* Initialize bitmap. */
2297 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2299 /* End pointer of BGP attribute. */
2300 endp
= BGP_INPUT_PNT(peer
) + size
;
2302 /* Get attributes to the end of attribute length. */
2303 while (BGP_INPUT_PNT(peer
) < endp
) {
2304 /* Check remaining length check.*/
2305 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2306 /* XXX warning: long int format, int arg (arg 5) */
2308 "%s: error BGP attribute length %lu is smaller than min len",
2310 (unsigned long)(endp
2311 - STREAM_PNT(BGP_INPUT(peer
))));
2313 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2314 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2315 return BGP_ATTR_PARSE_ERROR
;
2318 /* Fetch attribute flag and type. */
2319 startp
= BGP_INPUT_PNT(peer
);
2320 /* "The lower-order four bits of the Attribute Flags octet are
2321 unused. They MUST be zero when sent and MUST be ignored when
2323 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2324 type
= stream_getc(BGP_INPUT(peer
));
2326 /* Check whether Extended-Length applies and is in bounds */
2327 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2328 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2330 "%s: Extended length set, but just %lu bytes of attr header",
2332 (unsigned long)(endp
2333 - STREAM_PNT(BGP_INPUT(peer
))));
2335 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2336 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2337 return BGP_ATTR_PARSE_ERROR
;
2340 /* Check extended attribue length bit. */
2341 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2342 length
= stream_getw(BGP_INPUT(peer
));
2344 length
= stream_getc(BGP_INPUT(peer
));
2346 /* If any attribute appears more than once in the UPDATE
2347 message, then the Error Subcode is set to Malformed Attribute
2350 if (CHECK_BITMAP(seen
, type
)) {
2352 "%s: error BGP attribute type %d appears twice in a message",
2355 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2356 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2357 return BGP_ATTR_PARSE_ERROR
;
2360 /* Set type to bitmap to check duplicate attribute. `type' is
2361 unsigned char so it never overflow bitmap range. */
2363 SET_BITMAP(seen
, type
);
2365 /* Overflow check. */
2366 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2368 if (attr_endp
> endp
) {
2370 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2371 peer
->host
, type
, length
, size
, attr_endp
,
2373 bgp_notify_send_with_data(
2374 peer
, BGP_NOTIFY_UPDATE_ERR
,
2375 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, startp
,
2376 attr_endp
- startp
);
2377 return BGP_ATTR_PARSE_ERROR
;
2380 struct bgp_attr_parser_args attr_args
= {
2387 .total
= attr_endp
- startp
,
2391 /* If any recognized attribute has Attribute Flags that conflict
2392 with the Attribute Type Code, then the Error Subcode is set
2394 Attribute Flags Error. The Data field contains the erroneous
2395 attribute (type, length and value). */
2396 if (bgp_attr_flag_invalid(&attr_args
)) {
2397 bgp_attr_parse_ret_t ret
;
2398 ret
= bgp_attr_malformed(
2399 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2401 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2406 /* OK check attribute and store it's value. */
2408 case BGP_ATTR_ORIGIN
:
2409 ret
= bgp_attr_origin(&attr_args
);
2411 case BGP_ATTR_AS_PATH
:
2412 ret
= bgp_attr_aspath(&attr_args
);
2414 case BGP_ATTR_AS4_PATH
:
2415 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2417 case BGP_ATTR_NEXT_HOP
:
2418 ret
= bgp_attr_nexthop(&attr_args
);
2420 case BGP_ATTR_MULTI_EXIT_DISC
:
2421 ret
= bgp_attr_med(&attr_args
);
2423 case BGP_ATTR_LOCAL_PREF
:
2424 ret
= bgp_attr_local_pref(&attr_args
);
2426 case BGP_ATTR_ATOMIC_AGGREGATE
:
2427 ret
= bgp_attr_atomic(&attr_args
);
2429 case BGP_ATTR_AGGREGATOR
:
2430 ret
= bgp_attr_aggregator(&attr_args
);
2432 case BGP_ATTR_AS4_AGGREGATOR
:
2433 ret
= bgp_attr_as4_aggregator(&attr_args
,
2435 &as4_aggregator_addr
);
2437 case BGP_ATTR_COMMUNITIES
:
2438 ret
= bgp_attr_community(&attr_args
);
2440 case BGP_ATTR_LARGE_COMMUNITIES
:
2441 ret
= bgp_attr_large_community(&attr_args
);
2443 case BGP_ATTR_ORIGINATOR_ID
:
2444 ret
= bgp_attr_originator_id(&attr_args
);
2446 case BGP_ATTR_CLUSTER_LIST
:
2447 ret
= bgp_attr_cluster_list(&attr_args
);
2449 case BGP_ATTR_MP_REACH_NLRI
:
2450 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2452 case BGP_ATTR_MP_UNREACH_NLRI
:
2453 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2455 case BGP_ATTR_EXT_COMMUNITIES
:
2456 ret
= bgp_attr_ext_communities(&attr_args
);
2461 case BGP_ATTR_ENCAP
:
2462 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
2466 ret
= bgp_attr_unknown(&attr_args
);
2470 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
2471 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2472 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2473 ret
= BGP_ATTR_PARSE_ERROR
;
2476 /* If hard error occured immediately return to the caller. */
2477 if (ret
== BGP_ATTR_PARSE_ERROR
) {
2478 zlog_warn("%s: Attribute %s, parse error", peer
->host
,
2479 lookup_msg(attr_str
, type
, NULL
));
2481 aspath_unintern(&as4_path
);
2484 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
2487 "%s: Attribute %s, parse error - treating as withdrawal",
2488 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2490 aspath_unintern(&as4_path
);
2494 /* Check the fetched length. */
2495 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
2496 zlog_warn("%s: BGP attribute %s, fetch error",
2497 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2498 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2499 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2501 aspath_unintern(&as4_path
);
2502 return BGP_ATTR_PARSE_ERROR
;
2506 /* Check final read pointer is same as end pointer. */
2507 if (BGP_INPUT_PNT(peer
) != endp
) {
2508 zlog_warn("%s: BGP attribute %s, length mismatch", peer
->host
,
2509 lookup_msg(attr_str
, type
, NULL
));
2510 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2511 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2513 aspath_unintern(&as4_path
);
2514 return BGP_ATTR_PARSE_ERROR
;
2517 /* Check all mandatory well-known attributes are present */
2519 bgp_attr_parse_ret_t ret
;
2520 if ((ret
= bgp_attr_check(peer
, attr
)) < 0) {
2522 aspath_unintern(&as4_path
);
2528 * At this place we can see whether we got AS4_PATH and/or
2529 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2530 * We can not do this before we've read all attributes because
2531 * the as4 handling does not say whether AS4_PATH has to be sent
2532 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2533 * in relationship to AGGREGATOR.
2534 * So, to be defensive, we are not relying on any order and read
2535 * all attributes first, including these 32bit ones, and now,
2536 * afterwards, we look what and if something is to be done for as4.
2538 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2541 /* actually... this doesn't ever return failure currently, but
2542 * better safe than sorry */
2543 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
2544 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
2545 &as4_aggregator_addr
)) {
2546 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2547 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2549 aspath_unintern(&as4_path
);
2550 return BGP_ATTR_PARSE_ERROR
;
2553 /* At this stage, we have done all fiddling with as4, and the
2554 * resulting info is in attr->aggregator resp. attr->aspath
2555 * so we can chuck as4_aggregator and as4_path alltogether in
2556 * order to save memory
2559 aspath_unintern(&as4_path
); /* unintern - it is in the hash */
2560 /* The flag that we got this is still there, but that does not
2565 * The "rest" of the code does nothing with as4_aggregator.
2566 * there is no memory attached specifically which is not part
2568 * so ignoring just means do nothing.
2571 * Finally do the checks on the aspath we did not do yet
2572 * because we waited for a potentially synthesized aspath.
2574 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
2575 ret
= bgp_attr_aspath_check(peer
, attr
);
2576 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2580 /* Finally intern unknown attribute. */
2581 if (attr
->extra
->transit
)
2582 attr
->extra
->transit
=
2583 transit_intern(attr
->extra
->transit
);
2584 if (attr
->extra
->encap_subtlvs
)
2585 attr
->extra
->encap_subtlvs
= encap_intern(
2586 attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2588 if (attr
->extra
->vnc_subtlvs
)
2589 attr
->extra
->vnc_subtlvs
= encap_intern(
2590 attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2594 return BGP_ATTR_PARSE_PROCEED
;
2597 size_t bgp_packet_mpattr_start(struct stream
*s
, afi_t afi
, safi_t safi
,
2599 struct bpacket_attr_vec_arr
*vecarr
,
2606 /* Set extended bit always to encode the attribute length as 2 bytes */
2607 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
2608 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2609 sizep
= stream_get_endp(s
);
2610 stream_putw(s
, 0); /* Marker: Attribute length. */
2613 /* Convert AFI, SAFI to values for packet. */
2614 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
2616 stream_putw(s
, pkt_afi
); /* AFI */
2617 stream_putc(s
, pkt_safi
); /* SAFI */
2618 if (afi
== AFI_L2VPN
)
2620 else if (nh_afi
== AFI_MAX
)
2622 BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->extra
->mp_nexthop_len
);
2624 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2629 case SAFI_MULTICAST
:
2630 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
2633 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2637 stream_putl(s
, 0); /* RD = 0, per RFC */
2639 stream_put(s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2643 stream_put(s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2652 case SAFI_MULTICAST
: {
2653 struct attr_extra
*attre
= attr
->extra
;
2655 assert(attr
->extra
);
2656 stream_putc(s
, attre
->mp_nexthop_len
);
2657 stream_put(s
, &attre
->mp_nexthop_global
,
2659 if (attre
->mp_nexthop_len
2660 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2661 stream_put(s
, &attre
->mp_nexthop_local
,
2664 case SAFI_MPLS_VPN
: {
2665 struct attr_extra
*attre
= attr
->extra
;
2667 assert(attr
->extra
);
2668 if (attre
->mp_nexthop_len
2669 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2671 stream_putl(s
, 0); /* RD = 0, per RFC */
2673 stream_put(s
, &attre
->mp_nexthop_global
,
2675 } else if (attre
->mp_nexthop_len
2676 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2678 stream_putl(s
, 0); /* RD = 0, per RFC */
2680 stream_put(s
, &attre
->mp_nexthop_global
,
2682 stream_putl(s
, 0); /* RD = 0, per RFC */
2684 stream_put(s
, &attre
->mp_nexthop_local
,
2689 assert(attr
->extra
);
2690 stream_putc(s
, IPV6_MAX_BYTELEN
);
2691 stream_put(s
, &attr
->extra
->mp_nexthop_global
,
2701 if (attr
->extra
->mp_nexthop_len
2702 == BGP_ATTR_NHLEN_VPNV4
) {
2704 stream_putl(s
, 0); /* RD = 0, per RFC */
2707 &attr
->extra
->mp_nexthop_global_in
,
2709 } else if (attr
->extra
->mp_nexthop_len
2710 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2712 stream_putl(s
, 0); /* RD = 0, per RFC */
2714 stream_put(s
, &attr
->extra
->mp_nexthop_global
,
2716 } else if (attr
->extra
->mp_nexthop_len
2717 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2719 stream_putl(s
, 0); /* RD = 0, per RFC */
2721 stream_put(s
, &attr
->extra
->mp_nexthop_global
,
2723 stream_putl(s
, 0); /* RD = 0, per RFC */
2725 stream_put(s
, &attr
->extra
->mp_nexthop_local
,
2742 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
2743 struct prefix
*p
, struct prefix_rd
*prd
,
2744 u_char
*tag
, int addpath_encode
,
2745 u_int32_t addpath_tx_id
, struct attr
*attr
)
2747 if (safi
== SAFI_MPLS_VPN
) {
2749 stream_putl(s
, addpath_tx_id
);
2750 /* Tag, RD, Prefix write. */
2751 stream_putc(s
, p
->prefixlen
+ 88);
2752 stream_put(s
, tag
, 3);
2753 stream_put(s
, prd
->val
, 8);
2754 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
2755 } else if (safi
== SAFI_EVPN
) {
2756 bgp_packet_mpattr_route_type_5(s
, p
, prd
, tag
, attr
);
2758 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
2761 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
2763 int size
= PSIZE(p
->prefixlen
);
2764 if (safi
== SAFI_MPLS_VPN
)
2770 * Encodes the tunnel encapsulation attribute,
2771 * and with ENABLE_BGP_VNC the VNC attribute which uses
2772 * almost the same TLV format
2774 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
2775 struct stream
*s
, struct attr
*attr
,
2778 unsigned int attrlenfield
= 0;
2779 unsigned int attrhdrlen
= 0;
2780 struct bgp_attr_encap_subtlv
*subtlvs
;
2781 struct bgp_attr_encap_subtlv
*st
;
2782 const char *attrname
;
2784 if (!attr
|| !attr
->extra
2785 || (attrtype
== BGP_ATTR_ENCAP
2786 && (!attr
->extra
->encap_tunneltype
2787 || attr
->extra
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
2791 case BGP_ATTR_ENCAP
:
2792 attrname
= "Tunnel Encap";
2793 subtlvs
= attr
->extra
->encap_subtlvs
;
2794 if (subtlvs
== NULL
) /* nothing to do */
2797 * The tunnel encap attr has an "outer" tlv.
2799 * L = total length of subtlvs,
2800 * V = concatenated subtlvs.
2802 attrlenfield
= 2 + 2; /* T + L */
2803 attrhdrlen
= 1 + 1; /* subTLV T + L */
2809 subtlvs
= attr
->extra
->vnc_subtlvs
;
2810 if (subtlvs
== NULL
) /* nothing to do */
2812 attrlenfield
= 0; /* no outer T + L */
2813 attrhdrlen
= 2 + 2; /* subTLV T + L */
2821 /* compute attr length */
2822 for (st
= subtlvs
; st
; st
= st
->next
) {
2823 attrlenfield
+= (attrhdrlen
+ st
->length
);
2826 if (attrlenfield
> 0xffff) {
2827 zlog_info("%s attribute is too long (length=%d), can't send it",
2828 attrname
, attrlenfield
);
2832 if (attrlenfield
> 0xff) {
2833 /* 2-octet length field */
2835 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
2836 | BGP_ATTR_FLAG_EXTLEN
);
2837 stream_putc(s
, attrtype
);
2838 stream_putw(s
, attrlenfield
& 0xffff);
2840 /* 1-octet length field */
2841 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
2842 stream_putc(s
, attrtype
);
2843 stream_putc(s
, attrlenfield
& 0xff);
2846 if (attrtype
== BGP_ATTR_ENCAP
) {
2847 /* write outer T+L */
2848 stream_putw(s
, attr
->extra
->encap_tunneltype
);
2849 stream_putw(s
, attrlenfield
- 4);
2852 /* write each sub-tlv */
2853 for (st
= subtlvs
; st
; st
= st
->next
) {
2854 if (attrtype
== BGP_ATTR_ENCAP
) {
2855 stream_putc(s
, st
->type
);
2856 stream_putc(s
, st
->length
);
2859 stream_putw(s
, st
->type
);
2860 stream_putw(s
, st
->length
);
2863 stream_put(s
, st
->value
, st
->length
);
2867 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
2869 /* Set MP attribute length. Don't count the (2) bytes used to encode
2871 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
2874 /* Make attribute packet. */
2875 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
2876 struct stream
*s
, struct attr
*attr
,
2877 struct bpacket_attr_vec_arr
*vecarr
,
2878 struct prefix
*p
, afi_t afi
, safi_t safi
,
2879 struct peer
*from
, struct prefix_rd
*prd
,
2880 u_char
*tag
, int addpath_encode
,
2881 u_int32_t addpath_tx_id
)
2884 size_t aspath_sizep
;
2885 struct aspath
*aspath
;
2886 int send_as4_path
= 0;
2887 int send_as4_aggregator
= 0;
2888 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2893 /* Remember current pointer. */
2894 cp
= stream_get_endp(s
);
2897 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
2898 && !peer_cap_enhe(peer
))) {
2899 size_t mpattrlen_pos
= 0;
2901 mpattrlen_pos
= bgp_packet_mpattr_start(
2903 (peer_cap_enhe(peer
) ? AFI_IP6
2904 : AFI_MAX
), /* get from NH */
2906 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
2907 addpath_encode
, addpath_tx_id
, attr
);
2908 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2911 /* Origin attribute. */
2912 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
2913 stream_putc(s
, BGP_ATTR_ORIGIN
);
2915 stream_putc(s
, attr
->origin
);
2917 /* AS path attribute. */
2919 /* If remote-peer is EBGP */
2920 if (peer
->sort
== BGP_PEER_EBGP
2921 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2922 PEER_FLAG_AS_PATH_UNCHANGED
)
2923 || attr
->aspath
->segments
== NULL
)
2924 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2925 PEER_FLAG_RSERVER_CLIENT
))) {
2926 aspath
= aspath_dup(attr
->aspath
);
2928 /* Even though we may not be configured for confederations we
2930 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2931 aspath
= aspath_delete_confed_seq(aspath
);
2933 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2934 /* Stuff our path CONFED_ID on the front */
2935 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
2937 if (peer
->change_local_as
) {
2938 /* If replace-as is specified, we only use the
2939 change_local_as when
2940 advertising routes. */
2943 PEER_FLAG_LOCAL_AS_REPLACE_AS
)) {
2944 aspath
= aspath_add_seq(aspath
,
2947 aspath
= aspath_add_seq(aspath
,
2948 peer
->change_local_as
);
2950 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
2953 } else if (peer
->sort
== BGP_PEER_CONFED
) {
2954 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
2956 aspath
= aspath_dup(attr
->aspath
);
2957 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
2959 aspath
= attr
->aspath
;
2961 /* If peer is not AS4 capable, then:
2962 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2963 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
2965 * types are in it (i.e. exclude them if they are there)
2966 * AND do this only if there is at least one asnum > 65535 in the
2968 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
2970 * all ASnums > 65535 to BGP_AS_TRANS
2973 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
2974 stream_putc(s
, BGP_ATTR_AS_PATH
);
2975 aspath_sizep
= stream_get_endp(s
);
2977 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
2979 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2982 if (!use32bit
&& aspath_has_as4(aspath
))
2984 1; /* we'll do this later, at the correct place */
2986 /* Nexthop attribute. */
2987 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
)) {
2988 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2989 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
2990 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
2991 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
2994 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2995 } else if (safi
== SAFI_UNICAST
&& peer_cap_enhe(from
)) {
2997 * Likely this is the case when an IPv4 prefix was
2999 * Extended Next-hop capability and now being advertised
3002 * Setting the mandatory (ipv4) next-hop attribute here
3004 * implicit next-hop self with correct (ipv4 address
3007 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3008 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3009 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3012 stream_put_ipv4(s
, 0);
3016 /* MED attribute. */
3017 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3018 || bgp
->maxmed_active
) {
3019 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3020 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3022 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3026 /* Local preference. */
3027 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3028 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3029 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3031 stream_putl(s
, attr
->local_pref
);
3034 /* Atomic aggregate. */
3035 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3036 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3037 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3042 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3043 assert(attr
->extra
);
3045 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3046 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3047 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3050 /* AS4 capable peer */
3052 stream_putl(s
, attr
->extra
->aggregator_as
);
3054 /* 2-byte AS peer */
3057 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3059 if (attr
->extra
->aggregator_as
> 65535) {
3060 stream_putw(s
, BGP_AS_TRANS
);
3062 /* we have to send AS4_AGGREGATOR, too.
3063 * we'll do that later in order to send
3064 * attributes in ascending
3067 send_as4_aggregator
= 1;
3071 (u_int16_t
)attr
->extra
->aggregator_as
);
3073 stream_put_ipv4(s
, attr
->extra
->aggregator_addr
.s_addr
);
3076 /* Community attribute. */
3077 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3078 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3079 if (attr
->community
->size
* 4 > 255) {
3081 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3082 | BGP_ATTR_FLAG_EXTLEN
);
3083 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3084 stream_putw(s
, attr
->community
->size
* 4);
3087 BGP_ATTR_FLAG_OPTIONAL
3088 | BGP_ATTR_FLAG_TRANS
);
3089 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3090 stream_putc(s
, attr
->community
->size
* 4);
3092 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3096 * Large Community attribute.
3098 if (attr
->extra
&& CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3099 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3100 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3101 if (attr
->extra
->lcommunity
->size
* 12 > 255) {
3103 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3104 | BGP_ATTR_FLAG_EXTLEN
);
3105 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3106 stream_putw(s
, attr
->extra
->lcommunity
->size
* 12);
3109 BGP_ATTR_FLAG_OPTIONAL
3110 | BGP_ATTR_FLAG_TRANS
);
3111 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3112 stream_putc(s
, attr
->extra
->lcommunity
->size
* 12);
3114 stream_put(s
, attr
->extra
->lcommunity
->val
,
3115 attr
->extra
->lcommunity
->size
* 12);
3118 /* Route Reflector. */
3119 if (peer
->sort
== BGP_PEER_IBGP
&& from
3120 && from
->sort
== BGP_PEER_IBGP
) {
3121 /* Originator ID. */
3122 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3123 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3126 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3127 stream_put_in_addr(s
, &attr
->extra
->originator_id
);
3129 stream_put_in_addr(s
, &from
->remote_id
);
3132 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3133 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3135 if (attr
->extra
&& attr
->extra
->cluster
) {
3136 stream_putc(s
, attr
->extra
->cluster
->length
+ 4);
3137 /* If this peer configuration's parent BGP has
3139 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3140 stream_put_in_addr(s
, &bgp
->cluster_id
);
3142 stream_put_in_addr(s
, &bgp
->router_id
);
3143 stream_put(s
, attr
->extra
->cluster
->list
,
3144 attr
->extra
->cluster
->length
);
3147 /* If this peer configuration's parent BGP has
3149 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3150 stream_put_in_addr(s
, &bgp
->cluster_id
);
3152 stream_put_in_addr(s
, &bgp
->router_id
);
3156 /* Extended Communities attribute. */
3157 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3158 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3159 struct attr_extra
*attre
= attr
->extra
;
3163 if (peer
->sort
== BGP_PEER_IBGP
3164 || peer
->sort
== BGP_PEER_CONFED
) {
3165 if (attre
->ecommunity
->size
* 8 > 255) {
3167 BGP_ATTR_FLAG_OPTIONAL
3168 | BGP_ATTR_FLAG_TRANS
3169 | BGP_ATTR_FLAG_EXTLEN
);
3170 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3171 stream_putw(s
, attre
->ecommunity
->size
* 8);
3174 BGP_ATTR_FLAG_OPTIONAL
3175 | BGP_ATTR_FLAG_TRANS
);
3176 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3177 stream_putc(s
, attre
->ecommunity
->size
* 8);
3179 stream_put(s
, attre
->ecommunity
->val
,
3180 attre
->ecommunity
->size
* 8);
3184 int ecom_tr_size
= 0;
3187 for (i
= 0; i
< attre
->ecommunity
->size
; i
++) {
3188 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3191 if (CHECK_FLAG(tbit
,
3192 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3199 if (ecom_tr_size
* 8 > 255) {
3202 BGP_ATTR_FLAG_OPTIONAL
3203 | BGP_ATTR_FLAG_TRANS
3204 | BGP_ATTR_FLAG_EXTLEN
);
3206 BGP_ATTR_EXT_COMMUNITIES
);
3207 stream_putw(s
, ecom_tr_size
* 8);
3211 BGP_ATTR_FLAG_OPTIONAL
3212 | BGP_ATTR_FLAG_TRANS
);
3214 BGP_ATTR_EXT_COMMUNITIES
);
3215 stream_putc(s
, ecom_tr_size
* 8);
3218 for (i
= 0; i
< attre
->ecommunity
->size
; i
++) {
3219 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3224 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3227 stream_put(s
, pnt
, 8);
3233 if (send_as4_path
) {
3234 /* If the peer is NOT As4 capable, AND */
3235 /* there are ASnums > 65535 in path THEN
3236 * give out AS4_PATH */
3238 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3240 * Hm, I wonder... confederation things *should* only be at
3241 * the beginning of an aspath, right? Then we should use
3242 * aspath_delete_confed_seq for this, because it is already
3244 * Folks, talk to me: what is reasonable here!?
3246 aspath
= aspath_delete_confed_seq(aspath
);
3249 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3250 | BGP_ATTR_FLAG_EXTLEN
);
3251 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3252 aspath_sizep
= stream_get_endp(s
);
3254 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3257 if (aspath
!= attr
->aspath
)
3258 aspath_free(aspath
);
3260 if (send_as4_aggregator
) {
3261 assert(attr
->extra
);
3263 /* send AS4_AGGREGATOR, at this place */
3264 /* this section of code moved here in order to ensure the
3266 * *ascending* order of attributes
3268 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3269 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3271 stream_putl(s
, attr
->extra
->aggregator_as
);
3272 stream_put_ipv4(s
, attr
->extra
->aggregator_addr
.s_addr
);
3275 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3276 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3277 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3278 /* Tunnel Encap attribute */
3279 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3283 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3287 /* Unknown transit attribute. */
3288 if (attr
->extra
&& attr
->extra
->transit
)
3289 stream_put(s
, attr
->extra
->transit
->val
,
3290 attr
->extra
->transit
->length
);
3292 /* Return total size of attribute. */
3293 return stream_get_endp(s
) - cp
;
3296 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3298 unsigned long attrlen_pnt
;
3302 /* Set extended bit always to encode the attribute length as 2 bytes */
3303 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3304 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3306 attrlen_pnt
= stream_get_endp(s
);
3307 stream_putw(s
, 0); /* Length of this attribute. */
3309 /* Convert AFI, SAFI to values for packet. */
3310 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3312 stream_putw(s
, pkt_afi
);
3313 stream_putc(s
, pkt_safi
);
3318 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
3319 safi_t safi
, struct prefix_rd
*prd
,
3320 u_char
*tag
, int addpath_encode
,
3321 u_int32_t addpath_tx_id
, struct attr
*attr
)
3323 return bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
3324 addpath_encode
, addpath_tx_id
, attr
);
3327 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
3329 bgp_packet_mpattr_end(s
, attrlen_pnt
);
3332 /* Initialization of attribute. */
3333 void bgp_attr_init(void)
3345 void bgp_attr_finish(void)
3350 ecommunity_finish();
3351 lcommunity_finish();
3357 /* Make attribute packet. */
3358 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
3359 struct prefix
*prefix
)
3364 struct aspath
*aspath
;
3365 int addpath_encode
= 0;
3366 u_int32_t addpath_tx_id
= 0;
3368 /* Remember current pointer. */
3369 cp
= stream_get_endp(s
);
3371 /* Place holder of length. */
3374 /* Origin attribute. */
3375 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3376 stream_putc(s
, BGP_ATTR_ORIGIN
);
3378 stream_putc(s
, attr
->origin
);
3380 aspath
= attr
->aspath
;
3382 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3383 stream_putc(s
, BGP_ATTR_AS_PATH
);
3384 aspath_lenp
= stream_get_endp(s
);
3387 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
3389 /* Nexthop attribute. */
3390 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3391 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
3392 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3393 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3395 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3398 /* MED attribute. */
3399 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
3400 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3401 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3403 stream_putl(s
, attr
->med
);
3406 /* Local preference. */
3407 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
3408 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3409 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3411 stream_putl(s
, attr
->local_pref
);
3414 /* Atomic aggregate. */
3415 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3416 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3417 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3422 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3423 assert(attr
->extra
);
3424 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3425 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3427 stream_putl(s
, attr
->extra
->aggregator_as
);
3428 stream_put_ipv4(s
, attr
->extra
->aggregator_addr
.s_addr
);
3431 /* Community attribute. */
3432 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3433 if (attr
->community
->size
* 4 > 255) {
3435 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3436 | BGP_ATTR_FLAG_EXTLEN
);
3437 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3438 stream_putw(s
, attr
->community
->size
* 4);
3441 BGP_ATTR_FLAG_OPTIONAL
3442 | BGP_ATTR_FLAG_TRANS
);
3443 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3444 stream_putc(s
, attr
->community
->size
* 4);
3446 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3449 /* Large Community attribute. */
3451 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
3452 if (attr
->extra
->lcommunity
->size
* 12 > 255) {
3454 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3455 | BGP_ATTR_FLAG_EXTLEN
);
3456 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3457 stream_putw(s
, attr
->extra
->lcommunity
->size
* 12);
3460 BGP_ATTR_FLAG_OPTIONAL
3461 | BGP_ATTR_FLAG_TRANS
);
3462 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3463 stream_putc(s
, attr
->extra
->lcommunity
->size
* 12);
3466 stream_put(s
, attr
->extra
->lcommunity
->val
,
3467 attr
->extra
->lcommunity
->size
* 12);
3470 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3471 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
3472 && (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
3473 || attr
->extra
->mp_nexthop_len
3474 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
3476 struct attr_extra
*attre
= attr
->extra
;
3478 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3479 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3480 sizep
= stream_get_endp(s
);
3483 stream_putc(s
, 0); /* Marker: Attribute length. */
3484 stream_putw(s
, AFI_IP6
); /* AFI */
3485 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3488 stream_putc(s
, attre
->mp_nexthop_len
);
3489 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3490 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3491 stream_put(s
, &attre
->mp_nexthop_local
,
3498 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
3501 /* Set MP attribute length. */
3502 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
3505 /* Return total size of attribute. */
3506 len
= stream_get_endp(s
) - cp
- 2;
3507 stream_putw_at(s
, cp
, len
);