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
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_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"
54 /* Attribute strings for logging. */
55 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" }
82 static const int attr_str_max
= array_size(attr_str
);
84 static const struct message attr_flag_str
[] =
86 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
87 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
88 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
89 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
90 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
93 static struct hash
*cluster_hash
;
96 cluster_hash_alloc (void *p
)
98 const struct cluster_list
*val
= (const struct cluster_list
*) p
;
99 struct cluster_list
*cluster
;
101 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
102 cluster
->length
= val
->length
;
106 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
107 memcpy (cluster
->list
, val
->list
, val
->length
);
110 cluster
->list
= NULL
;
117 /* Cluster list related functions. */
118 static struct cluster_list
*
119 cluster_parse (struct in_addr
* pnt
, int length
)
121 struct cluster_list tmp
;
122 struct cluster_list
*cluster
;
127 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
133 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
137 for (i
= 0; i
< cluster
->length
/ 4; i
++)
138 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
144 cluster_hash_key_make (void *p
)
146 const struct cluster_list
*cluster
= p
;
148 return jhash(cluster
->list
, cluster
->length
, 0);
152 cluster_hash_cmp (const void *p1
, const void *p2
)
154 const struct cluster_list
* cluster1
= p1
;
155 const struct cluster_list
* cluster2
= p2
;
157 return (cluster1
->length
== cluster2
->length
&&
158 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
162 cluster_free (struct cluster_list
*cluster
)
165 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
166 XFREE (MTYPE_CLUSTER
, cluster
);
169 static struct cluster_list
*
170 cluster_dup (struct cluster_list
*cluster
)
172 struct cluster_list
*new;
174 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
175 new->length
= cluster
->length
;
179 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
180 memcpy (new->list
, cluster
->list
, cluster
->length
);
188 static struct cluster_list
*
189 cluster_intern (struct cluster_list
*cluster
)
191 struct cluster_list
*find
;
193 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
200 cluster_unintern (struct cluster_list
*cluster
)
205 if (cluster
->refcnt
== 0)
207 hash_release (cluster_hash
, cluster
);
208 cluster_free (cluster
);
215 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
219 cluster_finish (void)
221 hash_clean (cluster_hash
, (void (*)(void *))cluster_free
);
222 hash_free (cluster_hash
);
226 static struct hash
*encap_hash
= NULL
;
228 static struct hash
*vnc_hash
= NULL
;
231 struct bgp_attr_encap_subtlv
*
232 encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
234 struct bgp_attr_encap_subtlv
*new;
235 struct bgp_attr_encap_subtlv
*tail
;
236 struct bgp_attr_encap_subtlv
*p
;
238 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
239 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
241 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
244 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
247 memcpy(tail
, p
, size
);
255 encap_free(struct bgp_attr_encap_subtlv
*p
)
257 struct bgp_attr_encap_subtlv
*next
;
261 XFREE(MTYPE_ENCAP_TLV
, p
);
267 bgp_attr_flush_encap(struct attr
*attr
)
269 if (!attr
|| !attr
->extra
)
272 if (attr
->extra
->encap_subtlvs
) {
273 encap_free(attr
->extra
->encap_subtlvs
);
274 attr
->extra
->encap_subtlvs
= NULL
;
277 if (attr
->extra
->vnc_subtlvs
) {
278 encap_free(attr
->extra
->vnc_subtlvs
);
279 attr
->extra
->vnc_subtlvs
= NULL
;
285 * Compare encap sub-tlv chains
290 * This algorithm could be made faster if needed
293 encap_same(struct bgp_attr_encap_subtlv
*h1
, struct bgp_attr_encap_subtlv
*h2
)
295 struct bgp_attr_encap_subtlv
*p
;
296 struct bgp_attr_encap_subtlv
*q
;
300 if (h1
== NULL
|| h2
== NULL
)
303 for (p
= h1
; p
; p
= p
->next
) {
304 for (q
= h2
; q
; q
= q
->next
) {
305 if ((p
->type
== q
->type
) &&
306 (p
->length
== q
->length
) &&
307 !memcmp(p
->value
, q
->value
, p
->length
)) {
316 for (p
= h2
; p
; p
= p
->next
) {
317 for (q
= h1
; q
; q
= q
->next
) {
318 if ((p
->type
== q
->type
) &&
319 (p
->length
== q
->length
) &&
320 !memcmp(p
->value
, q
->value
, p
->length
)) {
333 encap_hash_alloc (void *p
)
335 /* Encap structure is already allocated. */
347 static struct bgp_attr_encap_subtlv
*
348 encap_intern (struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
350 struct bgp_attr_encap_subtlv
*find
;
351 struct hash
*hash
= encap_hash
;
353 if (type
== VNC_SUBTLV_TYPE
)
357 find
= hash_get (hash
, encap
, encap_hash_alloc
);
366 encap_unintern (struct bgp_attr_encap_subtlv
**encapp
, encap_subtlv_type type
)
368 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
372 if (encap
->refcnt
== 0)
374 struct hash
*hash
= encap_hash
;
376 if (type
== VNC_SUBTLV_TYPE
)
379 hash_release (hash
, encap
);
386 encap_hash_key_make (void *p
)
388 const struct bgp_attr_encap_subtlv
* encap
= p
;
390 return jhash(encap
->value
, encap
->length
, 0);
394 encap_hash_cmp (const void *p1
, const void *p2
)
396 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
397 (struct bgp_attr_encap_subtlv
*)p2
);
403 encap_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
405 vnc_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
412 hash_clean (encap_hash
, (void (*)(void *))encap_free
);
413 hash_free (encap_hash
);
416 hash_clean (vnc_hash
, (void (*)(void *))encap_free
);
417 hash_free (vnc_hash
);
422 /* Unknown transit attribute. */
423 static struct hash
*transit_hash
;
426 transit_free (struct transit
*transit
)
429 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
430 XFREE (MTYPE_TRANSIT
, transit
);
433 static struct transit
*
434 transit_dup (struct transit
*transit
)
438 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
439 new->length
= transit
->length
;
442 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
443 memcpy (new->val
, transit
->val
, transit
->length
);
452 transit_hash_alloc (void *p
)
454 /* Transit structure is already allocated. */
458 static struct transit
*
459 transit_intern (struct transit
*transit
)
461 struct transit
*find
;
463 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
465 transit_free (transit
);
472 transit_unintern (struct transit
*transit
)
477 if (transit
->refcnt
== 0)
479 hash_release (transit_hash
, transit
);
480 transit_free (transit
);
485 transit_hash_key_make (void *p
)
487 const struct transit
* transit
= p
;
489 return jhash(transit
->val
, transit
->length
, 0);
493 transit_hash_cmp (const void *p1
, const void *p2
)
495 const struct transit
* transit1
= p1
;
496 const struct transit
* transit2
= p2
;
498 return (transit1
->length
== transit2
->length
&&
499 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
505 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
509 transit_finish (void)
511 hash_clean (transit_hash
, (void (*)(void *))transit_free
);
512 hash_free (transit_hash
);
516 /* Attribute hash routines. */
517 static struct hash
*attrhash
;
519 static struct attr_extra
*
520 bgp_attr_extra_new (void)
522 return XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
526 bgp_attr_extra_free (struct attr
*attr
)
530 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
536 bgp_attr_extra_get (struct attr
*attr
)
539 attr
->extra
= bgp_attr_extra_new();
543 /* Shallow copy of an attribute
544 * Though, not so shallow that it doesn't copy the contents
545 * of the attr_extra pointed to by 'extra'
548 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
550 struct attr_extra
*extra
= new->extra
;
553 /* if caller provided attr_extra space, use it in any case.
555 * This is neccesary even if orig->extra equals NULL, because otherwise
556 * memory may be later allocated on the heap by bgp_attr_extra_get.
558 * That memory would eventually be leaked, because the caller must not
559 * call bgp_attr_extra_free if he provided attr_extra on the stack.
564 memset(new->extra
, 0, sizeof(struct attr_extra
));
566 *new->extra
= *orig
->extra
;
569 else if (orig
->extra
)
571 new->extra
= bgp_attr_extra_new();
572 *new->extra
= *orig
->extra
;
577 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
580 new->aspath
= aspath_dup(orig
->aspath
);
583 new->community
= community_dup(orig
->community
);
587 if (orig
->extra
->ecommunity
)
588 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
589 if (orig
->extra
->cluster
)
590 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
591 if (orig
->extra
->transit
)
592 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
593 if (orig
->extra
->encap_subtlvs
)
594 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
596 if (orig
->extra
->vnc_subtlvs
)
597 new->extra
->vnc_subtlvs
= encap_tlv_dup(orig
->extra
->vnc_subtlvs
);
603 bgp_attr_deep_free (struct attr
*attr
)
606 aspath_free(attr
->aspath
);
609 community_free(attr
->community
);
613 if (attr
->extra
->ecommunity
)
614 ecommunity_free(&attr
->extra
->ecommunity
);
615 if (attr
->extra
->cluster
)
616 cluster_free(attr
->extra
->cluster
);
617 if (attr
->extra
->transit
)
618 transit_free(attr
->extra
->transit
);
619 if (attr
->extra
->encap_subtlvs
)
620 encap_free(attr
->extra
->encap_subtlvs
);
622 if (attr
->extra
->vnc_subtlvs
)
623 encap_free(attr
->extra
->vnc_subtlvs
);
631 return attrhash
->count
;
635 attr_unknown_count (void)
637 return transit_hash
->count
;
641 attrhash_key_make (void *p
)
643 const struct attr
*attr
= (struct attr
*) p
;
644 const struct attr_extra
*extra
= attr
->extra
;
646 #define MIX(val) key = jhash_1word(val, key)
649 MIX(attr
->nexthop
.s_addr
);
651 MIX(attr
->local_pref
);
654 key
+= attr
->nexthop
.s_addr
;
656 key
+= attr
->local_pref
;
660 MIX(extra
->aggregator_as
);
661 MIX(extra
->aggregator_addr
.s_addr
);
663 MIX(extra
->mp_nexthop_global_in
.s_addr
);
664 MIX(extra
->originator_id
.s_addr
);
669 MIX(aspath_key_make (attr
->aspath
));
671 MIX(community_hash_make (attr
->community
));
675 if (extra
->lcommunity
)
676 MIX(lcommunity_hash_make (extra
->lcommunity
));
677 if (extra
->ecommunity
)
678 MIX(ecommunity_hash_make (extra
->ecommunity
));
680 MIX(cluster_hash_key_make (extra
->cluster
));
682 MIX(transit_hash_key_make (extra
->transit
));
683 if (extra
->encap_subtlvs
)
684 MIX(encap_hash_key_make (extra
->encap_subtlvs
));
686 if (extra
->vnc_subtlvs
)
687 MIX(encap_hash_key_make (extra
->vnc_subtlvs
));
689 MIX(extra
->mp_nexthop_len
);
690 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
691 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
698 attrhash_cmp (const void *p1
, const void *p2
)
700 const struct attr
* attr1
= p1
;
701 const struct attr
* attr2
= p2
;
703 if (attr1
->flag
== attr2
->flag
704 && attr1
->origin
== attr2
->origin
705 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
706 && attr1
->aspath
== attr2
->aspath
707 && attr1
->community
== attr2
->community
708 && attr1
->med
== attr2
->med
709 && attr1
->local_pref
== attr2
->local_pref
710 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
712 const struct attr_extra
*ae1
= attr1
->extra
;
713 const struct attr_extra
*ae2
= attr2
->extra
;
716 && ae1
->aggregator_as
== ae2
->aggregator_as
717 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
718 && ae1
->weight
== ae2
->weight
719 && ae1
->tag
== ae2
->tag
720 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
721 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
722 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
723 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
724 && ae1
->ecommunity
== ae2
->ecommunity
725 && ae1
->lcommunity
== ae2
->lcommunity
726 && ae1
->cluster
== ae2
->cluster
727 && ae1
->transit
== ae2
->transit
728 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
729 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
731 && encap_same(ae1
->vnc_subtlvs
, ae2
->vnc_subtlvs
)
733 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
))
737 /* neither attribute has extra attributes, so they're same */
747 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
751 * special for hash_clean below
754 attr_vfree (void *attr
)
756 bgp_attr_extra_free ((struct attr
*)attr
);
757 XFREE (MTYPE_ATTR
, attr
);
761 attrhash_finish (void)
763 hash_clean(attrhash
, attr_vfree
);
764 hash_free (attrhash
);
769 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
771 struct attr
*attr
= backet
->data
;
773 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
774 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
778 attr_show_all (struct vty
*vty
)
780 hash_iterate (attrhash
,
781 (void (*)(struct hash_backet
*, void *))
782 attr_show_all_iterator
,
787 bgp_attr_hash_alloc (void *p
)
789 const struct attr
* val
= (const struct attr
*) p
;
792 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
796 attr
->extra
= bgp_attr_extra_new ();
797 *attr
->extra
= *val
->extra
;
798 if (val
->extra
->encap_subtlvs
) {
799 val
->extra
->encap_subtlvs
= NULL
;
802 if (val
->extra
->vnc_subtlvs
) {
803 val
->extra
->vnc_subtlvs
= NULL
;
811 /* Internet argument attribute. */
813 bgp_attr_intern (struct attr
*attr
)
817 /* Intern referenced strucutre. */
820 if (! attr
->aspath
->refcnt
)
821 attr
->aspath
= aspath_intern (attr
->aspath
);
823 attr
->aspath
->refcnt
++;
827 if (! attr
->community
->refcnt
)
828 attr
->community
= community_intern (attr
->community
);
830 attr
->community
->refcnt
++;
834 struct attr_extra
*attre
= attr
->extra
;
836 if (attre
->ecommunity
)
838 if (! attre
->ecommunity
->refcnt
)
839 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
841 attre
->ecommunity
->refcnt
++;
844 if (attre
->lcommunity
)
846 if (! attre
->lcommunity
->refcnt
)
847 attre
->lcommunity
= lcommunity_intern (attre
->lcommunity
);
849 attre
->lcommunity
->refcnt
++;
853 if (! attre
->cluster
->refcnt
)
854 attre
->cluster
= cluster_intern (attre
->cluster
);
856 attre
->cluster
->refcnt
++;
860 if (! attre
->transit
->refcnt
)
861 attre
->transit
= transit_intern (attre
->transit
);
863 attre
->transit
->refcnt
++;
865 if (attre
->encap_subtlvs
)
867 if (! attre
->encap_subtlvs
->refcnt
)
868 attre
->encap_subtlvs
= encap_intern (attre
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
870 attre
->encap_subtlvs
->refcnt
++;
873 if (attre
->vnc_subtlvs
)
875 if (! attre
->vnc_subtlvs
->refcnt
)
876 attre
->vnc_subtlvs
= encap_intern (attre
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
878 attre
->vnc_subtlvs
->refcnt
++;
883 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
890 * Increment the refcount on various structures that attr holds.
891 * Note on usage: call _only_ when the 'attr' object has already
892 * been 'intern'ed and exists in 'attrhash' table. The function
893 * serves to hold a reference to that (real) object.
894 * Note also that the caller can safely call bgp_attr_unintern()
895 * after calling bgp_attr_refcount(). That would release the
896 * reference and could result in a free() of the attr object.
899 bgp_attr_refcount (struct attr
*attr
)
901 /* Intern referenced strucutre. */
903 attr
->aspath
->refcnt
++;
906 attr
->community
->refcnt
++;
910 struct attr_extra
*attre
= attr
->extra
;
911 if (attre
->ecommunity
)
912 attre
->ecommunity
->refcnt
++;
915 attre
->cluster
->refcnt
++;
918 attre
->transit
->refcnt
++;
920 if (attre
->encap_subtlvs
)
921 attre
->encap_subtlvs
->refcnt
++;
924 if (attre
->vnc_subtlvs
)
925 attre
->vnc_subtlvs
->refcnt
++;
932 /* Make network statement's attribute. */
934 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
936 memset (attr
, 0, sizeof (struct attr
));
937 bgp_attr_extra_get (attr
);
939 attr
->origin
= origin
;
940 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
941 attr
->aspath
= aspath_empty ();
942 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
943 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
944 attr
->extra
->tag
= 0;
945 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
946 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
952 /* Make network statement's attribute. */
954 bgp_attr_default_intern (u_char origin
)
959 memset (&attr
, 0, sizeof (struct attr
));
960 bgp_attr_extra_get (&attr
);
962 bgp_attr_default_set(&attr
, origin
);
964 new = bgp_attr_intern (&attr
);
965 bgp_attr_extra_free (&attr
);
967 aspath_unintern (&new->aspath
);
971 /* Create the attributes for an aggregate */
973 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
974 struct aspath
*aspath
,
975 struct community
*community
, int as_set
,
976 u_char atomic_aggregate
)
980 struct attr_extra attre
;
982 memset (&attr
, 0, sizeof (struct attr
));
983 memset (&attre
, 0, sizeof (struct attr_extra
));
986 /* Origin attribute. */
987 attr
.origin
= origin
;
988 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
990 /* AS path attribute. */
992 attr
.aspath
= aspath_intern (aspath
);
994 attr
.aspath
= aspath_empty ();
995 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
997 /* Next hop attribute. */
998 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1002 attr
.community
= community
;
1003 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1006 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1007 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1008 if (! as_set
|| atomic_aggregate
)
1009 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1010 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1011 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1012 attre
.aggregator_as
= bgp
->confed_id
;
1014 attre
.aggregator_as
= bgp
->as
;
1015 attre
.aggregator_addr
= bgp
->router_id
;
1017 new = bgp_attr_intern (&attr
);
1019 aspath_unintern (&new->aspath
);
1023 /* Unintern just the sub-components of the attr, but not the attr */
1025 bgp_attr_unintern_sub (struct attr
*attr
)
1027 /* aspath refcount shoud be decrement. */
1029 aspath_unintern (&attr
->aspath
);
1030 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
1032 if (attr
->community
)
1033 community_unintern (&attr
->community
);
1034 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
1038 if (attr
->extra
->ecommunity
)
1039 ecommunity_unintern (&attr
->extra
->ecommunity
);
1040 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
1042 if (attr
->extra
->lcommunity
)
1043 lcommunity_unintern (&attr
->extra
->lcommunity
);
1044 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
));
1046 if (attr
->extra
->cluster
)
1047 cluster_unintern (attr
->extra
->cluster
);
1048 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
1050 if (attr
->extra
->transit
)
1051 transit_unintern (attr
->extra
->transit
);
1053 if (attr
->extra
->encap_subtlvs
)
1054 encap_unintern (&attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1057 if (attr
->extra
->vnc_subtlvs
)
1058 encap_unintern (&attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1063 /* Free bgp attribute and aspath. */
1065 bgp_attr_unintern (struct attr
**pattr
)
1067 struct attr
*attr
= *pattr
;
1070 struct attr_extra tmp_extra
;
1072 /* Decrement attribute reference. */
1079 tmp
.extra
= &tmp_extra
;
1080 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
1083 /* If reference becomes zero then free attribute object. */
1084 if (attr
->refcnt
== 0)
1086 ret
= hash_release (attrhash
, attr
);
1087 assert (ret
!= NULL
);
1088 bgp_attr_extra_free (attr
);
1089 XFREE (MTYPE_ATTR
, attr
);
1093 bgp_attr_unintern_sub (&tmp
);
1097 bgp_attr_flush (struct attr
*attr
)
1099 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
1101 aspath_free (attr
->aspath
);
1102 attr
->aspath
= NULL
;
1104 if (attr
->community
&& ! attr
->community
->refcnt
)
1106 community_free (attr
->community
);
1107 attr
->community
= NULL
;
1111 struct attr_extra
*attre
= attr
->extra
;
1113 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
1114 ecommunity_free (&attre
->ecommunity
);
1115 if (attre
->lcommunity
&& ! attre
->lcommunity
->refcnt
)
1116 lcommunity_free (&attre
->lcommunity
);
1117 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
1119 cluster_free (attre
->cluster
);
1120 attre
->cluster
= NULL
;
1122 if (attre
->transit
&& ! attre
->transit
->refcnt
)
1124 transit_free (attre
->transit
);
1125 attre
->transit
= NULL
;
1127 if (attre
->encap_subtlvs
&& ! attre
->encap_subtlvs
->refcnt
)
1129 encap_free(attre
->encap_subtlvs
);
1130 attre
->encap_subtlvs
= NULL
;
1133 if (attre
->vnc_subtlvs
&& ! attre
->vnc_subtlvs
->refcnt
)
1135 encap_free(attre
->vnc_subtlvs
);
1136 attre
->vnc_subtlvs
= NULL
;
1142 /* Implement draft-scudder-idr-optional-transitive behaviour and
1143 * avoid resetting sessions for malformed attributes which are
1144 * are partial/optional and hence where the error likely was not
1145 * introduced by the sending neighbour.
1147 static bgp_attr_parse_ret_t
1148 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
1151 struct peer
*const peer
= args
->peer
;
1152 const u_int8_t flags
= args
->flags
;
1153 /* startp and length must be special-cased, as whether or not to
1154 * send the attribute data with the NOTIFY depends on the error,
1155 * the caller therefore signals this with the seperate length argument
1157 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1159 /* Only relax error handling for eBGP peers */
1160 if (peer
->sort
!= BGP_PEER_EBGP
)
1162 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1163 notify_datap
, length
);
1164 return BGP_ATTR_PARSE_ERROR
;
1168 /* Adjust the stream getp to the end of the attribute, in case we can
1169 * still proceed but the caller hasn't read all the attribute.
1171 stream_set_getp (BGP_INPUT (peer
),
1172 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
1175 switch (args
->type
) {
1176 /* where an attribute is relatively inconsequential, e.g. it does not
1177 * affect route selection, and can be safely ignored, then any such
1178 * attributes which are malformed should just be ignored and the route
1179 * processed as normal.
1181 case BGP_ATTR_AS4_AGGREGATOR
:
1182 case BGP_ATTR_AGGREGATOR
:
1183 case BGP_ATTR_ATOMIC_AGGREGATE
:
1184 return BGP_ATTR_PARSE_PROCEED
;
1186 /* Core attributes, particularly ones which may influence route
1187 * selection, should always cause session resets
1189 case BGP_ATTR_ORIGIN
:
1190 case BGP_ATTR_AS_PATH
:
1191 case BGP_ATTR_NEXT_HOP
:
1192 case BGP_ATTR_MULTI_EXIT_DISC
:
1193 case BGP_ATTR_LOCAL_PREF
:
1194 case BGP_ATTR_COMMUNITIES
:
1195 case BGP_ATTR_ORIGINATOR_ID
:
1196 case BGP_ATTR_CLUSTER_LIST
:
1197 case BGP_ATTR_MP_REACH_NLRI
:
1198 case BGP_ATTR_MP_UNREACH_NLRI
:
1199 case BGP_ATTR_EXT_COMMUNITIES
:
1200 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1201 notify_datap
, length
);
1202 return BGP_ATTR_PARSE_ERROR
;
1205 /* Partial optional attributes that are malformed should not cause
1206 * the whole session to be reset. Instead treat it as a withdrawal
1207 * of the routes, if possible.
1209 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1210 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1211 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1212 return BGP_ATTR_PARSE_WITHDRAW
;
1214 /* default to reset */
1215 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1218 /* Find out what is wrong with the path attribute flag bits and log the error.
1219 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1220 Extended Length. Checking O/T/P bits at once implies, that the attribute
1221 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1222 non-transitive" attribute. */
1224 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1225 u_int8_t desired_flags
/* how RFC says it must be */
1229 u_char real_flags
= args
->flags
;
1230 const u_int8_t attr_code
= args
->type
;
1232 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1233 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1234 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1237 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1238 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1241 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1242 LOOKUP (attr_str
, attr_code
),
1243 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1244 attr_flag_str
[i
].str
);
1249 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1250 " (real flags 0x%x, desired 0x%x)",
1251 __func__
, LOOKUP (attr_str
, attr_code
),
1252 real_flags
, desired_flags
);
1256 /* Required flags for attributes. EXTLEN will be masked off when testing,
1257 * as will PARTIAL for optional+transitive attributes.
1259 const u_int8_t attr_flags_values
[] = {
1260 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1261 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1262 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1263 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1264 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1265 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1266 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1267 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1268 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1269 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1270 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1271 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1272 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1273 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1274 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1275 [BGP_ATTR_LARGE_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
1277 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1280 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1282 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1283 const u_int8_t flags
= args
->flags
;
1284 const u_int8_t attr_code
= args
->type
;
1286 /* there may be attributes we don't know about */
1287 if (attr_code
> attr_flags_values_max
)
1289 if (attr_flags_values
[attr_code
] == 0)
1292 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1295 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1296 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1298 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1299 LOOKUP (attr_str
, attr_code
), flags
);
1303 /* "For well-known attributes and for optional non-transitive attributes,
1304 * the Partial bit MUST be set to 0."
1306 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1308 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1310 zlog_err ("%s well-known attribute "
1311 "must NOT have the partial flag set (%x)",
1312 LOOKUP (attr_str
, attr_code
), flags
);
1315 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1316 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1318 zlog_err ("%s optional + transitive attribute "
1319 "must NOT have the partial flag set (%x)",
1320 LOOKUP (attr_str
, attr_code
), flags
);
1325 /* Optional transitive attributes may go through speakers that don't
1326 * reocgnise them and set the Partial bit.
1328 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1329 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1330 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1333 == attr_flags_values
[attr_code
])
1336 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1340 /* Get origin attribute of the update message. */
1341 static bgp_attr_parse_ret_t
1342 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1344 struct peer
*const peer
= args
->peer
;
1345 struct attr
*const attr
= args
->attr
;
1346 const bgp_size_t length
= args
->length
;
1348 /* If any recognized attribute has Attribute Length that conflicts
1349 with the expected length (based on the attribute type code), then
1350 the Error Subcode is set to Attribute Length Error. The Data
1351 field contains the erroneous attribute (type, length and
1355 zlog_err ("Origin attribute length is not one %d", length
);
1356 return bgp_attr_malformed (args
,
1357 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1361 /* Fetch origin attribute. */
1362 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1364 /* If the ORIGIN attribute has an undefined value, then the Error
1365 Subcode is set to Invalid Origin Attribute. The Data field
1366 contains the unrecognized attribute (type, length and value). */
1367 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1368 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1369 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1371 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1372 return bgp_attr_malformed (args
,
1373 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1377 /* Set oring attribute flag. */
1378 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1383 /* Parse AS path information. This function is wrapper of
1386 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1388 struct attr
*const attr
= args
->attr
;
1389 struct peer
*const peer
= args
->peer
;
1390 const bgp_size_t length
= args
->length
;
1393 * peer with AS4 => will get 4Byte ASnums
1394 * otherwise, will get 16 Bit
1396 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1397 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1399 /* In case of IBGP, length will be zero. */
1402 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1403 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1406 /* Set aspath attribute flag. */
1407 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1409 return BGP_ATTR_PARSE_PROCEED
;
1412 static bgp_attr_parse_ret_t
1413 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1415 /* These checks were part of bgp_attr_aspath, but with
1416 * as4 we should to check aspath things when
1417 * aspath synthesizing with as4_path has already taken place.
1418 * Otherwise we check ASPATH and use the synthesized thing, and that is
1420 * So do the checks later, i.e. here
1422 struct bgp
*bgp
= peer
->bgp
;
1423 struct aspath
*aspath
;
1425 /* Confederation sanity check. */
1426 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1427 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1429 zlog_err ("Malformed AS path from %s", peer
->host
);
1430 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1431 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1432 return BGP_ATTR_PARSE_ERROR
;
1435 /* First AS check for EBGP. */
1436 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1438 if (peer
->sort
== BGP_PEER_EBGP
1439 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1441 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1442 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1443 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1444 return BGP_ATTR_PARSE_ERROR
;
1448 /* local-as prepend */
1449 if (peer
->change_local_as
&&
1450 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1452 aspath
= aspath_dup (attr
->aspath
);
1453 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1454 aspath_unintern (&attr
->aspath
);
1455 attr
->aspath
= aspath_intern (aspath
);
1458 return BGP_ATTR_PARSE_PROCEED
;
1461 /* Parse AS4 path information. This function is another wrapper of
1464 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1466 struct peer
*const peer
= args
->peer
;
1467 struct attr
*const attr
= args
->attr
;
1468 const bgp_size_t length
= args
->length
;
1470 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1472 /* In case of IBGP, length will be zero. */
1475 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1476 return bgp_attr_malformed (args
,
1477 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1481 /* Set aspath attribute flag. */
1483 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1485 return BGP_ATTR_PARSE_PROCEED
;
1488 /* Nexthop attribute. */
1489 static bgp_attr_parse_ret_t
1490 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1492 struct peer
*const peer
= args
->peer
;
1493 struct attr
*const attr
= args
->attr
;
1494 const bgp_size_t length
= args
->length
;
1496 in_addr_t nexthop_h
, nexthop_n
;
1498 /* Check nexthop attribute length. */
1501 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1503 return bgp_attr_malformed (args
,
1504 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1508 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1509 attribute must result in a NOTIFICATION message (this is implemented below).
1510 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1511 logged locally (this is implemented somewhere else). The UPDATE message
1512 gets ignored in any of these cases. */
1513 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1514 nexthop_h
= ntohl (nexthop_n
);
1515 if ((IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1516 && !BGP_DEBUG (allow_martians
, ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1518 char buf
[INET_ADDRSTRLEN
];
1519 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1520 zlog_err ("Martian nexthop %s", buf
);
1521 return bgp_attr_malformed (args
,
1522 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1526 attr
->nexthop
.s_addr
= nexthop_n
;
1527 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1529 return BGP_ATTR_PARSE_PROCEED
;
1532 /* MED atrribute. */
1533 static bgp_attr_parse_ret_t
1534 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1536 struct peer
*const peer
= args
->peer
;
1537 struct attr
*const attr
= args
->attr
;
1538 const bgp_size_t length
= args
->length
;
1543 zlog_err ("MED attribute length isn't four [%d]", length
);
1545 return bgp_attr_malformed (args
,
1546 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1550 attr
->med
= stream_getl (peer
->ibuf
);
1552 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1554 return BGP_ATTR_PARSE_PROCEED
;
1557 /* Local preference attribute. */
1558 static bgp_attr_parse_ret_t
1559 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1561 struct peer
*const peer
= args
->peer
;
1562 struct attr
*const attr
= args
->attr
;
1563 const bgp_size_t length
= args
->length
;
1568 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1569 return bgp_attr_malformed (args
,
1570 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1574 /* If it is contained in an UPDATE message that is received from an
1575 external peer, then this attribute MUST be ignored by the
1576 receiving speaker. */
1577 if (peer
->sort
== BGP_PEER_EBGP
)
1579 stream_forward_getp (peer
->ibuf
, length
);
1580 return BGP_ATTR_PARSE_PROCEED
;
1583 attr
->local_pref
= stream_getl (peer
->ibuf
);
1585 /* Set atomic aggregate flag. */
1586 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1588 return BGP_ATTR_PARSE_PROCEED
;
1591 /* Atomic aggregate. */
1593 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1595 struct attr
*const attr
= args
->attr
;
1596 const bgp_size_t length
= args
->length
;
1601 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1602 return bgp_attr_malformed (args
,
1603 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1607 /* Set atomic aggregate flag. */
1608 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1610 return BGP_ATTR_PARSE_PROCEED
;
1613 /* Aggregator attribute */
1615 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1617 struct peer
*const peer
= args
->peer
;
1618 struct attr
*const attr
= args
->attr
;
1619 const bgp_size_t length
= args
->length
;
1622 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1624 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1625 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1628 if (length
!= wantedlen
)
1630 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1631 return bgp_attr_malformed (args
,
1632 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1636 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1637 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1639 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1640 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1642 /* Set atomic aggregate flag. */
1643 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1645 return BGP_ATTR_PARSE_PROCEED
;
1648 /* New Aggregator attribute */
1649 static bgp_attr_parse_ret_t
1650 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1651 as_t
*as4_aggregator_as
,
1652 struct in_addr
*as4_aggregator_addr
)
1654 struct peer
*const peer
= args
->peer
;
1655 struct attr
*const attr
= args
->attr
;
1656 const bgp_size_t length
= args
->length
;
1660 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1661 return bgp_attr_malformed (args
,
1662 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1666 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1667 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1669 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1671 return BGP_ATTR_PARSE_PROCEED
;
1674 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1676 static bgp_attr_parse_ret_t
1677 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1678 struct attr
*const attr
,
1679 struct aspath
*as4_path
, as_t as4_aggregator
,
1680 struct in_addr
*as4_aggregator_addr
)
1682 int ignore_as4_path
= 0;
1683 struct aspath
*newpath
;
1684 struct attr_extra
*attre
= attr
->extra
;
1688 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1689 * checked that all well-known, mandatory attributes were present.
1691 * Can only be a problem with peer itself - hard error
1693 return BGP_ATTR_PARSE_ERROR
;
1696 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1698 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1700 * It is worth a warning though, because the peer really
1701 * should not send them
1703 if (BGP_DEBUG(as4
, AS4
))
1705 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1706 zlog_debug ("[AS4] %s %s AS4_PATH",
1707 peer
->host
, "AS4 capable peer, yet it sent");
1709 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1710 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1711 peer
->host
, "AS4 capable peer, yet it sent");
1714 return BGP_ATTR_PARSE_PROCEED
;
1717 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1718 * because that may override AS4_PATH
1720 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1722 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1727 * if the as_number in aggregator is not AS_TRANS,
1728 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1729 * and the Aggregator shall be taken as
1730 * info on the aggregating node, and the AS_PATH
1731 * shall be taken as the AS_PATH
1733 * the Aggregator shall be ignored and the
1734 * AS4_AGGREGATOR shall be taken as the
1735 * Aggregating node and the AS_PATH is to be
1736 * constructed "as in all other cases"
1738 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1741 if ( BGP_DEBUG(as4
, AS4
))
1742 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1743 " send AGGREGATOR != AS_TRANS and"
1744 " AS4_AGGREGATOR, so ignore"
1745 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1746 ignore_as4_path
= 1;
1750 /* "New_aggregator shall be taken as aggregator" */
1751 attre
->aggregator_as
= as4_aggregator
;
1752 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1757 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1758 * That is bogus - but reading the conditions
1759 * we have to handle AS4_AGGREGATOR as if it were
1760 * AGGREGATOR in that case
1762 if ( BGP_DEBUG(as4
, AS4
))
1763 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1764 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1765 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1766 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1767 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1768 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1772 /* need to reconcile NEW_AS_PATH and AS_PATH */
1773 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1775 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1776 aspath_unintern (&attr
->aspath
);
1777 attr
->aspath
= aspath_intern (newpath
);
1779 return BGP_ATTR_PARSE_PROCEED
;
1782 /* Community attribute. */
1783 static bgp_attr_parse_ret_t
1784 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1786 struct peer
*const peer
= args
->peer
;
1787 struct attr
*const attr
= args
->attr
;
1788 const bgp_size_t length
= args
->length
;
1792 attr
->community
= NULL
;
1793 return BGP_ATTR_PARSE_PROCEED
;
1797 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1799 /* XXX: fix community_parse to use stream API and remove this */
1800 stream_forward_getp (peer
->ibuf
, length
);
1802 if (!attr
->community
)
1803 return bgp_attr_malformed (args
,
1804 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1807 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1809 return BGP_ATTR_PARSE_PROCEED
;
1812 /* Originator ID attribute. */
1813 static bgp_attr_parse_ret_t
1814 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1816 struct peer
*const peer
= args
->peer
;
1817 struct attr
*const attr
= args
->attr
;
1818 const bgp_size_t length
= args
->length
;
1823 zlog_err ("Bad originator ID length %d", length
);
1825 return bgp_attr_malformed (args
,
1826 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1830 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1831 = stream_get_ipv4 (peer
->ibuf
);
1833 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1835 return BGP_ATTR_PARSE_PROCEED
;
1838 /* Cluster list attribute. */
1839 static bgp_attr_parse_ret_t
1840 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1842 struct peer
*const peer
= args
->peer
;
1843 struct attr
*const attr
= args
->attr
;
1844 const bgp_size_t length
= args
->length
;
1849 zlog_err ("Bad cluster list length %d", length
);
1851 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1855 (bgp_attr_extra_get (attr
))->cluster
1856 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1858 /* XXX: Fix cluster_parse to use stream API and then remove this */
1859 stream_forward_getp (peer
->ibuf
, length
);
1861 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1863 return BGP_ATTR_PARSE_PROCEED
;
1866 /* Multiprotocol reachability information parse. */
1868 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1869 struct bgp_nlri
*mp_update
)
1872 safi_t pkt_safi
, safi
;
1873 bgp_size_t nlri_len
;
1876 struct peer
*const peer
= args
->peer
;
1877 struct attr
*const attr
= args
->attr
;
1878 const bgp_size_t length
= args
->length
;
1879 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1881 /* Set end of packet. */
1882 s
= BGP_INPUT(peer
);
1883 start
= stream_get_getp(s
);
1885 /* safe to read statically sized header? */
1886 #define BGP_MP_REACH_MIN_SIZE 5
1887 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1888 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1890 zlog_info ("%s: %s sent invalid length, %lu",
1891 __func__
, peer
->host
, (unsigned long)length
);
1892 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1895 /* Load AFI, SAFI. */
1896 pkt_afi
= stream_getw (s
);
1897 pkt_safi
= stream_getc (s
);
1899 /* Convert AFI, SAFI to internal values, check. */
1900 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
1902 /* Log if AFI or SAFI is unrecognized. This is not an error unless
1903 * the attribute is otherwise malformed.
1905 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1906 zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1907 peer
->host
, pkt_afi
, pkt_safi
);
1908 return BGP_ATTR_PARSE_ERROR
;
1911 /* Get nexthop length. */
1912 attre
->mp_nexthop_len
= stream_getc (s
);
1914 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1916 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1917 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1918 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1921 /* Nexthop length check. */
1922 switch (attre
->mp_nexthop_len
)
1924 case BGP_ATTR_NHLEN_IPV4
:
1925 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1926 /* Probably needed for RFC 2283 */
1927 if (attr
->nexthop
.s_addr
== 0)
1928 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1930 case BGP_ATTR_NHLEN_VPNV4
:
1931 stream_getl (s
); /* RD high */
1932 stream_getl (s
); /* RD low */
1933 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1935 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1936 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1937 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1939 stream_getl (s
); /* RD high */
1940 stream_getl (s
); /* RD low */
1942 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1944 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1945 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1946 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1948 stream_getl (s
); /* RD high */
1949 stream_getl (s
); /* RD low */
1951 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1952 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1954 stream_getl (s
); /* RD high */
1955 stream_getl (s
); /* RD low */
1957 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1958 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1960 char buf1
[INET6_ADDRSTRLEN
];
1961 char buf2
[INET6_ADDRSTRLEN
];
1963 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1964 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1966 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1967 buf1
, INET6_ADDRSTRLEN
),
1968 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1969 buf2
, INET6_ADDRSTRLEN
));
1971 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1975 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1976 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1977 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1982 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1983 __func__
, peer
->host
);
1984 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1989 if ((val
= stream_getc (s
)))
1990 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1994 /* must have nrli_len, what is left of the attribute */
1995 nlri_len
= LEN_LEFT
;
1996 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
1998 zlog_info ("%s: (%s) Failed to read NLRI",
1999 __func__
, peer
->host
);
2000 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2003 mp_update
->afi
= afi
;
2004 mp_update
->safi
= safi
;
2005 mp_update
->nlri
= stream_pnt (s
);
2006 mp_update
->length
= nlri_len
;
2008 stream_forward_getp (s
, nlri_len
);
2010 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
2012 return BGP_ATTR_PARSE_PROCEED
;
2016 /* Multiprotocol unreachable parse */
2018 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
2019 struct bgp_nlri
*mp_withdraw
)
2023 safi_t pkt_safi
, safi
;
2024 u_int16_t withdraw_len
;
2025 struct peer
*const peer
= args
->peer
;
2026 struct attr
*const attr
= args
->attr
;
2027 const bgp_size_t length
= args
->length
;
2031 #define BGP_MP_UNREACH_MIN_SIZE 3
2032 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2033 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2035 pkt_afi
= stream_getw (s
);
2036 pkt_safi
= stream_getc (s
);
2038 /* Convert AFI, SAFI to internal values, check. */
2039 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
2041 /* Log if AFI or SAFI is unrecognized. This is not an error unless
2042 * the attribute is otherwise malformed.
2044 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2045 zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
2046 peer
->host
, pkt_afi
, pkt_safi
);
2047 return BGP_ATTR_PARSE_ERROR
;
2050 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2052 mp_withdraw
->afi
= afi
;
2053 mp_withdraw
->safi
= safi
;
2054 mp_withdraw
->nlri
= stream_pnt (s
);
2055 mp_withdraw
->length
= withdraw_len
;
2057 stream_forward_getp (s
, withdraw_len
);
2059 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
2061 return BGP_ATTR_PARSE_PROCEED
;
2064 /* Large Community attribute. */
2065 static bgp_attr_parse_ret_t
2066 bgp_attr_large_community (struct bgp_attr_parser_args
*args
)
2068 struct peer
*const peer
= args
->peer
;
2069 struct attr
*const attr
= args
->attr
;
2070 const bgp_size_t length
= args
->length
;
2073 * Large community follows new attribute format.
2078 attr
->extra
->lcommunity
= NULL
;
2079 /* Empty extcomm doesn't seem to be invalid per se */
2080 return BGP_ATTR_PARSE_PROCEED
;
2083 (bgp_attr_extra_get (attr
))->lcommunity
=
2084 lcommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2085 /* XXX: fix ecommunity_parse to use stream API */
2086 stream_forward_getp (peer
->ibuf
, length
);
2088 if (attr
->extra
&& !attr
->extra
->lcommunity
)
2089 return bgp_attr_malformed (args
,
2090 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2093 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
);
2095 return BGP_ATTR_PARSE_PROCEED
;
2098 /* Extended Community attribute. */
2099 static bgp_attr_parse_ret_t
2100 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
2102 struct peer
*const peer
= args
->peer
;
2103 struct attr
*const attr
= args
->attr
;
2104 const bgp_size_t length
= args
->length
;
2109 attr
->extra
->ecommunity
= NULL
;
2110 /* Empty extcomm doesn't seem to be invalid per se */
2111 return BGP_ATTR_PARSE_PROCEED
;
2114 (bgp_attr_extra_get (attr
))->ecommunity
=
2115 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2116 /* XXX: fix ecommunity_parse to use stream API */
2117 stream_forward_getp (peer
->ibuf
, length
);
2119 if (attr
->extra
&& !attr
->extra
->ecommunity
)
2120 return bgp_attr_malformed (args
,
2121 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2124 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
2126 return BGP_ATTR_PARSE_PROCEED
;
2129 /* Parse Tunnel Encap attribute in an UPDATE */
2133 struct peer
*peer
, /* IN */
2134 bgp_size_t length
, /* IN: attr's length field */
2135 struct attr
*attr
, /* IN: caller already allocated */
2136 u_char flag
, /* IN: attr's flags field */
2140 struct attr_extra
*attre
= NULL
;
2141 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2142 uint16_t tunneltype
= 0;
2144 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2146 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2147 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
2149 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
2150 bgp_notify_send_with_data (peer
,
2151 BGP_NOTIFY_UPDATE_ERR
,
2152 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2157 if (BGP_ATTR_ENCAP
== type
) {
2158 /* read outer TLV type and length */
2159 uint16_t tlv_length
;
2162 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2163 bgp_notify_send_with_data(peer
,
2164 BGP_NOTIFY_UPDATE_ERR
,
2165 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2169 tunneltype
= stream_getw (BGP_INPUT (peer
));
2170 tlv_length
= stream_getw (BGP_INPUT (peer
));
2173 if (tlv_length
!= length
) {
2174 zlog_info ("%s: tlv_length(%d) != length(%d)",
2175 __func__
, tlv_length
, length
);
2179 while (length
>= 4) {
2180 uint16_t subtype
= 0;
2181 uint16_t sublength
= 0;
2182 struct bgp_attr_encap_subtlv
*tlv
;
2184 if (BGP_ATTR_ENCAP
== type
) {
2185 subtype
= stream_getc (BGP_INPUT (peer
));
2186 sublength
= stream_getc (BGP_INPUT (peer
));
2190 subtype
= stream_getw (BGP_INPUT (peer
));
2191 sublength
= stream_getw (BGP_INPUT (peer
));
2196 if (sublength
> length
) {
2197 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2199 bgp_notify_send_with_data (peer
,
2200 BGP_NOTIFY_UPDATE_ERR
,
2201 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2206 /* alloc and copy sub-tlv */
2207 /* TBD make sure these are freed when attributes are released */
2208 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
2209 tlv
->type
= subtype
;
2210 tlv
->length
= sublength
;
2211 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2212 length
-= sublength
;
2214 /* attach tlv to encap chain */
2216 attre
= bgp_attr_extra_get(attr
);
2217 if (BGP_ATTR_ENCAP
== type
) {
2218 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
2219 stlv_last
= stlv_last
->next
);
2221 stlv_last
->next
= tlv
;
2223 attre
->encap_subtlvs
= tlv
;
2227 for (stlv_last
= attre
->vnc_subtlvs
; stlv_last
&& stlv_last
->next
;
2228 stlv_last
= stlv_last
->next
);
2230 stlv_last
->next
= tlv
;
2232 attre
->vnc_subtlvs
= tlv
;
2237 stlv_last
->next
= tlv
;
2242 if (attre
&& (BGP_ATTR_ENCAP
== type
)) {
2243 attre
->encap_tunneltype
= tunneltype
;
2247 /* spurious leftover data */
2248 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2249 bgp_notify_send_with_data (peer
,
2250 BGP_NOTIFY_UPDATE_ERR
,
2251 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2259 /* BGP unknown attribute treatment. */
2260 static bgp_attr_parse_ret_t
2261 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2263 bgp_size_t total
= args
->total
;
2264 struct transit
*transit
;
2265 struct attr_extra
*attre
;
2266 struct peer
*const peer
= args
->peer
;
2267 struct attr
*const attr
= args
->attr
;
2268 u_char
*const startp
= args
->startp
;
2269 const u_char type
= args
->type
;
2270 const u_char flag
= args
->flags
;
2271 const bgp_size_t length
= args
->length
;
2273 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2274 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2275 peer
->host
, type
, length
);
2277 /* Forward read pointer of input stream. */
2278 stream_forward_getp (peer
->ibuf
, length
);
2280 /* If any of the mandatory well-known attributes are not recognized,
2281 then the Error Subcode is set to Unrecognized Well-known
2282 Attribute. The Data field contains the unrecognized attribute
2283 (type, length and value). */
2284 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2286 return bgp_attr_malformed (args
,
2287 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2291 /* Unrecognized non-transitive optional attributes must be quietly
2292 ignored and not passed along to other BGP peers. */
2293 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2294 return BGP_ATTR_PARSE_PROCEED
;
2296 /* If a path with recognized transitive optional attribute is
2297 accepted and passed along to other BGP peers and the Partial bit
2298 in the Attribute Flags octet is set to 1 by some previous AS, it
2299 is not set back to 0 by the current AS. */
2300 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2302 /* Store transitive attribute to the end of attr->transit. */
2303 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2304 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2306 transit
= attre
->transit
;
2309 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2310 transit
->length
+ total
);
2312 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2314 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2315 transit
->length
+= total
;
2317 return BGP_ATTR_PARSE_PROCEED
;
2320 /* Well-known attribute check. */
2322 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2326 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2328 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2329 return BGP_ATTR_PARSE_PROCEED
;
2331 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2332 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2333 are present, it should. Check for any other attribute being present
2336 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2337 return BGP_ATTR_PARSE_PROCEED
;
2339 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2340 type
= BGP_ATTR_ORIGIN
;
2342 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2343 type
= BGP_ATTR_AS_PATH
;
2345 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2346 * NLRI is empty. We can't easily check NLRI empty here though.
2348 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2349 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2350 type
= BGP_ATTR_NEXT_HOP
;
2352 if (peer
->sort
== BGP_PEER_IBGP
2353 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2354 type
= BGP_ATTR_LOCAL_PREF
;
2358 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2359 LOOKUP (attr_str
, type
));
2360 bgp_notify_send_with_data (peer
,
2361 BGP_NOTIFY_UPDATE_ERR
,
2362 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2364 return BGP_ATTR_PARSE_ERROR
;
2366 return BGP_ATTR_PARSE_PROCEED
;
2369 /* Read attribute of update packet. This function is called from
2370 bgp_update_receive() in bgp_packet.c. */
2371 bgp_attr_parse_ret_t
2372 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2373 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2379 u_char
*startp
, *endp
;
2381 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2382 /* we need the as4_path only until we have synthesized the as_path with it */
2383 /* same goes for as4_aggregator */
2384 struct aspath
*as4_path
= NULL
;
2385 as_t as4_aggregator
= 0;
2386 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2388 /* Initialize bitmap. */
2389 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2391 /* End pointer of BGP attribute. */
2392 endp
= BGP_INPUT_PNT (peer
) + size
;
2394 /* Get attributes to the end of attribute length. */
2395 while (BGP_INPUT_PNT (peer
) < endp
)
2397 /* Check remaining length check.*/
2398 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2400 /* XXX warning: long int format, int arg (arg 5) */
2401 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2403 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2405 bgp_notify_send (peer
,
2406 BGP_NOTIFY_UPDATE_ERR
,
2407 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2408 return BGP_ATTR_PARSE_ERROR
;
2411 /* Fetch attribute flag and type. */
2412 startp
= BGP_INPUT_PNT (peer
);
2413 /* "The lower-order four bits of the Attribute Flags octet are
2414 unused. They MUST be zero when sent and MUST be ignored when
2416 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2417 type
= stream_getc (BGP_INPUT (peer
));
2419 /* Check whether Extended-Length applies and is in bounds */
2420 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2421 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2423 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2425 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2427 bgp_notify_send (peer
,
2428 BGP_NOTIFY_UPDATE_ERR
,
2429 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2430 return BGP_ATTR_PARSE_ERROR
;
2433 /* Check extended attribue length bit. */
2434 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2435 length
= stream_getw (BGP_INPUT (peer
));
2437 length
= stream_getc (BGP_INPUT (peer
));
2439 /* If any attribute appears more than once in the UPDATE
2440 message, then the Error Subcode is set to Malformed Attribute
2443 if (CHECK_BITMAP (seen
, type
))
2445 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2448 bgp_notify_send (peer
,
2449 BGP_NOTIFY_UPDATE_ERR
,
2450 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2451 return BGP_ATTR_PARSE_ERROR
;
2454 /* Set type to bitmap to check duplicate attribute. `type' is
2455 unsigned char so it never overflow bitmap range. */
2457 SET_BITMAP (seen
, type
);
2459 /* Overflow check. */
2460 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2462 if (attr_endp
> endp
)
2464 zlog_warn ("%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer
->host
, type
, length
, size
, attr_endp
, endp
);
2465 bgp_notify_send_with_data (peer
,
2466 BGP_NOTIFY_UPDATE_ERR
,
2467 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2468 startp
, attr_endp
- startp
);
2469 return BGP_ATTR_PARSE_ERROR
;
2472 struct bgp_attr_parser_args attr_args
= {
2479 .total
= attr_endp
- startp
,
2483 /* If any recognized attribute has Attribute Flags that conflict
2484 with the Attribute Type Code, then the Error Subcode is set to
2485 Attribute Flags Error. The Data field contains the erroneous
2486 attribute (type, length and value). */
2487 if (bgp_attr_flag_invalid (&attr_args
))
2489 bgp_attr_parse_ret_t ret
;
2490 ret
= bgp_attr_malformed (&attr_args
,
2491 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2493 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2498 /* OK check attribute and store it's value. */
2501 case BGP_ATTR_ORIGIN
:
2502 ret
= bgp_attr_origin (&attr_args
);
2504 case BGP_ATTR_AS_PATH
:
2505 ret
= bgp_attr_aspath (&attr_args
);
2507 case BGP_ATTR_AS4_PATH
:
2508 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2510 case BGP_ATTR_NEXT_HOP
:
2511 ret
= bgp_attr_nexthop (&attr_args
);
2513 case BGP_ATTR_MULTI_EXIT_DISC
:
2514 ret
= bgp_attr_med (&attr_args
);
2516 case BGP_ATTR_LOCAL_PREF
:
2517 ret
= bgp_attr_local_pref (&attr_args
);
2519 case BGP_ATTR_ATOMIC_AGGREGATE
:
2520 ret
= bgp_attr_atomic (&attr_args
);
2522 case BGP_ATTR_AGGREGATOR
:
2523 ret
= bgp_attr_aggregator (&attr_args
);
2525 case BGP_ATTR_AS4_AGGREGATOR
:
2526 ret
= bgp_attr_as4_aggregator (&attr_args
,
2528 &as4_aggregator_addr
);
2530 case BGP_ATTR_COMMUNITIES
:
2531 ret
= bgp_attr_community (&attr_args
);
2533 case BGP_ATTR_LARGE_COMMUNITIES
:
2534 ret
= bgp_attr_large_community (&attr_args
);
2536 case BGP_ATTR_ORIGINATOR_ID
:
2537 ret
= bgp_attr_originator_id (&attr_args
);
2539 case BGP_ATTR_CLUSTER_LIST
:
2540 ret
= bgp_attr_cluster_list (&attr_args
);
2542 case BGP_ATTR_MP_REACH_NLRI
:
2543 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2545 case BGP_ATTR_MP_UNREACH_NLRI
:
2546 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2548 case BGP_ATTR_EXT_COMMUNITIES
:
2549 ret
= bgp_attr_ext_communities (&attr_args
);
2554 case BGP_ATTR_ENCAP
:
2555 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2558 ret
= bgp_attr_unknown (&attr_args
);
2562 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2564 bgp_notify_send (peer
,
2565 BGP_NOTIFY_UPDATE_ERR
,
2566 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2567 ret
= BGP_ATTR_PARSE_ERROR
;
2570 /* If hard error occured immediately return to the caller. */
2571 if (ret
== BGP_ATTR_PARSE_ERROR
)
2573 zlog_warn ("%s: Attribute %s, parse error",
2575 LOOKUP (attr_str
, type
));
2577 aspath_unintern (&as4_path
);
2580 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2583 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2585 LOOKUP (attr_str
, type
));
2587 aspath_unintern (&as4_path
);
2591 /* Check the fetched length. */
2592 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2594 zlog_warn ("%s: BGP attribute %s, fetch error",
2595 peer
->host
, LOOKUP (attr_str
, type
));
2596 bgp_notify_send (peer
,
2597 BGP_NOTIFY_UPDATE_ERR
,
2598 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2600 aspath_unintern (&as4_path
);
2601 return BGP_ATTR_PARSE_ERROR
;
2605 /* Check final read pointer is same as end pointer. */
2606 if (BGP_INPUT_PNT (peer
) != endp
)
2608 zlog_warn ("%s: BGP attribute %s, length mismatch",
2609 peer
->host
, LOOKUP (attr_str
, type
));
2610 bgp_notify_send (peer
,
2611 BGP_NOTIFY_UPDATE_ERR
,
2612 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2614 aspath_unintern (&as4_path
);
2615 return BGP_ATTR_PARSE_ERROR
;
2618 /* Check all mandatory well-known attributes are present */
2620 bgp_attr_parse_ret_t ret
;
2621 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2624 aspath_unintern (&as4_path
);
2630 * At this place we can see whether we got AS4_PATH and/or
2631 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2632 * We can not do this before we've read all attributes because
2633 * the as4 handling does not say whether AS4_PATH has to be sent
2634 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2635 * in relationship to AGGREGATOR.
2636 * So, to be defensive, we are not relying on any order and read
2637 * all attributes first, including these 32bit ones, and now,
2638 * afterwards, we look what and if something is to be done for as4.
2640 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2643 /* actually... this doesn't ever return failure currently, but
2644 * better safe than sorry */
2645 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2646 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2647 as4_aggregator
, &as4_aggregator_addr
))
2649 bgp_notify_send (peer
,
2650 BGP_NOTIFY_UPDATE_ERR
,
2651 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2653 aspath_unintern (&as4_path
);
2654 return BGP_ATTR_PARSE_ERROR
;
2657 /* At this stage, we have done all fiddling with as4, and the
2658 * resulting info is in attr->aggregator resp. attr->aspath
2659 * so we can chuck as4_aggregator and as4_path alltogether in
2660 * order to save memory
2664 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2665 /* The flag that we got this is still there, but that does not
2670 * The "rest" of the code does nothing with as4_aggregator.
2671 * there is no memory attached specifically which is not part
2673 * so ignoring just means do nothing.
2676 * Finally do the checks on the aspath we did not do yet
2677 * because we waited for a potentially synthesized aspath.
2679 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2681 ret
= bgp_attr_aspath_check (peer
, attr
);
2682 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2687 /* Finally intern unknown attribute. */
2688 if (attr
->extra
->transit
)
2689 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2690 if (attr
->extra
->encap_subtlvs
)
2691 attr
->extra
->encap_subtlvs
= encap_intern (attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2693 if (attr
->extra
->vnc_subtlvs
)
2694 attr
->extra
->vnc_subtlvs
= encap_intern (attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2698 return BGP_ATTR_PARSE_PROCEED
;
2702 bgp_packet_mpattr_start (struct stream
*s
, afi_t afi
, safi_t safi
, afi_t nh_afi
,
2703 struct bpacket_attr_vec_arr
*vecarr
,
2710 /* Set extended bit always to encode the attribute length as 2 bytes */
2711 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2712 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2713 sizep
= stream_get_endp (s
);
2714 stream_putw (s
, 0); /* Marker: Attribute length. */
2717 /* Convert AFI, SAFI to values for packet. */
2718 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
2720 stream_putw (s
, pkt_afi
); /* AFI */
2721 stream_putc (s
, pkt_safi
); /* SAFI */
2730 case SAFI_MULTICAST
:
2731 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2733 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2736 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2737 stream_putc (s
, 12);
2738 stream_putl (s
, 0); /* RD = 0, per RFC */
2740 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2744 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2754 case SAFI_MULTICAST
:
2756 struct attr_extra
*attre
= attr
->extra
;
2758 assert (attr
->extra
);
2759 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2760 stream_putc (s
, attre
->mp_nexthop_len
);
2761 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2762 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2763 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2768 struct attr_extra
*attre
= attr
->extra
;
2770 assert (attr
->extra
);
2771 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2772 stream_putc (s
, 24);
2773 stream_putl (s
, 0); /* RD = 0, per RFC */
2775 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2776 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2777 stream_putc (s
, 48);
2778 stream_putl (s
, 0); /* RD = 0, per RFC */
2780 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2781 stream_putl (s
, 0); /* RD = 0, per RFC */
2783 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2788 assert (attr
->extra
);
2789 stream_putc (s
, IPV6_MAX_BYTELEN
);
2790 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2806 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2807 struct prefix
*p
, struct prefix_rd
*prd
,
2808 u_char
*tag
, int addpath_encode
,
2809 u_int32_t addpath_tx_id
)
2811 if (safi
== SAFI_MPLS_VPN
)
2814 stream_putl(s
, addpath_tx_id
);
2815 /* Tag, RD, Prefix write. */
2816 stream_putc (s
, p
->prefixlen
+ 88);
2817 stream_put (s
, tag
, 3);
2818 stream_put (s
, prd
->val
, 8);
2819 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2822 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
2826 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
2828 int size
= PSIZE (p
->prefixlen
);
2829 if (safi
== SAFI_MPLS_VPN
)
2835 * Encodes the tunnel encapsulation attribute,
2836 * and with ENABLE_BGP_VNC the VNC attribute which uses
2837 * almost the same TLV format
2840 bgp_packet_mpattr_tea(
2847 unsigned int attrlenfield
= 0;
2848 unsigned int attrhdrlen
= 0;
2849 struct bgp_attr_encap_subtlv
*subtlvs
;
2850 struct bgp_attr_encap_subtlv
*st
;
2851 const char *attrname
;
2853 if (!attr
|| !attr
->extra
)
2857 case BGP_ATTR_ENCAP
:
2858 attrname
= "Tunnel Encap";
2859 subtlvs
= attr
->extra
->encap_subtlvs
;
2862 * The tunnel encap attr has an "outer" tlv.
2864 * L = total length of subtlvs,
2865 * V = concatenated subtlvs.
2867 attrlenfield
= 2 + 2; /* T + L */
2868 attrhdrlen
= 1 + 1; /* subTLV T + L */
2874 subtlvs
= attr
->extra
->vnc_subtlvs
;
2875 attrlenfield
= 0; /* no outer T + L */
2876 attrhdrlen
= 2 + 2; /* subTLV T + L */
2885 /* if no tlvs, don't make attr */
2886 if (subtlvs
== NULL
)
2889 /* compute attr length */
2890 for (st
= subtlvs
; st
; st
= st
->next
) {
2891 attrlenfield
+= (attrhdrlen
+ st
->length
);
2894 if (attrlenfield
> 0xffff) {
2895 zlog_info ("%s attribute is too long (length=%d), can't send it",
2901 if (attrlenfield
> 0xff) {
2902 /* 2-octet length field */
2904 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2905 stream_putc (s
, attrtype
);
2906 stream_putw (s
, attrlenfield
& 0xffff);
2908 /* 1-octet length field */
2909 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
2910 stream_putc (s
, attrtype
);
2911 stream_putc (s
, attrlenfield
& 0xff);
2914 if (attrtype
== BGP_ATTR_ENCAP
) {
2915 /* write outer T+L */
2916 stream_putw(s
, attr
->extra
->encap_tunneltype
);
2917 stream_putw(s
, attrlenfield
- 4);
2920 /* write each sub-tlv */
2921 for (st
= subtlvs
; st
; st
= st
->next
) {
2922 if (attrtype
== BGP_ATTR_ENCAP
) {
2923 stream_putc (s
, st
->type
);
2924 stream_putc (s
, st
->length
);
2927 stream_putw (s
, st
->type
);
2928 stream_putw (s
, st
->length
);
2931 stream_put (s
, st
->value
, st
->length
);
2936 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
2938 /* Set MP attribute length. Don't count the (2) bytes used to encode
2940 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
2943 /* Make attribute packet. */
2945 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
2946 struct stream
*s
, struct attr
*attr
,
2947 struct bpacket_attr_vec_arr
*vecarr
,
2948 struct prefix
*p
, afi_t afi
, safi_t safi
,
2949 struct peer
*from
, struct prefix_rd
*prd
, u_char
*tag
,
2951 u_int32_t addpath_tx_id
)
2954 size_t aspath_sizep
;
2955 struct aspath
*aspath
;
2956 int send_as4_path
= 0;
2957 int send_as4_aggregator
= 0;
2958 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2963 /* Remember current pointer. */
2964 cp
= stream_get_endp (s
);
2966 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
2967 !peer_cap_enhe(peer
)))
2969 size_t mpattrlen_pos
= 0;
2971 mpattrlen_pos
= bgp_packet_mpattr_start(s
, afi
, safi
,
2972 (peer_cap_enhe(peer
) ? AFI_IP6
: afi
),
2974 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
2975 addpath_encode
, addpath_tx_id
);
2976 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2979 /* Origin attribute. */
2980 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2981 stream_putc (s
, BGP_ATTR_ORIGIN
);
2983 stream_putc (s
, attr
->origin
);
2985 /* AS path attribute. */
2987 /* If remote-peer is EBGP */
2988 if (peer
->sort
== BGP_PEER_EBGP
2989 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
2990 || attr
->aspath
->segments
== NULL
)
2991 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
2993 aspath
= aspath_dup (attr
->aspath
);
2995 /* Even though we may not be configured for confederations we may have
2996 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2997 aspath
= aspath_delete_confed_seq (aspath
);
2999 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
3001 /* Stuff our path CONFED_ID on the front */
3002 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
3006 if (peer
->change_local_as
) {
3007 /* If replace-as is specified, we only use the change_local_as when
3008 advertising routes. */
3009 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
3010 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3012 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
3014 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3018 else if (peer
->sort
== BGP_PEER_CONFED
)
3020 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
3021 aspath
= aspath_dup (attr
->aspath
);
3022 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
3025 aspath
= attr
->aspath
;
3027 /* If peer is not AS4 capable, then:
3028 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3029 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
3030 * types are in it (i.e. exclude them if they are there)
3031 * AND do this only if there is at least one asnum > 65535 in the path!
3032 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
3033 * all ASnums > 65535 to BGP_AS_TRANS
3036 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3037 stream_putc (s
, BGP_ATTR_AS_PATH
);
3038 aspath_sizep
= stream_get_endp (s
);
3040 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
3042 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3045 if (!use32bit
&& aspath_has_as4 (aspath
))
3046 send_as4_path
= 1; /* we'll do this later, at the correct place */
3048 /* Nexthop attribute. */
3049 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
))
3051 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
3053 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3054 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3055 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3057 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3059 else if (safi
== SAFI_UNICAST
&& peer_cap_enhe(from
))
3062 * Likely this is the case when an IPv4 prefix was received with
3063 * Extended Next-hop capability and now being advertised to
3065 * Setting the mandatory (ipv4) next-hop attribute here to enable
3066 * implicit next-hop self with correct (ipv4 address family).
3068 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3069 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3070 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
3072 stream_put_ipv4 (s
, 0);
3076 /* MED attribute. */
3077 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
3080 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3081 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3083 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
3086 /* Local preference. */
3087 if (peer
->sort
== BGP_PEER_IBGP
||
3088 peer
->sort
== BGP_PEER_CONFED
)
3090 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3091 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3093 stream_putl (s
, attr
->local_pref
);
3096 /* Atomic aggregate. */
3097 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3099 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3100 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3105 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3107 assert (attr
->extra
);
3109 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3110 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3111 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3115 /* AS4 capable peer */
3117 stream_putl (s
, attr
->extra
->aggregator_as
);
3121 /* 2-byte AS peer */
3124 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3125 if ( attr
->extra
->aggregator_as
> 65535 )
3127 stream_putw (s
, BGP_AS_TRANS
);
3129 /* we have to send AS4_AGGREGATOR, too.
3130 * we'll do that later in order to send attributes in ascending
3133 send_as4_aggregator
= 1;
3136 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
3138 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3141 /* Community attribute. */
3142 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3143 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
3145 if (attr
->community
->size
* 4 > 255)
3147 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3148 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3149 stream_putw (s
, attr
->community
->size
* 4);
3153 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3154 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3155 stream_putc (s
, attr
->community
->size
* 4);
3157 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3161 * Large Community attribute.
3164 CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_LARGE_COMMUNITY
)
3165 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
)))
3167 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3169 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3170 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3171 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3175 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3176 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3177 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3179 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3182 /* Route Reflector. */
3183 if (peer
->sort
== BGP_PEER_IBGP
3185 && from
->sort
== BGP_PEER_IBGP
)
3187 /* Originator ID. */
3188 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3189 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
3192 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3193 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
3195 stream_put_in_addr (s
, &from
->remote_id
);
3198 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3199 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
3201 if (attr
->extra
&& attr
->extra
->cluster
)
3203 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
3204 /* If this peer configuration's parent BGP has cluster_id. */
3205 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3206 stream_put_in_addr (s
, &bgp
->cluster_id
);
3208 stream_put_in_addr (s
, &bgp
->router_id
);
3209 stream_put (s
, attr
->extra
->cluster
->list
,
3210 attr
->extra
->cluster
->length
);
3215 /* If this peer configuration's parent BGP has cluster_id. */
3216 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3217 stream_put_in_addr (s
, &bgp
->cluster_id
);
3219 stream_put_in_addr (s
, &bgp
->router_id
);
3223 /* Extended Communities attribute. */
3224 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3225 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
3227 struct attr_extra
*attre
= attr
->extra
;
3231 if (peer
->sort
== BGP_PEER_IBGP
3232 || peer
->sort
== BGP_PEER_CONFED
)
3234 if (attre
->ecommunity
->size
* 8 > 255)
3236 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3237 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3238 stream_putw (s
, attre
->ecommunity
->size
* 8);
3242 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3243 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3244 stream_putc (s
, attre
->ecommunity
->size
* 8);
3246 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
3252 int ecom_tr_size
= 0;
3255 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3257 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3260 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3268 if (ecom_tr_size
* 8 > 255)
3270 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3271 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3272 stream_putw (s
, ecom_tr_size
* 8);
3276 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3277 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3278 stream_putc (s
, ecom_tr_size
* 8);
3281 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3283 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3286 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3289 stream_put (s
, pnt
, 8);
3295 if ( send_as4_path
)
3297 /* If the peer is NOT As4 capable, AND */
3298 /* there are ASnums > 65535 in path THEN
3299 * give out AS4_PATH */
3301 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3303 * Hm, I wonder... confederation things *should* only be at
3304 * the beginning of an aspath, right? Then we should use
3305 * aspath_delete_confed_seq for this, because it is already
3307 * Folks, talk to me: what is reasonable here!?
3309 aspath
= aspath_delete_confed_seq (aspath
);
3311 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3312 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3313 aspath_sizep
= stream_get_endp (s
);
3315 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3318 if (aspath
!= attr
->aspath
)
3319 aspath_free (aspath
);
3321 if ( send_as4_aggregator
)
3323 assert (attr
->extra
);
3325 /* send AS4_AGGREGATOR, at this place */
3326 /* this section of code moved here in order to ensure the correct
3327 * *ascending* order of attributes
3329 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3330 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3332 stream_putl (s
, attr
->extra
->aggregator_as
);
3333 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3336 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3337 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3339 /* Tunnel Encap attribute */
3340 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3344 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3348 /* Unknown transit attribute. */
3349 if (attr
->extra
&& attr
->extra
->transit
)
3350 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3352 /* Return total size of attribute. */
3353 return stream_get_endp (s
) - cp
;
3357 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3359 unsigned long attrlen_pnt
;
3363 /* Set extended bit always to encode the attribute length as 2 bytes */
3364 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3365 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3367 attrlen_pnt
= stream_get_endp (s
);
3368 stream_putw (s
, 0); /* Length of this attribute. */
3370 /* Convert AFI, SAFI to values for packet. */
3371 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
3373 stream_putw (s
, pkt_afi
);
3374 stream_putc (s
, pkt_safi
);
3380 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3381 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3382 u_char
*tag
, int addpath_encode
,
3383 u_int32_t addpath_tx_id
)
3385 if (safi
== SAFI_MPLS_VPN
)
3389 stream_putl(s
, addpath_tx_id
);
3391 stream_putc (s
, p
->prefixlen
+ 88);
3392 stream_put (s
, tag
, 3);
3393 stream_put (s
, prd
->val
, 8);
3394 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3397 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
3401 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3403 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3406 /* Initialization of attribute. */
3408 bgp_attr_init (void)
3421 bgp_attr_finish (void)
3425 community_finish ();
3426 ecommunity_finish ();
3427 lcommunity_finish ();
3433 /* Make attribute packet. */
3435 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3436 struct prefix
*prefix
)
3441 struct aspath
*aspath
;
3442 int addpath_encode
= 0;
3443 u_int32_t addpath_tx_id
= 0;
3445 /* Remember current pointer. */
3446 cp
= stream_get_endp (s
);
3448 /* Place holder of length. */
3451 /* Origin attribute. */
3452 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3453 stream_putc (s
, BGP_ATTR_ORIGIN
);
3455 stream_putc (s
, attr
->origin
);
3457 aspath
= attr
->aspath
;
3459 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3460 stream_putc (s
, BGP_ATTR_AS_PATH
);
3461 aspath_lenp
= stream_get_endp (s
);
3464 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3466 /* Nexthop attribute. */
3467 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3468 if(prefix
!= NULL
&& prefix
->family
!= AF_INET6
)
3470 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3471 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3473 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3476 /* MED attribute. */
3477 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3479 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3480 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3482 stream_putl (s
, attr
->med
);
3485 /* Local preference. */
3486 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3488 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3489 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3491 stream_putl (s
, attr
->local_pref
);
3494 /* Atomic aggregate. */
3495 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3497 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3498 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3503 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3505 assert (attr
->extra
);
3506 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3507 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3509 stream_putl (s
, attr
->extra
->aggregator_as
);
3510 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3513 /* Community attribute. */
3514 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3516 if (attr
->community
->size
* 4 > 255)
3518 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3519 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3520 stream_putw (s
, attr
->community
->size
* 4);
3524 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3525 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3526 stream_putc (s
, attr
->community
->size
* 4);
3528 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3531 /* Large Community attribute. */
3532 if (attr
->extra
&& attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
))
3534 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3536 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3537 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3538 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3542 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3543 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3544 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3547 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3550 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3551 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3552 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3553 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3556 struct attr_extra
*attre
= attr
->extra
;
3558 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3559 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3560 sizep
= stream_get_endp (s
);
3563 stream_putc (s
, 0); /* Marker: Attribute length. */
3564 stream_putw(s
, AFI_IP6
); /* AFI */
3565 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3568 stream_putc(s
, attre
->mp_nexthop_len
);
3569 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3570 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3571 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3577 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3579 /* Set MP attribute length. */
3580 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3583 /* Return total size of attribute. */
3584 len
= stream_get_endp (s
) - cp
- 2;
3585 stream_putw_at (s
, cp
, len
);