1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_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
[] =
58 { BGP_ATTR_ORIGIN
, "ORIGIN" },
59 { BGP_ATTR_AS_PATH
, "AS_PATH" },
60 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
61 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
62 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
63 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
64 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
65 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
66 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
67 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
68 { BGP_ATTR_DPA
, "DPA" },
69 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
70 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
71 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
72 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
73 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
74 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
75 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
76 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
77 { BGP_ATTR_ENCAP
, "ENCAP" },
79 { BGP_ATTR_VNC
, "VNC" },
81 { BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY" },
82 { BGP_ATTR_PREFIX_SID
, "PREFIX_SID" },
86 static const struct message attr_flag_str
[] =
88 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
89 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
90 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
91 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
92 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
96 static struct hash
*cluster_hash
;
99 cluster_hash_alloc (void *p
)
101 const struct cluster_list
*val
= (const struct cluster_list
*) p
;
102 struct cluster_list
*cluster
;
104 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
105 cluster
->length
= val
->length
;
109 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
110 memcpy (cluster
->list
, val
->list
, val
->length
);
113 cluster
->list
= NULL
;
120 /* Cluster list related functions. */
121 static struct cluster_list
*
122 cluster_parse (struct in_addr
* pnt
, int length
)
124 struct cluster_list tmp
;
125 struct cluster_list
*cluster
;
130 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
136 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
140 for (i
= 0; i
< cluster
->length
/ 4; i
++)
141 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
147 cluster_hash_key_make (void *p
)
149 const struct cluster_list
*cluster
= p
;
151 return jhash(cluster
->list
, cluster
->length
, 0);
155 cluster_hash_cmp (const void *p1
, const void *p2
)
157 const struct cluster_list
* cluster1
= p1
;
158 const struct cluster_list
* cluster2
= p2
;
160 return (cluster1
->length
== cluster2
->length
&&
161 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
165 cluster_free (struct cluster_list
*cluster
)
168 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
169 XFREE (MTYPE_CLUSTER
, cluster
);
172 static struct cluster_list
*
173 cluster_dup (struct cluster_list
*cluster
)
175 struct cluster_list
*new;
177 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
178 new->length
= cluster
->length
;
182 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
183 memcpy (new->list
, cluster
->list
, cluster
->length
);
191 static struct cluster_list
*
192 cluster_intern (struct cluster_list
*cluster
)
194 struct cluster_list
*find
;
196 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
203 cluster_unintern (struct cluster_list
*cluster
)
208 if (cluster
->refcnt
== 0)
210 hash_release (cluster_hash
, cluster
);
211 cluster_free (cluster
);
218 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
222 cluster_finish (void)
224 hash_clean (cluster_hash
, (void (*)(void *))cluster_free
);
225 hash_free (cluster_hash
);
229 static struct hash
*encap_hash
= NULL
;
231 static struct hash
*vnc_hash
= NULL
;
234 struct bgp_attr_encap_subtlv
*
235 encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
237 struct bgp_attr_encap_subtlv
*new;
238 struct bgp_attr_encap_subtlv
*tail
;
239 struct bgp_attr_encap_subtlv
*p
;
241 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
242 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
244 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
247 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
250 memcpy(tail
, p
, size
);
258 encap_free(struct bgp_attr_encap_subtlv
*p
)
260 struct bgp_attr_encap_subtlv
*next
;
264 XFREE(MTYPE_ENCAP_TLV
, p
);
270 bgp_attr_flush_encap(struct attr
*attr
)
272 if (!attr
|| !attr
->extra
)
275 if (attr
->extra
->encap_subtlvs
) {
276 encap_free(attr
->extra
->encap_subtlvs
);
277 attr
->extra
->encap_subtlvs
= NULL
;
280 if (attr
->extra
->vnc_subtlvs
) {
281 encap_free(attr
->extra
->vnc_subtlvs
);
282 attr
->extra
->vnc_subtlvs
= NULL
;
288 * Compare encap sub-tlv chains
293 * This algorithm could be made faster if needed
296 encap_same(struct bgp_attr_encap_subtlv
*h1
, struct bgp_attr_encap_subtlv
*h2
)
298 struct bgp_attr_encap_subtlv
*p
;
299 struct bgp_attr_encap_subtlv
*q
;
303 if (h1
== NULL
|| h2
== NULL
)
306 for (p
= h1
; p
; p
= p
->next
) {
307 for (q
= h2
; q
; q
= q
->next
) {
308 if ((p
->type
== q
->type
) &&
309 (p
->length
== q
->length
) &&
310 !memcmp(p
->value
, q
->value
, p
->length
)) {
319 for (p
= h2
; p
; p
= p
->next
) {
320 for (q
= h1
; q
; q
= q
->next
) {
321 if ((p
->type
== q
->type
) &&
322 (p
->length
== q
->length
) &&
323 !memcmp(p
->value
, q
->value
, p
->length
)) {
336 encap_hash_alloc (void *p
)
338 /* Encap structure is already allocated. */
350 static struct bgp_attr_encap_subtlv
*
351 encap_intern (struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
353 struct bgp_attr_encap_subtlv
*find
;
354 struct hash
*hash
= encap_hash
;
356 if (type
== VNC_SUBTLV_TYPE
)
360 find
= hash_get (hash
, encap
, encap_hash_alloc
);
369 encap_unintern (struct bgp_attr_encap_subtlv
**encapp
, encap_subtlv_type type
)
371 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
375 if (encap
->refcnt
== 0)
377 struct hash
*hash
= encap_hash
;
379 if (type
== VNC_SUBTLV_TYPE
)
382 hash_release (hash
, encap
);
389 encap_hash_key_make (void *p
)
391 const struct bgp_attr_encap_subtlv
* encap
= p
;
393 return jhash(encap
->value
, encap
->length
, 0);
397 encap_hash_cmp (const void *p1
, const void *p2
)
399 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
400 (struct bgp_attr_encap_subtlv
*)p2
);
406 encap_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
408 vnc_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
415 hash_clean (encap_hash
, (void (*)(void *))encap_free
);
416 hash_free (encap_hash
);
419 hash_clean (vnc_hash
, (void (*)(void *))encap_free
);
420 hash_free (vnc_hash
);
426 overlay_index_same(const struct attr_extra
*ae1
, const struct attr_extra
*ae2
)
434 return !memcmp(&(ae1
->evpn_overlay
), &(ae2
->evpn_overlay
), sizeof(struct overlay_index
));
437 /* Unknown transit attribute. */
438 static struct hash
*transit_hash
;
441 transit_free (struct transit
*transit
)
444 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
445 XFREE (MTYPE_TRANSIT
, transit
);
448 static struct transit
*
449 transit_dup (struct transit
*transit
)
453 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
454 new->length
= transit
->length
;
457 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
458 memcpy (new->val
, transit
->val
, transit
->length
);
467 transit_hash_alloc (void *p
)
469 /* Transit structure is already allocated. */
473 static struct transit
*
474 transit_intern (struct transit
*transit
)
476 struct transit
*find
;
478 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
480 transit_free (transit
);
487 transit_unintern (struct transit
*transit
)
492 if (transit
->refcnt
== 0)
494 hash_release (transit_hash
, transit
);
495 transit_free (transit
);
500 transit_hash_key_make (void *p
)
502 const struct transit
* transit
= p
;
504 return jhash(transit
->val
, transit
->length
, 0);
508 transit_hash_cmp (const void *p1
, const void *p2
)
510 const struct transit
* transit1
= p1
;
511 const struct transit
* transit2
= p2
;
513 return (transit1
->length
== transit2
->length
&&
514 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
520 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
524 transit_finish (void)
526 hash_clean (transit_hash
, (void (*)(void *))transit_free
);
527 hash_free (transit_hash
);
531 /* Attribute hash routines. */
532 static struct hash
*attrhash
;
534 static struct attr_extra
*
535 bgp_attr_extra_new (void)
537 struct attr_extra
*extra
;
538 extra
= XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
539 extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
544 bgp_attr_extra_free (struct attr
*attr
)
548 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
554 bgp_attr_extra_get (struct attr
*attr
)
557 attr
->extra
= bgp_attr_extra_new();
561 /* Shallow copy of an attribute
562 * Though, not so shallow that it doesn't copy the contents
563 * of the attr_extra pointed to by 'extra'
566 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
568 struct attr_extra
*extra
= new->extra
;
571 /* if caller provided attr_extra space, use it in any case.
573 * This is neccesary even if orig->extra equals NULL, because otherwise
574 * memory may be later allocated on the heap by bgp_attr_extra_get.
576 * That memory would eventually be leaked, because the caller must not
577 * call bgp_attr_extra_free if he provided attr_extra on the stack.
582 memset(new->extra
, 0, sizeof(struct attr_extra
));
584 *new->extra
= *orig
->extra
;
587 else if (orig
->extra
)
589 new->extra
= bgp_attr_extra_new();
590 *new->extra
= *orig
->extra
;
595 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
598 new->aspath
= aspath_dup(orig
->aspath
);
601 new->community
= community_dup(orig
->community
);
605 if (orig
->extra
->ecommunity
)
606 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
607 if (orig
->extra
->cluster
)
608 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
609 if (orig
->extra
->transit
)
610 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
611 if (orig
->extra
->encap_subtlvs
)
612 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
614 if (orig
->extra
->vnc_subtlvs
)
615 new->extra
->vnc_subtlvs
= encap_tlv_dup(orig
->extra
->vnc_subtlvs
);
621 bgp_attr_deep_free (struct attr
*attr
)
624 aspath_free(attr
->aspath
);
627 community_free(attr
->community
);
631 if (attr
->extra
->ecommunity
)
632 ecommunity_free(&attr
->extra
->ecommunity
);
633 if (attr
->extra
->cluster
)
634 cluster_free(attr
->extra
->cluster
);
635 if (attr
->extra
->transit
)
636 transit_free(attr
->extra
->transit
);
637 if (attr
->extra
->encap_subtlvs
)
638 encap_free(attr
->extra
->encap_subtlvs
);
640 if (attr
->extra
->vnc_subtlvs
)
641 encap_free(attr
->extra
->vnc_subtlvs
);
649 return attrhash
->count
;
653 attr_unknown_count (void)
655 return transit_hash
->count
;
659 attrhash_key_make (void *p
)
661 const struct attr
*attr
= (struct attr
*) p
;
662 const struct attr_extra
*extra
= attr
->extra
;
664 #define MIX(val) key = jhash_1word(val, key)
667 MIX(attr
->nexthop
.s_addr
);
669 MIX(attr
->local_pref
);
672 key
+= attr
->nexthop
.s_addr
;
674 key
+= attr
->local_pref
;
678 MIX(extra
->aggregator_as
);
679 MIX(extra
->aggregator_addr
.s_addr
);
681 MIX(extra
->mp_nexthop_global_in
.s_addr
);
682 MIX(extra
->originator_id
.s_addr
);
684 MIX(extra
->label_index
);
688 MIX(aspath_key_make (attr
->aspath
));
690 MIX(community_hash_make (attr
->community
));
694 if (extra
->lcommunity
)
695 MIX(lcommunity_hash_make (extra
->lcommunity
));
696 if (extra
->ecommunity
)
697 MIX(ecommunity_hash_make (extra
->ecommunity
));
699 MIX(cluster_hash_key_make (extra
->cluster
));
701 MIX(transit_hash_key_make (extra
->transit
));
702 if (extra
->encap_subtlvs
)
703 MIX(encap_hash_key_make (extra
->encap_subtlvs
));
705 if (extra
->vnc_subtlvs
)
706 MIX(encap_hash_key_make (extra
->vnc_subtlvs
));
708 MIX(extra
->mp_nexthop_len
);
709 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
710 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
717 attrhash_cmp (const void *p1
, const void *p2
)
719 const struct attr
* attr1
= p1
;
720 const struct attr
* attr2
= p2
;
722 if (attr1
->flag
== attr2
->flag
723 && attr1
->origin
== attr2
->origin
724 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
725 && attr1
->aspath
== attr2
->aspath
726 && attr1
->community
== attr2
->community
727 && attr1
->med
== attr2
->med
728 && attr1
->local_pref
== attr2
->local_pref
729 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
731 const struct attr_extra
*ae1
= attr1
->extra
;
732 const struct attr_extra
*ae2
= attr2
->extra
;
735 && ae1
->aggregator_as
== ae2
->aggregator_as
736 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
737 && ae1
->weight
== ae2
->weight
738 && ae1
->tag
== ae2
->tag
739 && ae1
->label_index
== ae2
->label_index
740 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
741 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
742 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
743 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
744 && ae1
->ecommunity
== ae2
->ecommunity
745 && ae1
->lcommunity
== ae2
->lcommunity
746 && ae1
->cluster
== ae2
->cluster
747 && ae1
->transit
== ae2
->transit
748 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
749 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
751 && encap_same(ae1
->vnc_subtlvs
, ae2
->vnc_subtlvs
)
753 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
)
754 && overlay_index_same(ae1
, ae2
))
758 /* neither attribute has extra attributes, so they're same */
768 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
772 * special for hash_clean below
775 attr_vfree (void *attr
)
777 bgp_attr_extra_free ((struct attr
*)attr
);
778 XFREE (MTYPE_ATTR
, attr
);
782 attrhash_finish (void)
784 hash_clean(attrhash
, attr_vfree
);
785 hash_free (attrhash
);
790 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
792 struct attr
*attr
= backet
->data
;
794 vty_outln (vty
, "attr[%ld] nexthop %s", attr
->refcnt
,
795 inet_ntoa(attr
->nexthop
));
799 attr_show_all (struct vty
*vty
)
801 hash_iterate (attrhash
,
802 (void (*)(struct hash_backet
*, void *))
803 attr_show_all_iterator
,
808 bgp_attr_hash_alloc (void *p
)
810 const struct attr
* val
= (const struct attr
*) p
;
813 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
817 attr
->extra
= bgp_attr_extra_new ();
818 *attr
->extra
= *val
->extra
;
819 if (val
->extra
->encap_subtlvs
) {
820 val
->extra
->encap_subtlvs
= NULL
;
823 if (val
->extra
->vnc_subtlvs
) {
824 val
->extra
->vnc_subtlvs
= NULL
;
832 /* Internet argument attribute. */
834 bgp_attr_intern (struct attr
*attr
)
838 /* Intern referenced strucutre. */
841 if (! attr
->aspath
->refcnt
)
842 attr
->aspath
= aspath_intern (attr
->aspath
);
844 attr
->aspath
->refcnt
++;
848 if (! attr
->community
->refcnt
)
849 attr
->community
= community_intern (attr
->community
);
851 attr
->community
->refcnt
++;
855 struct attr_extra
*attre
= attr
->extra
;
857 if (attre
->ecommunity
)
859 if (! attre
->ecommunity
->refcnt
)
860 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
862 attre
->ecommunity
->refcnt
++;
865 if (attre
->lcommunity
)
867 if (! attre
->lcommunity
->refcnt
)
868 attre
->lcommunity
= lcommunity_intern (attre
->lcommunity
);
870 attre
->lcommunity
->refcnt
++;
874 if (! attre
->cluster
->refcnt
)
875 attre
->cluster
= cluster_intern (attre
->cluster
);
877 attre
->cluster
->refcnt
++;
881 if (! attre
->transit
->refcnt
)
882 attre
->transit
= transit_intern (attre
->transit
);
884 attre
->transit
->refcnt
++;
886 if (attre
->encap_subtlvs
)
888 if (! attre
->encap_subtlvs
->refcnt
)
889 attre
->encap_subtlvs
= encap_intern (attre
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
891 attre
->encap_subtlvs
->refcnt
++;
894 if (attre
->vnc_subtlvs
)
896 if (! attre
->vnc_subtlvs
->refcnt
)
897 attre
->vnc_subtlvs
= encap_intern (attre
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
899 attre
->vnc_subtlvs
->refcnt
++;
904 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
911 * Increment the refcount on various structures that attr holds.
912 * Note on usage: call _only_ when the 'attr' object has already
913 * been 'intern'ed and exists in 'attrhash' table. The function
914 * serves to hold a reference to that (real) object.
915 * Note also that the caller can safely call bgp_attr_unintern()
916 * after calling bgp_attr_refcount(). That would release the
917 * reference and could result in a free() of the attr object.
920 bgp_attr_refcount (struct attr
*attr
)
922 /* Intern referenced strucutre. */
924 attr
->aspath
->refcnt
++;
927 attr
->community
->refcnt
++;
931 struct attr_extra
*attre
= attr
->extra
;
932 if (attre
->ecommunity
)
933 attre
->ecommunity
->refcnt
++;
936 attre
->cluster
->refcnt
++;
939 attre
->transit
->refcnt
++;
941 if (attre
->encap_subtlvs
)
942 attre
->encap_subtlvs
->refcnt
++;
945 if (attre
->vnc_subtlvs
)
946 attre
->vnc_subtlvs
->refcnt
++;
953 /* Make network statement's attribute. */
955 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
957 memset (attr
, 0, sizeof (struct attr
));
958 bgp_attr_extra_get (attr
);
960 attr
->origin
= origin
;
961 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
962 attr
->aspath
= aspath_empty ();
963 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
964 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
965 attr
->extra
->tag
= 0;
966 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
967 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
972 /* Create the attributes for an aggregate */
974 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
975 struct aspath
*aspath
,
976 struct community
*community
, int as_set
,
977 u_char atomic_aggregate
)
981 struct attr_extra attre
;
983 memset (&attr
, 0, sizeof (struct attr
));
984 memset (&attre
, 0, sizeof (struct attr_extra
));
987 /* Origin attribute. */
988 attr
.origin
= origin
;
989 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
991 /* AS path attribute. */
993 attr
.aspath
= aspath_intern (aspath
);
995 attr
.aspath
= aspath_empty ();
996 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
998 /* Next hop attribute. */
999 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1003 attr
.community
= community
;
1004 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1007 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1008 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1009 if (! as_set
|| atomic_aggregate
)
1010 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1011 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1012 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1013 attre
.aggregator_as
= bgp
->confed_id
;
1015 attre
.aggregator_as
= bgp
->as
;
1016 attre
.aggregator_addr
= bgp
->router_id
;
1018 new = bgp_attr_intern (&attr
);
1020 aspath_unintern (&new->aspath
);
1024 /* Unintern just the sub-components of the attr, but not the attr */
1026 bgp_attr_unintern_sub (struct attr
*attr
)
1028 /* aspath refcount shoud be decrement. */
1030 aspath_unintern (&attr
->aspath
);
1031 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
1033 if (attr
->community
)
1034 community_unintern (&attr
->community
);
1035 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
1039 if (attr
->extra
->ecommunity
)
1040 ecommunity_unintern (&attr
->extra
->ecommunity
);
1041 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
1043 if (attr
->extra
->lcommunity
)
1044 lcommunity_unintern (&attr
->extra
->lcommunity
);
1045 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
));
1047 if (attr
->extra
->cluster
)
1048 cluster_unintern (attr
->extra
->cluster
);
1049 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
1051 if (attr
->extra
->transit
)
1052 transit_unintern (attr
->extra
->transit
);
1054 if (attr
->extra
->encap_subtlvs
)
1055 encap_unintern (&attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1058 if (attr
->extra
->vnc_subtlvs
)
1059 encap_unintern (&attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1064 /* Free bgp attribute and aspath. */
1066 bgp_attr_unintern (struct attr
**pattr
)
1068 struct attr
*attr
= *pattr
;
1071 struct attr_extra tmp_extra
;
1073 /* Decrement attribute reference. */
1080 tmp
.extra
= &tmp_extra
;
1081 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
1084 /* If reference becomes zero then free attribute object. */
1085 if (attr
->refcnt
== 0)
1087 ret
= hash_release (attrhash
, attr
);
1088 assert (ret
!= NULL
);
1089 bgp_attr_extra_free (attr
);
1090 XFREE (MTYPE_ATTR
, attr
);
1094 bgp_attr_unintern_sub (&tmp
);
1098 bgp_attr_flush (struct attr
*attr
)
1100 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
1102 aspath_free (attr
->aspath
);
1103 attr
->aspath
= NULL
;
1105 if (attr
->community
&& ! attr
->community
->refcnt
)
1107 community_free (attr
->community
);
1108 attr
->community
= NULL
;
1112 struct attr_extra
*attre
= attr
->extra
;
1114 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
1115 ecommunity_free (&attre
->ecommunity
);
1116 if (attre
->lcommunity
&& ! attre
->lcommunity
->refcnt
)
1117 lcommunity_free (&attre
->lcommunity
);
1118 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
1120 cluster_free (attre
->cluster
);
1121 attre
->cluster
= NULL
;
1123 if (attre
->transit
&& ! attre
->transit
->refcnt
)
1125 transit_free (attre
->transit
);
1126 attre
->transit
= NULL
;
1128 if (attre
->encap_subtlvs
&& ! attre
->encap_subtlvs
->refcnt
)
1130 encap_free(attre
->encap_subtlvs
);
1131 attre
->encap_subtlvs
= NULL
;
1134 if (attre
->vnc_subtlvs
&& ! attre
->vnc_subtlvs
->refcnt
)
1136 encap_free(attre
->vnc_subtlvs
);
1137 attre
->vnc_subtlvs
= NULL
;
1143 /* Implement draft-scudder-idr-optional-transitive behaviour and
1144 * avoid resetting sessions for malformed attributes which are
1145 * are partial/optional and hence where the error likely was not
1146 * introduced by the sending neighbour.
1148 static bgp_attr_parse_ret_t
1149 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
1152 struct peer
*const peer
= args
->peer
;
1153 const u_int8_t flags
= args
->flags
;
1154 /* startp and length must be special-cased, as whether or not to
1155 * send the attribute data with the NOTIFY depends on the error,
1156 * the caller therefore signals this with the seperate length argument
1158 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1160 /* Only relax error handling for eBGP peers */
1161 if (peer
->sort
!= BGP_PEER_EBGP
)
1163 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1164 notify_datap
, length
);
1165 return BGP_ATTR_PARSE_ERROR
;
1169 /* Adjust the stream getp to the end of the attribute, in case we can
1170 * still proceed but the caller hasn't read all the attribute.
1172 stream_set_getp (BGP_INPUT (peer
),
1173 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
1176 switch (args
->type
) {
1177 /* where an attribute is relatively inconsequential, e.g. it does not
1178 * affect route selection, and can be safely ignored, then any such
1179 * attributes which are malformed should just be ignored and the route
1180 * processed as normal.
1182 case BGP_ATTR_AS4_AGGREGATOR
:
1183 case BGP_ATTR_AGGREGATOR
:
1184 case BGP_ATTR_ATOMIC_AGGREGATE
:
1185 return BGP_ATTR_PARSE_PROCEED
;
1187 /* Core attributes, particularly ones which may influence route
1188 * selection, should always cause session resets
1190 case BGP_ATTR_ORIGIN
:
1191 case BGP_ATTR_AS_PATH
:
1192 case BGP_ATTR_NEXT_HOP
:
1193 case BGP_ATTR_MULTI_EXIT_DISC
:
1194 case BGP_ATTR_LOCAL_PREF
:
1195 case BGP_ATTR_COMMUNITIES
:
1196 case BGP_ATTR_ORIGINATOR_ID
:
1197 case BGP_ATTR_CLUSTER_LIST
:
1198 case BGP_ATTR_MP_REACH_NLRI
:
1199 case BGP_ATTR_MP_UNREACH_NLRI
:
1200 case BGP_ATTR_EXT_COMMUNITIES
:
1201 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1202 notify_datap
, length
);
1203 return BGP_ATTR_PARSE_ERROR
;
1206 /* Partial optional attributes that are malformed should not cause
1207 * the whole session to be reset. Instead treat it as a withdrawal
1208 * of the routes, if possible.
1210 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1211 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1212 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1213 return BGP_ATTR_PARSE_WITHDRAW
;
1215 /* default to reset */
1216 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1219 /* Find out what is wrong with the path attribute flag bits and log the error.
1220 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1221 Extended Length. Checking O/T/P bits at once implies, that the attribute
1222 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1223 non-transitive" attribute. */
1225 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1226 u_int8_t desired_flags
/* how RFC says it must be */
1230 u_char real_flags
= args
->flags
;
1231 const u_int8_t attr_code
= args
->type
;
1233 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1234 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1235 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1238 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1239 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1242 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1243 lookup_msg(attr_str
, attr_code
, NULL
),
1244 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1245 attr_flag_str
[i
].str
);
1250 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1251 " (real flags 0x%x, desired 0x%x)",
1252 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1253 real_flags
, desired_flags
);
1257 /* Required flags for attributes. EXTLEN will be masked off when testing,
1258 * as will PARTIAL for optional+transitive attributes.
1260 const u_int8_t attr_flags_values
[] = {
1261 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1262 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1263 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1264 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1265 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1266 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1267 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1268 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1269 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1270 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1271 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1272 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1273 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1274 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1275 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1276 [BGP_ATTR_LARGE_COMMUNITIES
]= BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1277 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1279 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1282 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1284 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1285 const u_int8_t flags
= args
->flags
;
1286 const u_int8_t attr_code
= args
->type
;
1288 /* there may be attributes we don't know about */
1289 if (attr_code
> attr_flags_values_max
)
1291 if (attr_flags_values
[attr_code
] == 0)
1294 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1297 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1298 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1300 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1301 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1305 /* "For well-known attributes and for optional non-transitive attributes,
1306 * the Partial bit MUST be set to 0."
1308 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1310 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1312 zlog_err ("%s well-known attribute "
1313 "must NOT have the partial flag set (%x)",
1314 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1317 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1318 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1320 zlog_err ("%s optional + transitive attribute "
1321 "must NOT have the partial flag set (%x)",
1322 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1327 /* Optional transitive attributes may go through speakers that don't
1328 * reocgnise them and set the Partial bit.
1330 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1331 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1332 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1335 == attr_flags_values
[attr_code
])
1338 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1342 /* Get origin attribute of the update message. */
1343 static bgp_attr_parse_ret_t
1344 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1346 struct peer
*const peer
= args
->peer
;
1347 struct attr
*const attr
= args
->attr
;
1348 const bgp_size_t length
= args
->length
;
1350 /* If any recognized attribute has Attribute Length that conflicts
1351 with the expected length (based on the attribute type code), then
1352 the Error Subcode is set to Attribute Length Error. The Data
1353 field contains the erroneous attribute (type, length and
1357 zlog_err ("Origin attribute length is not one %d", length
);
1358 return bgp_attr_malformed (args
,
1359 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1363 /* Fetch origin attribute. */
1364 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1366 /* If the ORIGIN attribute has an undefined value, then the Error
1367 Subcode is set to Invalid Origin Attribute. The Data field
1368 contains the unrecognized attribute (type, length and value). */
1369 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1370 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1371 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1373 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1374 return bgp_attr_malformed (args
,
1375 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1379 /* Set oring attribute flag. */
1380 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1385 /* Parse AS path information. This function is wrapper of
1388 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1390 struct attr
*const attr
= args
->attr
;
1391 struct peer
*const peer
= args
->peer
;
1392 const bgp_size_t length
= args
->length
;
1395 * peer with AS4 => will get 4Byte ASnums
1396 * otherwise, will get 16 Bit
1398 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1399 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1401 /* In case of IBGP, length will be zero. */
1404 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1405 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1408 /* Set aspath attribute flag. */
1409 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1411 return BGP_ATTR_PARSE_PROCEED
;
1414 static bgp_attr_parse_ret_t
1415 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1417 /* These checks were part of bgp_attr_aspath, but with
1418 * as4 we should to check aspath things when
1419 * aspath synthesizing with as4_path has already taken place.
1420 * Otherwise we check ASPATH and use the synthesized thing, and that is
1422 * So do the checks later, i.e. here
1424 struct bgp
*bgp
= peer
->bgp
;
1425 struct aspath
*aspath
;
1427 /* Confederation sanity check. */
1428 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1429 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1431 zlog_err ("Malformed AS path from %s", peer
->host
);
1432 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1433 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1434 return BGP_ATTR_PARSE_ERROR
;
1437 /* First AS check for EBGP. */
1438 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1440 if (peer
->sort
== BGP_PEER_EBGP
1441 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1443 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1444 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1445 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1446 return BGP_ATTR_PARSE_ERROR
;
1450 /* local-as prepend */
1451 if (peer
->change_local_as
&&
1452 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1454 aspath
= aspath_dup (attr
->aspath
);
1455 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1456 aspath_unintern (&attr
->aspath
);
1457 attr
->aspath
= aspath_intern (aspath
);
1460 return BGP_ATTR_PARSE_PROCEED
;
1463 /* Parse AS4 path information. This function is another wrapper of
1466 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1468 struct peer
*const peer
= args
->peer
;
1469 struct attr
*const attr
= args
->attr
;
1470 const bgp_size_t length
= args
->length
;
1472 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1474 /* In case of IBGP, length will be zero. */
1477 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1478 return bgp_attr_malformed (args
,
1479 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1483 /* Set aspath attribute flag. */
1484 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1486 return BGP_ATTR_PARSE_PROCEED
;
1489 /* Nexthop attribute. */
1490 static bgp_attr_parse_ret_t
1491 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1493 struct peer
*const peer
= args
->peer
;
1494 struct attr
*const attr
= args
->attr
;
1495 const bgp_size_t length
= args
->length
;
1497 in_addr_t nexthop_h
, nexthop_n
;
1499 /* Check nexthop attribute length. */
1502 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1504 return bgp_attr_malformed (args
,
1505 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1509 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1510 attribute must result in a NOTIFICATION message (this is implemented below).
1511 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1512 logged locally (this is implemented somewhere else). The UPDATE message
1513 gets ignored in any of these cases. */
1514 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1515 nexthop_h
= ntohl (nexthop_n
);
1516 if ((IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1517 && !BGP_DEBUG (allow_martians
, ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1519 char buf
[INET_ADDRSTRLEN
];
1520 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1521 zlog_err ("Martian nexthop %s", buf
);
1522 return bgp_attr_malformed (args
,
1523 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1527 attr
->nexthop
.s_addr
= nexthop_n
;
1528 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1530 return BGP_ATTR_PARSE_PROCEED
;
1533 /* MED atrribute. */
1534 static bgp_attr_parse_ret_t
1535 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1537 struct peer
*const peer
= args
->peer
;
1538 struct attr
*const attr
= args
->attr
;
1539 const bgp_size_t length
= args
->length
;
1544 zlog_err ("MED attribute length isn't four [%d]", length
);
1546 return bgp_attr_malformed (args
,
1547 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1551 attr
->med
= stream_getl (peer
->ibuf
);
1553 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1555 return BGP_ATTR_PARSE_PROCEED
;
1558 /* Local preference attribute. */
1559 static bgp_attr_parse_ret_t
1560 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1562 struct peer
*const peer
= args
->peer
;
1563 struct attr
*const attr
= args
->attr
;
1564 const bgp_size_t length
= args
->length
;
1569 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1570 return bgp_attr_malformed (args
,
1571 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1575 /* If it is contained in an UPDATE message that is received from an
1576 external peer, then this attribute MUST be ignored by the
1577 receiving speaker. */
1578 if (peer
->sort
== BGP_PEER_EBGP
)
1580 stream_forward_getp (peer
->ibuf
, length
);
1581 return BGP_ATTR_PARSE_PROCEED
;
1584 attr
->local_pref
= stream_getl (peer
->ibuf
);
1586 /* Set atomic aggregate flag. */
1587 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1589 return BGP_ATTR_PARSE_PROCEED
;
1592 /* Atomic aggregate. */
1594 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1596 struct attr
*const attr
= args
->attr
;
1597 const bgp_size_t length
= args
->length
;
1602 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1603 return bgp_attr_malformed (args
,
1604 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1608 /* Set atomic aggregate flag. */
1609 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1611 return BGP_ATTR_PARSE_PROCEED
;
1614 /* Aggregator attribute */
1616 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1618 struct peer
*const peer
= args
->peer
;
1619 struct attr
*const attr
= args
->attr
;
1620 const bgp_size_t length
= args
->length
;
1623 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1625 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1626 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1629 if (length
!= wantedlen
)
1631 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1632 return bgp_attr_malformed (args
,
1633 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1637 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1638 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1640 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1641 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1643 /* Set atomic aggregate flag. */
1644 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1646 return BGP_ATTR_PARSE_PROCEED
;
1649 /* New Aggregator attribute */
1650 static bgp_attr_parse_ret_t
1651 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1652 as_t
*as4_aggregator_as
,
1653 struct in_addr
*as4_aggregator_addr
)
1655 struct peer
*const peer
= args
->peer
;
1656 struct attr
*const attr
= args
->attr
;
1657 const bgp_size_t length
= args
->length
;
1661 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1662 return bgp_attr_malformed (args
,
1663 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1667 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1668 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1670 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1672 return BGP_ATTR_PARSE_PROCEED
;
1675 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1677 static bgp_attr_parse_ret_t
1678 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1679 struct attr
*const attr
,
1680 struct aspath
*as4_path
, as_t as4_aggregator
,
1681 struct in_addr
*as4_aggregator_addr
)
1683 int ignore_as4_path
= 0;
1684 struct aspath
*newpath
;
1685 struct attr_extra
*attre
= attr
->extra
;
1689 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1690 * checked that all well-known, mandatory attributes were present.
1692 * Can only be a problem with peer itself - hard error
1694 return BGP_ATTR_PARSE_ERROR
;
1697 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1699 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1701 * It is worth a warning though, because the peer really
1702 * should not send them
1704 if (BGP_DEBUG(as4
, AS4
))
1706 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1707 zlog_debug ("[AS4] %s %s AS4_PATH",
1708 peer
->host
, "AS4 capable peer, yet it sent");
1710 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1711 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1712 peer
->host
, "AS4 capable peer, yet it sent");
1715 return BGP_ATTR_PARSE_PROCEED
;
1718 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1719 * because that may override AS4_PATH
1721 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1723 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1728 * if the as_number in aggregator is not AS_TRANS,
1729 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1730 * and the Aggregator shall be taken as
1731 * info on the aggregating node, and the AS_PATH
1732 * shall be taken as the AS_PATH
1734 * the Aggregator shall be ignored and the
1735 * AS4_AGGREGATOR shall be taken as the
1736 * Aggregating node and the AS_PATH is to be
1737 * constructed "as in all other cases"
1739 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1742 if ( BGP_DEBUG(as4
, AS4
))
1743 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1744 " send AGGREGATOR != AS_TRANS and"
1745 " AS4_AGGREGATOR, so ignore"
1746 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1747 ignore_as4_path
= 1;
1751 /* "New_aggregator shall be taken as aggregator" */
1752 attre
->aggregator_as
= as4_aggregator
;
1753 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1758 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1759 * That is bogus - but reading the conditions
1760 * we have to handle AS4_AGGREGATOR as if it were
1761 * AGGREGATOR in that case
1763 if ( BGP_DEBUG(as4
, AS4
))
1764 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1765 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1766 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1767 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1768 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1769 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1773 /* need to reconcile NEW_AS_PATH and AS_PATH */
1774 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1776 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1777 aspath_unintern (&attr
->aspath
);
1778 attr
->aspath
= aspath_intern (newpath
);
1780 return BGP_ATTR_PARSE_PROCEED
;
1783 /* Community attribute. */
1784 static bgp_attr_parse_ret_t
1785 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1787 struct peer
*const peer
= args
->peer
;
1788 struct attr
*const attr
= args
->attr
;
1789 const bgp_size_t length
= args
->length
;
1793 attr
->community
= NULL
;
1794 return BGP_ATTR_PARSE_PROCEED
;
1798 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1800 /* XXX: fix community_parse to use stream API and remove this */
1801 stream_forward_getp (peer
->ibuf
, length
);
1803 if (!attr
->community
)
1804 return bgp_attr_malformed (args
,
1805 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1808 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1810 return BGP_ATTR_PARSE_PROCEED
;
1813 /* Originator ID attribute. */
1814 static bgp_attr_parse_ret_t
1815 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1817 struct peer
*const peer
= args
->peer
;
1818 struct attr
*const attr
= args
->attr
;
1819 const bgp_size_t length
= args
->length
;
1824 zlog_err ("Bad originator ID length %d", length
);
1826 return bgp_attr_malformed (args
,
1827 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1831 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1832 = stream_get_ipv4 (peer
->ibuf
);
1834 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1836 return BGP_ATTR_PARSE_PROCEED
;
1839 /* Cluster list attribute. */
1840 static bgp_attr_parse_ret_t
1841 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1843 struct peer
*const peer
= args
->peer
;
1844 struct attr
*const attr
= args
->attr
;
1845 const bgp_size_t length
= args
->length
;
1850 zlog_err ("Bad cluster list length %d", length
);
1852 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1856 (bgp_attr_extra_get (attr
))->cluster
1857 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1859 /* XXX: Fix cluster_parse to use stream API and then remove this */
1860 stream_forward_getp (peer
->ibuf
, length
);
1862 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1864 return BGP_ATTR_PARSE_PROCEED
;
1867 /* Multiprotocol reachability information parse. */
1869 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1870 struct bgp_nlri
*mp_update
)
1874 safi_t pkt_safi
, safi
;
1875 bgp_size_t nlri_len
;
1878 struct peer
*const peer
= args
->peer
;
1879 struct attr
*const attr
= args
->attr
;
1880 const bgp_size_t length
= args
->length
;
1881 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1883 /* Set end of packet. */
1884 s
= BGP_INPUT(peer
);
1885 start
= stream_get_getp(s
);
1887 /* safe to read statically sized header? */
1888 #define BGP_MP_REACH_MIN_SIZE 5
1889 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1890 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1892 zlog_info ("%s: %s sent invalid length, %lu",
1893 __func__
, peer
->host
, (unsigned long)length
);
1894 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1897 /* Load AFI, SAFI. */
1898 pkt_afi
= stream_getw (s
);
1899 pkt_safi
= stream_getc (s
);
1901 /* Convert AFI, SAFI to internal values, check. */
1902 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
1904 /* Log if AFI or SAFI is unrecognized. This is not an error unless
1905 * the attribute is otherwise malformed.
1907 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1908 zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1909 peer
->host
, pkt_afi
, pkt_safi
);
1910 return BGP_ATTR_PARSE_ERROR
;
1913 /* Get nexthop length. */
1914 attre
->mp_nexthop_len
= stream_getc (s
);
1916 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1918 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1919 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1920 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1923 /* Nexthop length check. */
1924 switch (attre
->mp_nexthop_len
)
1926 case BGP_ATTR_NHLEN_IPV4
:
1927 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1928 /* Probably needed for RFC 2283 */
1929 if (attr
->nexthop
.s_addr
== 0)
1930 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1932 case BGP_ATTR_NHLEN_VPNV4
:
1933 stream_getl (s
); /* RD high */
1934 stream_getl (s
); /* RD low */
1935 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1937 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1938 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1939 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1941 stream_getl (s
); /* RD high */
1942 stream_getl (s
); /* RD low */
1944 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1946 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1947 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1948 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1950 stream_getl (s
); /* RD high */
1951 stream_getl (s
); /* RD low */
1953 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1954 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1956 stream_getl (s
); /* RD high */
1957 stream_getl (s
); /* RD low */
1959 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1960 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1962 char buf1
[INET6_ADDRSTRLEN
];
1963 char buf2
[INET6_ADDRSTRLEN
];
1965 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1966 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1968 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1969 buf1
, INET6_ADDRSTRLEN
),
1970 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1971 buf2
, INET6_ADDRSTRLEN
));
1973 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1977 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1978 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1979 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1984 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1985 __func__
, peer
->host
);
1986 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1991 if ((val
= stream_getc (s
)))
1992 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1996 /* must have nrli_len, what is left of the attribute */
1997 nlri_len
= LEN_LEFT
;
1998 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
2000 zlog_info ("%s: (%s) Failed to read NLRI",
2001 __func__
, peer
->host
);
2002 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2005 mp_update
->afi
= afi
;
2006 mp_update
->safi
= safi
;
2007 mp_update
->nlri
= stream_pnt (s
);
2008 mp_update
->length
= nlri_len
;
2010 stream_forward_getp (s
, nlri_len
);
2012 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
2014 return BGP_ATTR_PARSE_PROCEED
;
2018 /* Multiprotocol unreachable parse */
2020 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
2021 struct bgp_nlri
*mp_withdraw
)
2026 safi_t pkt_safi
, safi
;
2027 u_int16_t withdraw_len
;
2028 struct peer
*const peer
= args
->peer
;
2029 struct attr
*const attr
= args
->attr
;
2030 const bgp_size_t length
= args
->length
;
2034 #define BGP_MP_UNREACH_MIN_SIZE 3
2035 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2036 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2038 pkt_afi
= stream_getw (s
);
2039 pkt_safi
= stream_getc (s
);
2041 /* Convert AFI, SAFI to internal values, check. */
2042 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
2044 /* Log if AFI or SAFI is unrecognized. This is not an error unless
2045 * the attribute is otherwise malformed.
2047 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2048 zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
2049 peer
->host
, pkt_afi
, pkt_safi
);
2050 return BGP_ATTR_PARSE_ERROR
;
2053 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2055 mp_withdraw
->afi
= afi
;
2056 mp_withdraw
->safi
= safi
;
2057 mp_withdraw
->nlri
= stream_pnt (s
);
2058 mp_withdraw
->length
= withdraw_len
;
2060 stream_forward_getp (s
, withdraw_len
);
2062 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
2064 return BGP_ATTR_PARSE_PROCEED
;
2067 /* Large Community attribute. */
2068 static bgp_attr_parse_ret_t
2069 bgp_attr_large_community (struct bgp_attr_parser_args
*args
)
2071 struct peer
*const peer
= args
->peer
;
2072 struct attr
*const attr
= args
->attr
;
2073 const bgp_size_t length
= args
->length
;
2076 * Large community follows new attribute format.
2081 attr
->extra
->lcommunity
= NULL
;
2082 /* Empty extcomm doesn't seem to be invalid per se */
2083 return BGP_ATTR_PARSE_PROCEED
;
2086 (bgp_attr_extra_get (attr
))->lcommunity
=
2087 lcommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2088 /* XXX: fix ecommunity_parse to use stream API */
2089 stream_forward_getp (peer
->ibuf
, length
);
2091 if (attr
->extra
&& !attr
->extra
->lcommunity
)
2092 return bgp_attr_malformed (args
,
2093 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2096 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
);
2098 return BGP_ATTR_PARSE_PROCEED
;
2101 /* Extended Community attribute. */
2102 static bgp_attr_parse_ret_t
2103 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
2105 struct peer
*const peer
= args
->peer
;
2106 struct attr
*const attr
= args
->attr
;
2107 const bgp_size_t length
= args
->length
;
2112 attr
->extra
->ecommunity
= NULL
;
2113 /* Empty extcomm doesn't seem to be invalid per se */
2114 return BGP_ATTR_PARSE_PROCEED
;
2117 (bgp_attr_extra_get (attr
))->ecommunity
=
2118 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2119 /* XXX: fix ecommunity_parse to use stream API */
2120 stream_forward_getp (peer
->ibuf
, length
);
2122 if (attr
->extra
&& !attr
->extra
->ecommunity
)
2123 return bgp_attr_malformed (args
,
2124 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2127 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
2129 return BGP_ATTR_PARSE_PROCEED
;
2132 /* Parse Tunnel Encap attribute in an UPDATE */
2136 struct peer
*peer
, /* IN */
2137 bgp_size_t length
, /* IN: attr's length field */
2138 struct attr
*attr
, /* IN: caller already allocated */
2139 u_char flag
, /* IN: attr's flags field */
2143 struct attr_extra
*attre
= NULL
;
2144 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2145 uint16_t tunneltype
= 0;
2147 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2149 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2150 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
2152 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
2153 bgp_notify_send_with_data (peer
,
2154 BGP_NOTIFY_UPDATE_ERR
,
2155 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2160 if (BGP_ATTR_ENCAP
== type
) {
2161 /* read outer TLV type and length */
2162 uint16_t tlv_length
;
2165 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2166 bgp_notify_send_with_data(peer
,
2167 BGP_NOTIFY_UPDATE_ERR
,
2168 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2172 tunneltype
= stream_getw (BGP_INPUT (peer
));
2173 tlv_length
= stream_getw (BGP_INPUT (peer
));
2176 if (tlv_length
!= length
) {
2177 zlog_info ("%s: tlv_length(%d) != length(%d)",
2178 __func__
, tlv_length
, length
);
2182 while (length
>= 4) {
2183 uint16_t subtype
= 0;
2184 uint16_t sublength
= 0;
2185 struct bgp_attr_encap_subtlv
*tlv
;
2187 if (BGP_ATTR_ENCAP
== type
) {
2188 subtype
= stream_getc (BGP_INPUT (peer
));
2189 sublength
= stream_getc (BGP_INPUT (peer
));
2193 subtype
= stream_getw (BGP_INPUT (peer
));
2194 sublength
= stream_getw (BGP_INPUT (peer
));
2199 if (sublength
> length
) {
2200 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2202 bgp_notify_send_with_data (peer
,
2203 BGP_NOTIFY_UPDATE_ERR
,
2204 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2209 /* alloc and copy sub-tlv */
2210 /* TBD make sure these are freed when attributes are released */
2211 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
2212 tlv
->type
= subtype
;
2213 tlv
->length
= sublength
;
2214 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2215 length
-= sublength
;
2217 /* attach tlv to encap chain */
2219 attre
= bgp_attr_extra_get(attr
);
2220 if (BGP_ATTR_ENCAP
== type
) {
2221 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
2222 stlv_last
= stlv_last
->next
);
2224 stlv_last
->next
= tlv
;
2226 attre
->encap_subtlvs
= tlv
;
2230 for (stlv_last
= attre
->vnc_subtlvs
; stlv_last
&& stlv_last
->next
;
2231 stlv_last
= stlv_last
->next
);
2233 stlv_last
->next
= tlv
;
2235 attre
->vnc_subtlvs
= tlv
;
2240 stlv_last
->next
= tlv
;
2245 if (BGP_ATTR_ENCAP
== type
) {
2247 attre
= bgp_attr_extra_get(attr
);
2248 attre
->encap_tunneltype
= tunneltype
;
2252 /* spurious leftover data */
2253 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2254 bgp_notify_send_with_data (peer
,
2255 BGP_NOTIFY_UPDATE_ERR
,
2256 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2264 /* Prefix SID attribute
2265 * draft-ietf-idr-bgp-prefix-sid-05
2267 static bgp_attr_parse_ret_t
2268 bgp_attr_prefix_sid (struct bgp_attr_parser_args
*args
, struct bgp_nlri
*mp_update
)
2270 struct peer
*const peer
= args
->peer
;
2271 struct attr
*const attr
= args
->attr
;
2274 u_int32_t label_index
;
2275 struct in6_addr ipv6_sid
;
2276 u_int32_t srgb_base
;
2277 u_int32_t srgb_range
;
2280 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
);
2282 type
= stream_getc (peer
->ibuf
);
2283 length
= stream_getw (peer
->ibuf
);
2285 if (type
== BGP_PREFIX_SID_LABEL_INDEX
)
2287 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
)
2289 zlog_err ("Prefix SID label index length is %d instead of %d", length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2290 return bgp_attr_malformed (args
,
2291 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2295 /* Ignore flags and reserved */
2296 stream_getc (peer
->ibuf
);
2297 stream_getw (peer
->ibuf
);
2299 /* Fetch the label index and see if it is valid. */
2300 label_index
= stream_getl (peer
->ibuf
);
2301 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2302 return bgp_attr_malformed (args
,
2303 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2306 /* Store label index; subsequently, we'll check on address-family */
2307 (bgp_attr_extra_get (attr
))->label_index
= label_index
;
2310 * Ignore the Label index attribute unless received for labeled-unicast
2313 if (!mp_update
->length
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2314 attr
->extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
2317 /* Placeholder code for the IPv6 SID type */
2318 else if (type
== BGP_PREFIX_SID_IPV6
)
2320 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
)
2322 zlog_err ("Prefix SID IPv6 length is %d instead of %d", length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2323 return bgp_attr_malformed (args
,
2324 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2328 /* Ignore reserved */
2329 stream_getc (peer
->ibuf
);
2330 stream_getw (peer
->ibuf
);
2332 stream_get (&ipv6_sid
, peer
->ibuf
, 16);
2335 /* Placeholder code for the Originator SRGB type */
2336 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
)
2339 stream_getw (peer
->ibuf
);
2343 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)
2345 zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2346 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2347 return bgp_attr_malformed (args
,
2348 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2352 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2354 for (int i
= 0; i
< srgb_count
; i
++)
2356 stream_get (&srgb_base
, peer
->ibuf
, 3);
2357 stream_get (&srgb_range
, peer
->ibuf
, 3);
2361 return BGP_ATTR_PARSE_PROCEED
;
2364 /* BGP unknown attribute treatment. */
2365 static bgp_attr_parse_ret_t
2366 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2368 bgp_size_t total
= args
->total
;
2369 struct transit
*transit
;
2370 struct attr_extra
*attre
;
2371 struct peer
*const peer
= args
->peer
;
2372 struct attr
*const attr
= args
->attr
;
2373 u_char
*const startp
= args
->startp
;
2374 const u_char type
= args
->type
;
2375 const u_char flag
= args
->flags
;
2376 const bgp_size_t length
= args
->length
;
2378 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2379 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2380 peer
->host
, type
, length
);
2382 /* Forward read pointer of input stream. */
2383 stream_forward_getp (peer
->ibuf
, length
);
2385 /* If any of the mandatory well-known attributes are not recognized,
2386 then the Error Subcode is set to Unrecognized Well-known
2387 Attribute. The Data field contains the unrecognized attribute
2388 (type, length and value). */
2389 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2391 return bgp_attr_malformed (args
,
2392 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2396 /* Unrecognized non-transitive optional attributes must be quietly
2397 ignored and not passed along to other BGP peers. */
2398 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2399 return BGP_ATTR_PARSE_PROCEED
;
2401 /* If a path with recognized transitive optional attribute is
2402 accepted and passed along to other BGP peers and the Partial bit
2403 in the Attribute Flags octet is set to 1 by some previous AS, it
2404 is not set back to 0 by the current AS. */
2405 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2407 /* Store transitive attribute to the end of attr->transit. */
2408 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2409 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2411 transit
= attre
->transit
;
2414 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2415 transit
->length
+ total
);
2417 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2419 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2420 transit
->length
+= total
;
2422 return BGP_ATTR_PARSE_PROCEED
;
2425 /* Well-known attribute check. */
2427 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2431 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2433 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2434 return BGP_ATTR_PARSE_PROCEED
;
2436 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2437 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2438 are present, it should. Check for any other attribute being present
2441 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2442 return BGP_ATTR_PARSE_PROCEED
;
2444 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2445 type
= BGP_ATTR_ORIGIN
;
2447 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2448 type
= BGP_ATTR_AS_PATH
;
2450 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2451 * NLRI is empty. We can't easily check NLRI empty here though.
2453 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2454 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2455 type
= BGP_ATTR_NEXT_HOP
;
2457 if (peer
->sort
== BGP_PEER_IBGP
2458 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2459 type
= BGP_ATTR_LOCAL_PREF
;
2463 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2464 lookup_msg(attr_str
, type
, NULL
));
2465 bgp_notify_send_with_data (peer
,
2466 BGP_NOTIFY_UPDATE_ERR
,
2467 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2469 return BGP_ATTR_PARSE_ERROR
;
2471 return BGP_ATTR_PARSE_PROCEED
;
2474 /* Read attribute of update packet. This function is called from
2475 bgp_update_receive() in bgp_packet.c. */
2476 bgp_attr_parse_ret_t
2477 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2478 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2484 u_char
*startp
, *endp
;
2486 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2487 /* we need the as4_path only until we have synthesized the as_path with it */
2488 /* same goes for as4_aggregator */
2489 struct aspath
*as4_path
= NULL
;
2490 as_t as4_aggregator
= 0;
2491 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2493 /* Initialize bitmap. */
2494 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2496 /* End pointer of BGP attribute. */
2497 endp
= BGP_INPUT_PNT (peer
) + size
;
2499 /* Get attributes to the end of attribute length. */
2500 while (BGP_INPUT_PNT (peer
) < endp
)
2502 /* Check remaining length check.*/
2503 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2505 /* XXX warning: long int format, int arg (arg 5) */
2506 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2508 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2510 bgp_notify_send (peer
,
2511 BGP_NOTIFY_UPDATE_ERR
,
2512 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2513 return BGP_ATTR_PARSE_ERROR
;
2516 /* Fetch attribute flag and type. */
2517 startp
= BGP_INPUT_PNT (peer
);
2518 /* "The lower-order four bits of the Attribute Flags octet are
2519 unused. They MUST be zero when sent and MUST be ignored when
2521 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2522 type
= stream_getc (BGP_INPUT (peer
));
2524 /* Check whether Extended-Length applies and is in bounds */
2525 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2526 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2528 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2530 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2532 bgp_notify_send (peer
,
2533 BGP_NOTIFY_UPDATE_ERR
,
2534 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2535 return BGP_ATTR_PARSE_ERROR
;
2538 /* Check extended attribue length bit. */
2539 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2540 length
= stream_getw (BGP_INPUT (peer
));
2542 length
= stream_getc (BGP_INPUT (peer
));
2544 /* If any attribute appears more than once in the UPDATE
2545 message, then the Error Subcode is set to Malformed Attribute
2548 if (CHECK_BITMAP (seen
, type
))
2550 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2553 bgp_notify_send (peer
,
2554 BGP_NOTIFY_UPDATE_ERR
,
2555 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2556 return BGP_ATTR_PARSE_ERROR
;
2559 /* Set type to bitmap to check duplicate attribute. `type' is
2560 unsigned char so it never overflow bitmap range. */
2562 SET_BITMAP (seen
, type
);
2564 /* Overflow check. */
2565 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2567 if (attr_endp
> endp
)
2569 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
);
2570 bgp_notify_send_with_data (peer
,
2571 BGP_NOTIFY_UPDATE_ERR
,
2572 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2573 startp
, attr_endp
- startp
);
2574 return BGP_ATTR_PARSE_ERROR
;
2577 struct bgp_attr_parser_args attr_args
= {
2584 .total
= attr_endp
- startp
,
2588 /* If any recognized attribute has Attribute Flags that conflict
2589 with the Attribute Type Code, then the Error Subcode is set to
2590 Attribute Flags Error. The Data field contains the erroneous
2591 attribute (type, length and value). */
2592 if (bgp_attr_flag_invalid (&attr_args
))
2594 bgp_attr_parse_ret_t ret
;
2595 ret
= bgp_attr_malformed (&attr_args
,
2596 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2598 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2603 /* OK check attribute and store it's value. */
2606 case BGP_ATTR_ORIGIN
:
2607 ret
= bgp_attr_origin (&attr_args
);
2609 case BGP_ATTR_AS_PATH
:
2610 ret
= bgp_attr_aspath (&attr_args
);
2612 case BGP_ATTR_AS4_PATH
:
2613 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2615 case BGP_ATTR_NEXT_HOP
:
2616 ret
= bgp_attr_nexthop (&attr_args
);
2618 case BGP_ATTR_MULTI_EXIT_DISC
:
2619 ret
= bgp_attr_med (&attr_args
);
2621 case BGP_ATTR_LOCAL_PREF
:
2622 ret
= bgp_attr_local_pref (&attr_args
);
2624 case BGP_ATTR_ATOMIC_AGGREGATE
:
2625 ret
= bgp_attr_atomic (&attr_args
);
2627 case BGP_ATTR_AGGREGATOR
:
2628 ret
= bgp_attr_aggregator (&attr_args
);
2630 case BGP_ATTR_AS4_AGGREGATOR
:
2631 ret
= bgp_attr_as4_aggregator (&attr_args
,
2633 &as4_aggregator_addr
);
2635 case BGP_ATTR_COMMUNITIES
:
2636 ret
= bgp_attr_community (&attr_args
);
2638 case BGP_ATTR_LARGE_COMMUNITIES
:
2639 ret
= bgp_attr_large_community (&attr_args
);
2641 case BGP_ATTR_ORIGINATOR_ID
:
2642 ret
= bgp_attr_originator_id (&attr_args
);
2644 case BGP_ATTR_CLUSTER_LIST
:
2645 ret
= bgp_attr_cluster_list (&attr_args
);
2647 case BGP_ATTR_MP_REACH_NLRI
:
2648 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2650 case BGP_ATTR_MP_UNREACH_NLRI
:
2651 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2653 case BGP_ATTR_EXT_COMMUNITIES
:
2654 ret
= bgp_attr_ext_communities (&attr_args
);
2659 case BGP_ATTR_ENCAP
:
2660 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2662 case BGP_ATTR_PREFIX_SID
:
2663 ret
= bgp_attr_prefix_sid (&attr_args
, mp_update
);
2666 ret
= bgp_attr_unknown (&attr_args
);
2670 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2672 bgp_notify_send (peer
,
2673 BGP_NOTIFY_UPDATE_ERR
,
2674 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2675 ret
= BGP_ATTR_PARSE_ERROR
;
2678 /* If hard error occured immediately return to the caller. */
2679 if (ret
== BGP_ATTR_PARSE_ERROR
)
2681 zlog_warn ("%s: Attribute %s, parse error",
2683 lookup_msg(attr_str
, type
, NULL
));
2685 aspath_unintern (&as4_path
);
2688 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2691 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2693 lookup_msg(attr_str
, type
, NULL
));
2695 aspath_unintern (&as4_path
);
2699 /* Check the fetched length. */
2700 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2702 zlog_warn ("%s: BGP attribute %s, fetch error",
2703 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2704 bgp_notify_send (peer
,
2705 BGP_NOTIFY_UPDATE_ERR
,
2706 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2708 aspath_unintern (&as4_path
);
2709 return BGP_ATTR_PARSE_ERROR
;
2713 /* Check final read pointer is same as end pointer. */
2714 if (BGP_INPUT_PNT (peer
) != endp
)
2716 zlog_warn ("%s: BGP attribute %s, length mismatch",
2717 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2718 bgp_notify_send (peer
,
2719 BGP_NOTIFY_UPDATE_ERR
,
2720 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2722 aspath_unintern (&as4_path
);
2723 return BGP_ATTR_PARSE_ERROR
;
2726 /* Check all mandatory well-known attributes are present */
2728 bgp_attr_parse_ret_t ret
;
2729 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2732 aspath_unintern (&as4_path
);
2738 * At this place we can see whether we got AS4_PATH and/or
2739 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2740 * We can not do this before we've read all attributes because
2741 * the as4 handling does not say whether AS4_PATH has to be sent
2742 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2743 * in relationship to AGGREGATOR.
2744 * So, to be defensive, we are not relying on any order and read
2745 * all attributes first, including these 32bit ones, and now,
2746 * afterwards, we look what and if something is to be done for as4.
2748 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2751 /* actually... this doesn't ever return failure currently, but
2752 * better safe than sorry */
2753 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2754 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2755 as4_aggregator
, &as4_aggregator_addr
))
2757 bgp_notify_send (peer
,
2758 BGP_NOTIFY_UPDATE_ERR
,
2759 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2761 aspath_unintern (&as4_path
);
2762 return BGP_ATTR_PARSE_ERROR
;
2765 /* At this stage, we have done all fiddling with as4, and the
2766 * resulting info is in attr->aggregator resp. attr->aspath
2767 * so we can chuck as4_aggregator and as4_path alltogether in
2768 * order to save memory
2772 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2773 /* The flag that we got this is still there, but that does not
2778 * The "rest" of the code does nothing with as4_aggregator.
2779 * there is no memory attached specifically which is not part
2781 * so ignoring just means do nothing.
2784 * Finally do the checks on the aspath we did not do yet
2785 * because we waited for a potentially synthesized aspath.
2787 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2789 ret
= bgp_attr_aspath_check (peer
, attr
);
2790 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2795 /* Finally intern unknown attribute. */
2796 if (attr
->extra
->transit
)
2797 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2798 if (attr
->extra
->encap_subtlvs
)
2799 attr
->extra
->encap_subtlvs
= encap_intern (attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2801 if (attr
->extra
->vnc_subtlvs
)
2802 attr
->extra
->vnc_subtlvs
= encap_intern (attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2806 return BGP_ATTR_PARSE_PROCEED
;
2810 bgp_packet_mpattr_start (struct stream
*s
, struct peer
*peer
,
2811 afi_t afi
, safi_t safi
,
2812 struct bpacket_attr_vec_arr
*vecarr
,
2820 /* Set extended bit always to encode the attribute length as 2 bytes */
2821 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2822 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2823 sizep
= stream_get_endp (s
);
2824 stream_putw (s
, 0); /* Marker: Attribute length. */
2827 /* Convert AFI, SAFI to values for packet. */
2828 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
2830 stream_putw (s
, pkt_afi
); /* AFI */
2831 stream_putc (s
, pkt_safi
); /* SAFI */
2834 if (peer_cap_enhe(peer
, afi
, safi
)) {
2837 if (afi
== AFI_L2VPN
)
2839 else if (safi
== SAFI_LABELED_UNICAST
)
2842 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->extra
->mp_nexthop_len
);
2846 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2853 case SAFI_MULTICAST
:
2854 case SAFI_LABELED_UNICAST
:
2856 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2859 stream_putc (s
, 12);
2860 stream_putl (s
, 0); /* RD = 0, per RFC */
2862 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2866 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2876 case SAFI_MULTICAST
:
2877 case SAFI_LABELED_UNICAST
:
2879 struct attr_extra
*attre
= attr
->extra
;
2881 assert (attr
->extra
);
2883 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2884 stream_putc (s
, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2885 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2886 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2888 stream_putc (s
, IPV6_MAX_BYTELEN
);
2889 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2895 struct attr_extra
*attre
= attr
->extra
;
2897 assert (attr
->extra
);
2898 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2899 stream_putc (s
, 24);
2900 stream_putl (s
, 0); /* RD = 0, per RFC */
2902 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2903 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2904 stream_putc (s
, 48);
2905 stream_putl (s
, 0); /* RD = 0, per RFC */
2907 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2908 stream_putl (s
, 0); /* RD = 0, per RFC */
2910 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2915 assert (attr
->extra
);
2916 stream_putc (s
, IPV6_MAX_BYTELEN
);
2917 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2927 if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
)
2929 stream_putc (s
, 12);
2930 stream_putl (s
, 0); /* RD = 0, per RFC */
2932 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2934 else if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
)
2936 stream_putc (s
, 24);
2937 stream_putl (s
, 0); /* RD = 0, per RFC */
2939 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2941 else if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2943 stream_putc (s
, 48);
2944 stream_putl (s
, 0); /* RD = 0, per RFC */
2946 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2947 stream_putl (s
, 0); /* RD = 0, per RFC */
2949 stream_put (s
, &attr
->extra
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2966 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2967 struct prefix
*p
, struct prefix_rd
*prd
,
2968 u_char
*tag
, int addpath_encode
,
2969 u_int32_t addpath_tx_id
, struct attr
*attr
)
2971 if (safi
== SAFI_MPLS_VPN
)
2974 stream_putl(s
, addpath_tx_id
);
2975 /* Tag, RD, Prefix write. */
2976 stream_putc (s
, p
->prefixlen
+ 88);
2977 stream_put (s
, tag
, 3);
2978 stream_put (s
, prd
->val
, 8);
2979 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2981 else if (safi
== SAFI_EVPN
)
2983 bgp_packet_mpattr_route_type_5(s
, p
, prd
, tag
, attr
);
2985 else if (safi
== SAFI_LABELED_UNICAST
)
2987 /* Prefix write with label. */
2988 stream_put_labeled_prefix(s
, p
, tag
);
2991 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
2995 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
2997 int size
= PSIZE (p
->prefixlen
);
2998 if (safi
== SAFI_MPLS_VPN
)
3004 * Encodes the tunnel encapsulation attribute,
3005 * and with ENABLE_BGP_VNC the VNC attribute which uses
3006 * almost the same TLV format
3009 bgp_packet_mpattr_tea(
3016 unsigned int attrlenfield
= 0;
3017 unsigned int attrhdrlen
= 0;
3018 struct bgp_attr_encap_subtlv
*subtlvs
;
3019 struct bgp_attr_encap_subtlv
*st
;
3020 const char *attrname
;
3022 if (!attr
|| !attr
->extra
||
3023 (attrtype
== BGP_ATTR_ENCAP
&&
3024 (!attr
->extra
->encap_tunneltype
||
3025 attr
->extra
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3029 case BGP_ATTR_ENCAP
:
3030 attrname
= "Tunnel Encap";
3031 subtlvs
= attr
->extra
->encap_subtlvs
;
3032 if (subtlvs
== NULL
) /* nothing to do */
3035 * The tunnel encap attr has an "outer" tlv.
3037 * L = total length of subtlvs,
3038 * V = concatenated subtlvs.
3040 attrlenfield
= 2 + 2; /* T + L */
3041 attrhdrlen
= 1 + 1; /* subTLV T + L */
3047 subtlvs
= attr
->extra
->vnc_subtlvs
;
3048 if (subtlvs
== NULL
) /* nothing to do */
3050 attrlenfield
= 0; /* no outer T + L */
3051 attrhdrlen
= 2 + 2; /* subTLV T + L */
3059 /* compute attr length */
3060 for (st
= subtlvs
; st
; st
= st
->next
) {
3061 attrlenfield
+= (attrhdrlen
+ st
->length
);
3064 if (attrlenfield
> 0xffff) {
3065 zlog_info ("%s attribute is too long (length=%d), can't send it",
3071 if (attrlenfield
> 0xff) {
3072 /* 2-octet length field */
3074 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3075 stream_putc (s
, attrtype
);
3076 stream_putw (s
, attrlenfield
& 0xffff);
3078 /* 1-octet length field */
3079 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
3080 stream_putc (s
, attrtype
);
3081 stream_putc (s
, attrlenfield
& 0xff);
3084 if (attrtype
== BGP_ATTR_ENCAP
) {
3085 /* write outer T+L */
3086 stream_putw(s
, attr
->extra
->encap_tunneltype
);
3087 stream_putw(s
, attrlenfield
- 4);
3090 /* write each sub-tlv */
3091 for (st
= subtlvs
; st
; st
= st
->next
) {
3092 if (attrtype
== BGP_ATTR_ENCAP
) {
3093 stream_putc (s
, st
->type
);
3094 stream_putc (s
, st
->length
);
3097 stream_putw (s
, st
->type
);
3098 stream_putw (s
, st
->length
);
3101 stream_put (s
, st
->value
, st
->length
);
3106 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
3108 /* Set MP attribute length. Don't count the (2) bytes used to encode
3110 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
3113 /* Make attribute packet. */
3115 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
3116 struct stream
*s
, struct attr
*attr
,
3117 struct bpacket_attr_vec_arr
*vecarr
,
3118 struct prefix
*p
, afi_t afi
, safi_t safi
,
3119 struct peer
*from
, struct prefix_rd
*prd
, u_char
*tag
,
3121 u_int32_t addpath_tx_id
)
3124 size_t aspath_sizep
;
3125 struct aspath
*aspath
;
3126 int send_as4_path
= 0;
3127 int send_as4_aggregator
= 0;
3128 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3133 /* Remember current pointer. */
3134 cp
= stream_get_endp (s
);
3136 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
3137 !peer_cap_enhe(peer
, afi
, safi
)))
3139 size_t mpattrlen_pos
= 0;
3141 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
, vecarr
, attr
);
3142 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
3143 addpath_encode
, addpath_tx_id
, attr
);
3144 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3147 /* Origin attribute. */
3148 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3149 stream_putc (s
, BGP_ATTR_ORIGIN
);
3151 stream_putc (s
, attr
->origin
);
3153 /* AS path attribute. */
3155 /* If remote-peer is EBGP */
3156 if (peer
->sort
== BGP_PEER_EBGP
3157 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
3158 || attr
->aspath
->segments
== NULL
)
3159 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
3161 aspath
= aspath_dup (attr
->aspath
);
3163 /* Even though we may not be configured for confederations we may have
3164 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3165 aspath
= aspath_delete_confed_seq (aspath
);
3167 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
3169 /* Stuff our path CONFED_ID on the front */
3170 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
3174 if (peer
->change_local_as
) {
3175 /* If replace-as is specified, we only use the change_local_as when
3176 advertising routes. */
3177 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
3178 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3180 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
3182 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3186 else if (peer
->sort
== BGP_PEER_CONFED
)
3188 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
3189 aspath
= aspath_dup (attr
->aspath
);
3190 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
3193 aspath
= attr
->aspath
;
3195 /* If peer is not AS4 capable, then:
3196 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3197 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
3198 * types are in it (i.e. exclude them if they are there)
3199 * AND do this only if there is at least one asnum > 65535 in the path!
3200 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
3201 * all ASnums > 65535 to BGP_AS_TRANS
3204 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3205 stream_putc (s
, BGP_ATTR_AS_PATH
);
3206 aspath_sizep
= stream_get_endp (s
);
3208 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
3210 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3213 if (!use32bit
&& aspath_has_as4 (aspath
))
3214 send_as4_path
= 1; /* we'll do this later, at the correct place */
3216 /* Nexthop attribute. */
3217 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
, afi
, safi
))
3219 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
3221 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3222 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3223 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3225 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3227 else if (peer_cap_enhe(from
, afi
, safi
))
3230 * Likely this is the case when an IPv4 prefix was received with
3231 * Extended Next-hop capability and now being advertised to
3233 * Setting the mandatory (ipv4) next-hop attribute here to enable
3234 * implicit next-hop self with correct (ipv4 address family).
3236 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3237 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3238 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
3240 stream_put_ipv4 (s
, 0);
3244 /* MED attribute. */
3245 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
3248 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3249 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3251 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
3254 /* Local preference. */
3255 if (peer
->sort
== BGP_PEER_IBGP
||
3256 peer
->sort
== BGP_PEER_CONFED
)
3258 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3259 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3261 stream_putl (s
, attr
->local_pref
);
3264 /* Atomic aggregate. */
3265 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3267 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3268 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3273 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3275 assert (attr
->extra
);
3277 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3278 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3279 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3283 /* AS4 capable peer */
3285 stream_putl (s
, attr
->extra
->aggregator_as
);
3289 /* 2-byte AS peer */
3292 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3293 if ( attr
->extra
->aggregator_as
> 65535 )
3295 stream_putw (s
, BGP_AS_TRANS
);
3297 /* we have to send AS4_AGGREGATOR, too.
3298 * we'll do that later in order to send attributes in ascending
3301 send_as4_aggregator
= 1;
3304 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
3306 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3309 /* Community attribute. */
3310 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3311 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
3313 if (attr
->community
->size
* 4 > 255)
3315 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3316 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3317 stream_putw (s
, attr
->community
->size
* 4);
3321 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3322 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3323 stream_putc (s
, attr
->community
->size
* 4);
3325 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3329 * Large Community attribute.
3332 CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_LARGE_COMMUNITY
)
3333 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
)))
3335 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3337 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3338 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3339 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3343 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3344 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3345 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3347 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3350 /* Route Reflector. */
3351 if (peer
->sort
== BGP_PEER_IBGP
3353 && from
->sort
== BGP_PEER_IBGP
)
3355 /* Originator ID. */
3356 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3357 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
3360 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3361 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
3363 stream_put_in_addr (s
, &from
->remote_id
);
3366 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3367 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
3369 if (attr
->extra
&& attr
->extra
->cluster
)
3371 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
3372 /* If this peer configuration's parent BGP has cluster_id. */
3373 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3374 stream_put_in_addr (s
, &bgp
->cluster_id
);
3376 stream_put_in_addr (s
, &bgp
->router_id
);
3377 stream_put (s
, attr
->extra
->cluster
->list
,
3378 attr
->extra
->cluster
->length
);
3383 /* If this peer configuration's parent BGP has cluster_id. */
3384 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3385 stream_put_in_addr (s
, &bgp
->cluster_id
);
3387 stream_put_in_addr (s
, &bgp
->router_id
);
3391 /* Extended Communities attribute. */
3392 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3393 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
3395 struct attr_extra
*attre
= attr
->extra
;
3399 if (peer
->sort
== BGP_PEER_IBGP
3400 || peer
->sort
== BGP_PEER_CONFED
)
3402 if (attre
->ecommunity
->size
* 8 > 255)
3404 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3405 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3406 stream_putw (s
, attre
->ecommunity
->size
* 8);
3410 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3411 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3412 stream_putc (s
, attre
->ecommunity
->size
* 8);
3414 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
3420 int ecom_tr_size
= 0;
3423 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3425 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3428 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3436 if (ecom_tr_size
* 8 > 255)
3438 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3439 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3440 stream_putw (s
, ecom_tr_size
* 8);
3444 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3445 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3446 stream_putc (s
, ecom_tr_size
* 8);
3449 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3451 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3454 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3457 stream_put (s
, pnt
, 8);
3463 /* Label index attribute. */
3464 if (safi
== SAFI_LABELED_UNICAST
)
3466 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3468 u_int32_t label_index
;
3470 assert (attr
->extra
);
3471 label_index
= attr
->extra
->label_index
;
3473 if (label_index
!= BGP_INVALID_LABEL_INDEX
)
3475 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3476 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3477 stream_putc (s
, 10);
3478 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3479 stream_putw (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3480 stream_putc (s
, 0); // reserved
3481 stream_putw (s
, 0); // flags
3482 stream_putl (s
, label_index
);
3487 if ( send_as4_path
)
3489 /* If the peer is NOT As4 capable, AND */
3490 /* there are ASnums > 65535 in path THEN
3491 * give out AS4_PATH */
3493 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3495 * Hm, I wonder... confederation things *should* only be at
3496 * the beginning of an aspath, right? Then we should use
3497 * aspath_delete_confed_seq for this, because it is already
3499 * Folks, talk to me: what is reasonable here!?
3501 aspath
= aspath_delete_confed_seq (aspath
);
3503 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3504 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3505 aspath_sizep
= stream_get_endp (s
);
3507 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3510 if (aspath
!= attr
->aspath
)
3511 aspath_free (aspath
);
3513 if ( send_as4_aggregator
)
3515 assert (attr
->extra
);
3517 /* send AS4_AGGREGATOR, at this place */
3518 /* this section of code moved here in order to ensure the correct
3519 * *ascending* order of attributes
3521 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3522 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3524 stream_putl (s
, attr
->extra
->aggregator_as
);
3525 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3528 if (((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3529 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
)) ||
3530 (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3532 /* Tunnel Encap attribute */
3533 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3537 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3541 /* Unknown transit attribute. */
3542 if (attr
->extra
&& attr
->extra
->transit
)
3543 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3545 /* Return total size of attribute. */
3546 return stream_get_endp (s
) - cp
;
3550 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3552 unsigned long attrlen_pnt
;
3556 /* Set extended bit always to encode the attribute length as 2 bytes */
3557 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3558 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3560 attrlen_pnt
= stream_get_endp (s
);
3561 stream_putw (s
, 0); /* Length of this attribute. */
3563 /* Convert AFI, SAFI to values for packet. */
3564 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
3566 stream_putw (s
, pkt_afi
);
3567 stream_putc (s
, pkt_safi
);
3573 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3574 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3575 u_char
*tag
, int addpath_encode
,
3576 u_int32_t addpath_tx_id
, struct attr
*attr
)
3578 u_char wlabel
[3] = {0x80, 0x00, 0x00};
3580 if (safi
== SAFI_LABELED_UNICAST
)
3583 return bgp_packet_mpattr_prefix (s
, afi
, safi
, p
, prd
,
3584 tag
, addpath_encode
, addpath_tx_id
, attr
);
3588 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3590 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3593 /* Initialization of attribute. */
3595 bgp_attr_init (void)
3608 bgp_attr_finish (void)
3612 community_finish ();
3613 ecommunity_finish ();
3614 lcommunity_finish ();
3620 /* Make attribute packet. */
3622 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3623 struct prefix
*prefix
)
3628 struct aspath
*aspath
;
3629 int addpath_encode
= 0;
3630 u_int32_t addpath_tx_id
= 0;
3632 /* Remember current pointer. */
3633 cp
= stream_get_endp (s
);
3635 /* Place holder of length. */
3638 /* Origin attribute. */
3639 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3640 stream_putc (s
, BGP_ATTR_ORIGIN
);
3642 stream_putc (s
, attr
->origin
);
3644 aspath
= attr
->aspath
;
3646 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3647 stream_putc (s
, BGP_ATTR_AS_PATH
);
3648 aspath_lenp
= stream_get_endp (s
);
3651 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3653 /* Nexthop attribute. */
3654 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3655 if(prefix
!= NULL
&& prefix
->family
!= AF_INET6
)
3657 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3658 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3660 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3663 /* MED attribute. */
3664 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3666 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3667 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3669 stream_putl (s
, attr
->med
);
3672 /* Local preference. */
3673 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3675 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3676 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3678 stream_putl (s
, attr
->local_pref
);
3681 /* Atomic aggregate. */
3682 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3684 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3685 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3690 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3692 assert (attr
->extra
);
3693 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3694 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3696 stream_putl (s
, attr
->extra
->aggregator_as
);
3697 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3700 /* Community attribute. */
3701 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3703 if (attr
->community
->size
* 4 > 255)
3705 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3706 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3707 stream_putw (s
, attr
->community
->size
* 4);
3711 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3712 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3713 stream_putc (s
, attr
->community
->size
* 4);
3715 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3718 /* Large Community attribute. */
3719 if (attr
->extra
&& attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
))
3721 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3723 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3724 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3725 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3729 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3730 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3731 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3734 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3737 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3738 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3739 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3740 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3743 struct attr_extra
*attre
= attr
->extra
;
3745 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3746 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3747 sizep
= stream_get_endp (s
);
3750 stream_putc (s
, 0); /* Marker: Attribute length. */
3751 stream_putw(s
, AFI_IP6
); /* AFI */
3752 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3755 stream_putc(s
, attre
->mp_nexthop_len
);
3756 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3757 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3758 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3764 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3766 /* Set MP attribute length. */
3767 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3771 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3773 assert (attr
->extra
);
3775 if (attr
->extra
->label_index
!= BGP_INVALID_LABEL_INDEX
)
3777 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3778 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3779 stream_putc (s
, 10);
3780 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3781 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3782 stream_putc (s
, 0); // reserved
3783 stream_putw (s
, 0); // flags
3784 stream_putl (s
, attr
->extra
->label_index
);
3788 /* Return total size of attribute. */
3789 len
= stream_get_endp (s
) - cp
- 2;
3790 stream_putw_at (s
, cp
, len
);