1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_label.h"
43 #include "bgpd/bgp_packet.h"
44 #include "bgpd/bgp_ecommunity.h"
45 #include "bgpd/bgp_lcommunity.h"
46 #include "bgpd/bgp_updgrp.h"
47 #include "bgpd/bgp_encap_types.h"
49 # include "bgpd/rfapi/bgp_rfapi_cfg.h"
50 # include "bgp_encap_types.h"
51 # include "bgp_vnc_types.h"
53 #include "bgp_encap_types.h"
56 /* Attribute strings for logging. */
57 static const struct message attr_str
[] =
59 { BGP_ATTR_ORIGIN
, "ORIGIN" },
60 { BGP_ATTR_AS_PATH
, "AS_PATH" },
61 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
62 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
63 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
64 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
65 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
66 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
67 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
68 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
69 { BGP_ATTR_DPA
, "DPA" },
70 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
71 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
72 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
73 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
74 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
75 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
76 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
77 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
78 { BGP_ATTR_ENCAP
, "ENCAP" },
80 { BGP_ATTR_VNC
, "VNC" },
82 { BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY" },
83 { BGP_ATTR_PREFIX_SID
, "PREFIX_SID" }
85 static const int attr_str_max
= array_size(attr_str
);
87 static const struct message attr_flag_str
[] =
89 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
90 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
91 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
92 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
93 { 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
;
540 extra
->label
= MPLS_INVALID_LABEL
;
545 bgp_attr_extra_free (struct attr
*attr
)
549 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
555 bgp_attr_extra_get (struct attr
*attr
)
558 attr
->extra
= bgp_attr_extra_new();
562 /* Shallow copy of an attribute
563 * Though, not so shallow that it doesn't copy the contents
564 * of the attr_extra pointed to by 'extra'
567 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
569 struct attr_extra
*extra
= new->extra
;
572 /* if caller provided attr_extra space, use it in any case.
574 * This is neccesary even if orig->extra equals NULL, because otherwise
575 * memory may be later allocated on the heap by bgp_attr_extra_get.
577 * That memory would eventually be leaked, because the caller must not
578 * call bgp_attr_extra_free if he provided attr_extra on the stack.
583 memset(new->extra
, 0, sizeof(struct attr_extra
));
584 new->extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
585 new->extra
->label
= MPLS_INVALID_LABEL
;
588 *new->extra
= *orig
->extra
;
591 else if (orig
->extra
)
593 new->extra
= bgp_attr_extra_new();
594 *new->extra
= *orig
->extra
;
599 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
602 new->aspath
= aspath_dup(orig
->aspath
);
605 new->community
= community_dup(orig
->community
);
609 if (orig
->extra
->ecommunity
)
610 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
611 if (orig
->extra
->cluster
)
612 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
613 if (orig
->extra
->transit
)
614 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
615 if (orig
->extra
->encap_subtlvs
)
616 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
618 if (orig
->extra
->vnc_subtlvs
)
619 new->extra
->vnc_subtlvs
= encap_tlv_dup(orig
->extra
->vnc_subtlvs
);
625 bgp_attr_deep_free (struct attr
*attr
)
628 aspath_free(attr
->aspath
);
631 community_free(attr
->community
);
635 if (attr
->extra
->ecommunity
)
636 ecommunity_free(&attr
->extra
->ecommunity
);
637 if (attr
->extra
->cluster
)
638 cluster_free(attr
->extra
->cluster
);
639 if (attr
->extra
->transit
)
640 transit_free(attr
->extra
->transit
);
641 if (attr
->extra
->encap_subtlvs
)
642 encap_free(attr
->extra
->encap_subtlvs
);
644 if (attr
->extra
->vnc_subtlvs
)
645 encap_free(attr
->extra
->vnc_subtlvs
);
653 return attrhash
->count
;
657 attr_unknown_count (void)
659 return transit_hash
->count
;
663 attrhash_key_make (void *p
)
665 const struct attr
*attr
= (struct attr
*) p
;
666 const struct attr_extra
*extra
= attr
->extra
;
668 #define MIX(val) key = jhash_1word(val, key)
671 MIX(attr
->nexthop
.s_addr
);
673 MIX(attr
->local_pref
);
676 key
+= attr
->nexthop
.s_addr
;
678 key
+= attr
->local_pref
;
682 MIX(extra
->aggregator_as
);
683 MIX(extra
->aggregator_addr
.s_addr
);
685 MIX(extra
->mp_nexthop_global_in
.s_addr
);
686 MIX(extra
->originator_id
.s_addr
);
689 MIX(extra
->label_index
);
693 MIX(aspath_key_make (attr
->aspath
));
695 MIX(community_hash_make (attr
->community
));
699 if (extra
->lcommunity
)
700 MIX(lcommunity_hash_make (extra
->lcommunity
));
701 if (extra
->ecommunity
)
702 MIX(ecommunity_hash_make (extra
->ecommunity
));
704 MIX(cluster_hash_key_make (extra
->cluster
));
706 MIX(transit_hash_key_make (extra
->transit
));
707 if (extra
->encap_subtlvs
)
708 MIX(encap_hash_key_make (extra
->encap_subtlvs
));
710 if (extra
->vnc_subtlvs
)
711 MIX(encap_hash_key_make (extra
->vnc_subtlvs
));
713 MIX(extra
->mp_nexthop_len
);
714 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
715 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
722 attrhash_cmp (const void *p1
, const void *p2
)
724 const struct attr
* attr1
= p1
;
725 const struct attr
* attr2
= p2
;
727 if (attr1
->flag
== attr2
->flag
728 && attr1
->origin
== attr2
->origin
729 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
730 && attr1
->aspath
== attr2
->aspath
731 && attr1
->community
== attr2
->community
732 && attr1
->med
== attr2
->med
733 && attr1
->local_pref
== attr2
->local_pref
734 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
736 const struct attr_extra
*ae1
= attr1
->extra
;
737 const struct attr_extra
*ae2
= attr2
->extra
;
740 && ae1
->aggregator_as
== ae2
->aggregator_as
741 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
742 && ae1
->weight
== ae2
->weight
743 && ae1
->tag
== ae2
->tag
744 && ae1
->label_index
== ae2
->label_index
745 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
746 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
747 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
748 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
749 && ae1
->ecommunity
== ae2
->ecommunity
750 && ae1
->lcommunity
== ae2
->lcommunity
751 && ae1
->cluster
== ae2
->cluster
752 && ae1
->transit
== ae2
->transit
753 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
754 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
756 && encap_same(ae1
->vnc_subtlvs
, ae2
->vnc_subtlvs
)
758 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
)
759 && overlay_index_same(ae1
, ae2
))
763 /* neither attribute has extra attributes, so they're same */
773 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
777 * special for hash_clean below
780 attr_vfree (void *attr
)
782 bgp_attr_extra_free ((struct attr
*)attr
);
783 XFREE (MTYPE_ATTR
, attr
);
787 attrhash_finish (void)
789 hash_clean(attrhash
, attr_vfree
);
790 hash_free (attrhash
);
795 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
797 struct attr
*attr
= backet
->data
;
799 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
800 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
804 attr_show_all (struct vty
*vty
)
806 hash_iterate (attrhash
,
807 (void (*)(struct hash_backet
*, void *))
808 attr_show_all_iterator
,
813 bgp_attr_hash_alloc (void *p
)
815 const struct attr
* val
= (const struct attr
*) p
;
818 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
822 attr
->extra
= bgp_attr_extra_new ();
823 *attr
->extra
= *val
->extra
;
824 if (val
->extra
->encap_subtlvs
) {
825 val
->extra
->encap_subtlvs
= NULL
;
828 if (val
->extra
->vnc_subtlvs
) {
829 val
->extra
->vnc_subtlvs
= NULL
;
837 /* Internet argument attribute. */
839 bgp_attr_intern (struct attr
*attr
)
843 /* Intern referenced strucutre. */
846 if (! attr
->aspath
->refcnt
)
847 attr
->aspath
= aspath_intern (attr
->aspath
);
849 attr
->aspath
->refcnt
++;
853 if (! attr
->community
->refcnt
)
854 attr
->community
= community_intern (attr
->community
);
856 attr
->community
->refcnt
++;
860 struct attr_extra
*attre
= attr
->extra
;
862 if (attre
->ecommunity
)
864 if (! attre
->ecommunity
->refcnt
)
865 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
867 attre
->ecommunity
->refcnt
++;
870 if (attre
->lcommunity
)
872 if (! attre
->lcommunity
->refcnt
)
873 attre
->lcommunity
= lcommunity_intern (attre
->lcommunity
);
875 attre
->lcommunity
->refcnt
++;
879 if (! attre
->cluster
->refcnt
)
880 attre
->cluster
= cluster_intern (attre
->cluster
);
882 attre
->cluster
->refcnt
++;
886 if (! attre
->transit
->refcnt
)
887 attre
->transit
= transit_intern (attre
->transit
);
889 attre
->transit
->refcnt
++;
891 if (attre
->encap_subtlvs
)
893 if (! attre
->encap_subtlvs
->refcnt
)
894 attre
->encap_subtlvs
= encap_intern (attre
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
896 attre
->encap_subtlvs
->refcnt
++;
899 if (attre
->vnc_subtlvs
)
901 if (! attre
->vnc_subtlvs
->refcnt
)
902 attre
->vnc_subtlvs
= encap_intern (attre
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
904 attre
->vnc_subtlvs
->refcnt
++;
909 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
916 * Increment the refcount on various structures that attr holds.
917 * Note on usage: call _only_ when the 'attr' object has already
918 * been 'intern'ed and exists in 'attrhash' table. The function
919 * serves to hold a reference to that (real) object.
920 * Note also that the caller can safely call bgp_attr_unintern()
921 * after calling bgp_attr_refcount(). That would release the
922 * reference and could result in a free() of the attr object.
925 bgp_attr_refcount (struct attr
*attr
)
927 /* Intern referenced strucutre. */
929 attr
->aspath
->refcnt
++;
932 attr
->community
->refcnt
++;
936 struct attr_extra
*attre
= attr
->extra
;
937 if (attre
->ecommunity
)
938 attre
->ecommunity
->refcnt
++;
941 attre
->cluster
->refcnt
++;
944 attre
->transit
->refcnt
++;
946 if (attre
->encap_subtlvs
)
947 attre
->encap_subtlvs
->refcnt
++;
950 if (attre
->vnc_subtlvs
)
951 attre
->vnc_subtlvs
->refcnt
++;
958 /* Make network statement's attribute. */
960 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
962 memset (attr
, 0, sizeof (struct attr
));
963 bgp_attr_extra_get (attr
);
965 attr
->origin
= origin
;
966 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
967 attr
->aspath
= aspath_empty ();
968 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
969 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
970 attr
->extra
->tag
= 0;
971 attr
->extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
972 attr
->extra
->label
= MPLS_INVALID_LABEL
;
973 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
974 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
979 /* Create the attributes for an aggregate */
981 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
982 struct aspath
*aspath
,
983 struct community
*community
, int as_set
,
984 u_char atomic_aggregate
)
988 struct attr_extra attre
;
990 memset (&attr
, 0, sizeof (struct attr
));
991 memset (&attre
, 0, sizeof (struct attr_extra
));
994 /* Origin attribute. */
995 attr
.origin
= origin
;
996 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
998 /* AS path attribute. */
1000 attr
.aspath
= aspath_intern (aspath
);
1002 attr
.aspath
= aspath_empty ();
1003 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1005 /* Next hop attribute. */
1006 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1010 attr
.community
= community
;
1011 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1014 attre
.label_index
= BGP_INVALID_LABEL_INDEX
;
1015 attre
.label
= MPLS_INVALID_LABEL
;
1016 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1017 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1018 if (! as_set
|| atomic_aggregate
)
1019 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1020 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1021 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1022 attre
.aggregator_as
= bgp
->confed_id
;
1024 attre
.aggregator_as
= bgp
->as
;
1025 attre
.aggregator_addr
= bgp
->router_id
;
1027 new = bgp_attr_intern (&attr
);
1029 aspath_unintern (&new->aspath
);
1033 /* Unintern just the sub-components of the attr, but not the attr */
1035 bgp_attr_unintern_sub (struct attr
*attr
)
1037 /* aspath refcount shoud be decrement. */
1039 aspath_unintern (&attr
->aspath
);
1040 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
1042 if (attr
->community
)
1043 community_unintern (&attr
->community
);
1044 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
1048 if (attr
->extra
->ecommunity
)
1049 ecommunity_unintern (&attr
->extra
->ecommunity
);
1050 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
1052 if (attr
->extra
->lcommunity
)
1053 lcommunity_unintern (&attr
->extra
->lcommunity
);
1054 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
));
1056 if (attr
->extra
->cluster
)
1057 cluster_unintern (attr
->extra
->cluster
);
1058 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
1060 if (attr
->extra
->transit
)
1061 transit_unintern (attr
->extra
->transit
);
1063 if (attr
->extra
->encap_subtlvs
)
1064 encap_unintern (&attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1067 if (attr
->extra
->vnc_subtlvs
)
1068 encap_unintern (&attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1073 /* Free bgp attribute and aspath. */
1075 bgp_attr_unintern (struct attr
**pattr
)
1077 struct attr
*attr
= *pattr
;
1080 struct attr_extra tmp_extra
;
1082 /* Decrement attribute reference. */
1089 tmp
.extra
= &tmp_extra
;
1090 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
1093 /* If reference becomes zero then free attribute object. */
1094 if (attr
->refcnt
== 0)
1096 ret
= hash_release (attrhash
, attr
);
1097 assert (ret
!= NULL
);
1098 bgp_attr_extra_free (attr
);
1099 XFREE (MTYPE_ATTR
, attr
);
1103 bgp_attr_unintern_sub (&tmp
);
1107 bgp_attr_flush (struct attr
*attr
)
1109 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
1111 aspath_free (attr
->aspath
);
1112 attr
->aspath
= NULL
;
1114 if (attr
->community
&& ! attr
->community
->refcnt
)
1116 community_free (attr
->community
);
1117 attr
->community
= NULL
;
1121 struct attr_extra
*attre
= attr
->extra
;
1123 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
1124 ecommunity_free (&attre
->ecommunity
);
1125 if (attre
->lcommunity
&& ! attre
->lcommunity
->refcnt
)
1126 lcommunity_free (&attre
->lcommunity
);
1127 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
1129 cluster_free (attre
->cluster
);
1130 attre
->cluster
= NULL
;
1132 if (attre
->transit
&& ! attre
->transit
->refcnt
)
1134 transit_free (attre
->transit
);
1135 attre
->transit
= NULL
;
1137 if (attre
->encap_subtlvs
&& ! attre
->encap_subtlvs
->refcnt
)
1139 encap_free(attre
->encap_subtlvs
);
1140 attre
->encap_subtlvs
= NULL
;
1143 if (attre
->vnc_subtlvs
&& ! attre
->vnc_subtlvs
->refcnt
)
1145 encap_free(attre
->vnc_subtlvs
);
1146 attre
->vnc_subtlvs
= NULL
;
1152 /* Implement draft-scudder-idr-optional-transitive behaviour and
1153 * avoid resetting sessions for malformed attributes which are
1154 * are partial/optional and hence where the error likely was not
1155 * introduced by the sending neighbour.
1157 static bgp_attr_parse_ret_t
1158 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
1161 struct peer
*const peer
= args
->peer
;
1162 const u_int8_t flags
= args
->flags
;
1163 /* startp and length must be special-cased, as whether or not to
1164 * send the attribute data with the NOTIFY depends on the error,
1165 * the caller therefore signals this with the seperate length argument
1167 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1169 /* Only relax error handling for eBGP peers */
1170 if (peer
->sort
!= BGP_PEER_EBGP
)
1172 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1173 notify_datap
, length
);
1174 return BGP_ATTR_PARSE_ERROR
;
1178 /* Adjust the stream getp to the end of the attribute, in case we can
1179 * still proceed but the caller hasn't read all the attribute.
1181 stream_set_getp (BGP_INPUT (peer
),
1182 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
1185 switch (args
->type
) {
1186 /* where an attribute is relatively inconsequential, e.g. it does not
1187 * affect route selection, and can be safely ignored, then any such
1188 * attributes which are malformed should just be ignored and the route
1189 * processed as normal.
1191 case BGP_ATTR_AS4_AGGREGATOR
:
1192 case BGP_ATTR_AGGREGATOR
:
1193 case BGP_ATTR_ATOMIC_AGGREGATE
:
1194 return BGP_ATTR_PARSE_PROCEED
;
1196 /* Core attributes, particularly ones which may influence route
1197 * selection, should always cause session resets
1199 case BGP_ATTR_ORIGIN
:
1200 case BGP_ATTR_AS_PATH
:
1201 case BGP_ATTR_NEXT_HOP
:
1202 case BGP_ATTR_MULTI_EXIT_DISC
:
1203 case BGP_ATTR_LOCAL_PREF
:
1204 case BGP_ATTR_COMMUNITIES
:
1205 case BGP_ATTR_ORIGINATOR_ID
:
1206 case BGP_ATTR_CLUSTER_LIST
:
1207 case BGP_ATTR_MP_REACH_NLRI
:
1208 case BGP_ATTR_MP_UNREACH_NLRI
:
1209 case BGP_ATTR_EXT_COMMUNITIES
:
1210 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1211 notify_datap
, length
);
1212 return BGP_ATTR_PARSE_ERROR
;
1215 /* Partial optional attributes that are malformed should not cause
1216 * the whole session to be reset. Instead treat it as a withdrawal
1217 * of the routes, if possible.
1219 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1220 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1221 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1222 return BGP_ATTR_PARSE_WITHDRAW
;
1224 /* default to reset */
1225 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1228 /* Find out what is wrong with the path attribute flag bits and log the error.
1229 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1230 Extended Length. Checking O/T/P bits at once implies, that the attribute
1231 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1232 non-transitive" attribute. */
1234 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1235 u_int8_t desired_flags
/* how RFC says it must be */
1239 u_char real_flags
= args
->flags
;
1240 const u_int8_t attr_code
= args
->type
;
1242 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1243 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1244 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1247 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1248 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1251 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1252 LOOKUP (attr_str
, attr_code
),
1253 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1254 attr_flag_str
[i
].str
);
1259 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1260 " (real flags 0x%x, desired 0x%x)",
1261 __func__
, LOOKUP (attr_str
, attr_code
),
1262 real_flags
, desired_flags
);
1266 /* Required flags for attributes. EXTLEN will be masked off when testing,
1267 * as will PARTIAL for optional+transitive attributes.
1269 const u_int8_t attr_flags_values
[] = {
1270 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1271 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1272 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1273 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1274 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1275 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1276 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1277 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1278 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1279 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1280 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1281 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1282 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1283 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1284 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1285 [BGP_ATTR_LARGE_COMMUNITIES
]= BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1286 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1288 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1291 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1293 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1294 const u_int8_t flags
= args
->flags
;
1295 const u_int8_t attr_code
= args
->type
;
1297 /* there may be attributes we don't know about */
1298 if (attr_code
> attr_flags_values_max
)
1300 if (attr_flags_values
[attr_code
] == 0)
1303 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1306 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1307 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1309 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1310 LOOKUP (attr_str
, attr_code
), flags
);
1314 /* "For well-known attributes and for optional non-transitive attributes,
1315 * the Partial bit MUST be set to 0."
1317 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1319 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1321 zlog_err ("%s well-known attribute "
1322 "must NOT have the partial flag set (%x)",
1323 LOOKUP (attr_str
, attr_code
), flags
);
1326 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1327 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1329 zlog_err ("%s optional + transitive attribute "
1330 "must NOT have the partial flag set (%x)",
1331 LOOKUP (attr_str
, attr_code
), flags
);
1336 /* Optional transitive attributes may go through speakers that don't
1337 * reocgnise them and set the Partial bit.
1339 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1340 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1341 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1344 == attr_flags_values
[attr_code
])
1347 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1351 /* Get origin attribute of the update message. */
1352 static bgp_attr_parse_ret_t
1353 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1355 struct peer
*const peer
= args
->peer
;
1356 struct attr
*const attr
= args
->attr
;
1357 const bgp_size_t length
= args
->length
;
1359 /* If any recognized attribute has Attribute Length that conflicts
1360 with the expected length (based on the attribute type code), then
1361 the Error Subcode is set to Attribute Length Error. The Data
1362 field contains the erroneous attribute (type, length and
1366 zlog_err ("Origin attribute length is not one %d", length
);
1367 return bgp_attr_malformed (args
,
1368 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1372 /* Fetch origin attribute. */
1373 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1375 /* If the ORIGIN attribute has an undefined value, then the Error
1376 Subcode is set to Invalid Origin Attribute. The Data field
1377 contains the unrecognized attribute (type, length and value). */
1378 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1379 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1380 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1382 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1383 return bgp_attr_malformed (args
,
1384 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1388 /* Set oring attribute flag. */
1389 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1394 /* Parse AS path information. This function is wrapper of
1397 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1399 struct attr
*const attr
= args
->attr
;
1400 struct peer
*const peer
= args
->peer
;
1401 const bgp_size_t length
= args
->length
;
1404 * peer with AS4 => will get 4Byte ASnums
1405 * otherwise, will get 16 Bit
1407 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1408 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1410 /* In case of IBGP, length will be zero. */
1413 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1414 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1417 /* Set aspath attribute flag. */
1418 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1420 return BGP_ATTR_PARSE_PROCEED
;
1423 static bgp_attr_parse_ret_t
1424 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1426 /* These checks were part of bgp_attr_aspath, but with
1427 * as4 we should to check aspath things when
1428 * aspath synthesizing with as4_path has already taken place.
1429 * Otherwise we check ASPATH and use the synthesized thing, and that is
1431 * So do the checks later, i.e. here
1433 struct bgp
*bgp
= peer
->bgp
;
1434 struct aspath
*aspath
;
1436 /* Confederation sanity check. */
1437 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1438 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1440 zlog_err ("Malformed AS path from %s", peer
->host
);
1441 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1442 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1443 return BGP_ATTR_PARSE_ERROR
;
1446 /* First AS check for EBGP. */
1447 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1449 if (peer
->sort
== BGP_PEER_EBGP
1450 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1452 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1453 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1454 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1455 return BGP_ATTR_PARSE_ERROR
;
1459 /* local-as prepend */
1460 if (peer
->change_local_as
&&
1461 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1463 aspath
= aspath_dup (attr
->aspath
);
1464 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1465 aspath_unintern (&attr
->aspath
);
1466 attr
->aspath
= aspath_intern (aspath
);
1469 return BGP_ATTR_PARSE_PROCEED
;
1472 /* Parse AS4 path information. This function is another wrapper of
1475 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1477 struct peer
*const peer
= args
->peer
;
1478 struct attr
*const attr
= args
->attr
;
1479 const bgp_size_t length
= args
->length
;
1481 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1483 /* In case of IBGP, length will be zero. */
1486 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1487 return bgp_attr_malformed (args
,
1488 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1492 /* Set aspath attribute flag. */
1493 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1495 return BGP_ATTR_PARSE_PROCEED
;
1498 /* Nexthop attribute. */
1499 static bgp_attr_parse_ret_t
1500 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1502 struct peer
*const peer
= args
->peer
;
1503 struct attr
*const attr
= args
->attr
;
1504 const bgp_size_t length
= args
->length
;
1506 in_addr_t nexthop_h
, nexthop_n
;
1508 /* Check nexthop attribute length. */
1511 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1513 return bgp_attr_malformed (args
,
1514 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1518 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1519 attribute must result in a NOTIFICATION message (this is implemented below).
1520 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1521 logged locally (this is implemented somewhere else). The UPDATE message
1522 gets ignored in any of these cases. */
1523 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1524 nexthop_h
= ntohl (nexthop_n
);
1525 if ((IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1526 && !BGP_DEBUG (allow_martians
, ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1528 char buf
[INET_ADDRSTRLEN
];
1529 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1530 zlog_err ("Martian nexthop %s", buf
);
1531 return bgp_attr_malformed (args
,
1532 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1536 attr
->nexthop
.s_addr
= nexthop_n
;
1537 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1539 return BGP_ATTR_PARSE_PROCEED
;
1542 /* MED atrribute. */
1543 static bgp_attr_parse_ret_t
1544 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1546 struct peer
*const peer
= args
->peer
;
1547 struct attr
*const attr
= args
->attr
;
1548 const bgp_size_t length
= args
->length
;
1553 zlog_err ("MED attribute length isn't four [%d]", length
);
1555 return bgp_attr_malformed (args
,
1556 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1560 attr
->med
= stream_getl (peer
->ibuf
);
1562 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1564 return BGP_ATTR_PARSE_PROCEED
;
1567 /* Local preference attribute. */
1568 static bgp_attr_parse_ret_t
1569 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1571 struct peer
*const peer
= args
->peer
;
1572 struct attr
*const attr
= args
->attr
;
1573 const bgp_size_t length
= args
->length
;
1578 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1579 return bgp_attr_malformed (args
,
1580 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1584 /* If it is contained in an UPDATE message that is received from an
1585 external peer, then this attribute MUST be ignored by the
1586 receiving speaker. */
1587 if (peer
->sort
== BGP_PEER_EBGP
)
1589 stream_forward_getp (peer
->ibuf
, length
);
1590 return BGP_ATTR_PARSE_PROCEED
;
1593 attr
->local_pref
= stream_getl (peer
->ibuf
);
1595 /* Set atomic aggregate flag. */
1596 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1598 return BGP_ATTR_PARSE_PROCEED
;
1601 /* Atomic aggregate. */
1603 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1605 struct attr
*const attr
= args
->attr
;
1606 const bgp_size_t length
= args
->length
;
1611 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1612 return bgp_attr_malformed (args
,
1613 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1617 /* Set atomic aggregate flag. */
1618 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1620 return BGP_ATTR_PARSE_PROCEED
;
1623 /* Aggregator attribute */
1625 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1627 struct peer
*const peer
= args
->peer
;
1628 struct attr
*const attr
= args
->attr
;
1629 const bgp_size_t length
= args
->length
;
1632 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1634 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1635 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1638 if (length
!= wantedlen
)
1640 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1641 return bgp_attr_malformed (args
,
1642 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1646 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1647 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1649 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1650 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1652 /* Set atomic aggregate flag. */
1653 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1655 return BGP_ATTR_PARSE_PROCEED
;
1658 /* New Aggregator attribute */
1659 static bgp_attr_parse_ret_t
1660 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1661 as_t
*as4_aggregator_as
,
1662 struct in_addr
*as4_aggregator_addr
)
1664 struct peer
*const peer
= args
->peer
;
1665 struct attr
*const attr
= args
->attr
;
1666 const bgp_size_t length
= args
->length
;
1670 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1671 return bgp_attr_malformed (args
,
1672 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1676 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1677 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1679 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1681 return BGP_ATTR_PARSE_PROCEED
;
1684 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1686 static bgp_attr_parse_ret_t
1687 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1688 struct attr
*const attr
,
1689 struct aspath
*as4_path
, as_t as4_aggregator
,
1690 struct in_addr
*as4_aggregator_addr
)
1692 int ignore_as4_path
= 0;
1693 struct aspath
*newpath
;
1694 struct attr_extra
*attre
= attr
->extra
;
1698 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1699 * checked that all well-known, mandatory attributes were present.
1701 * Can only be a problem with peer itself - hard error
1703 return BGP_ATTR_PARSE_ERROR
;
1706 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1708 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1710 * It is worth a warning though, because the peer really
1711 * should not send them
1713 if (BGP_DEBUG(as4
, AS4
))
1715 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1716 zlog_debug ("[AS4] %s %s AS4_PATH",
1717 peer
->host
, "AS4 capable peer, yet it sent");
1719 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1720 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1721 peer
->host
, "AS4 capable peer, yet it sent");
1724 return BGP_ATTR_PARSE_PROCEED
;
1727 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1728 * because that may override AS4_PATH
1730 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1732 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1737 * if the as_number in aggregator is not AS_TRANS,
1738 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1739 * and the Aggregator shall be taken as
1740 * info on the aggregating node, and the AS_PATH
1741 * shall be taken as the AS_PATH
1743 * the Aggregator shall be ignored and the
1744 * AS4_AGGREGATOR shall be taken as the
1745 * Aggregating node and the AS_PATH is to be
1746 * constructed "as in all other cases"
1748 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1751 if ( BGP_DEBUG(as4
, AS4
))
1752 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1753 " send AGGREGATOR != AS_TRANS and"
1754 " AS4_AGGREGATOR, so ignore"
1755 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1756 ignore_as4_path
= 1;
1760 /* "New_aggregator shall be taken as aggregator" */
1761 attre
->aggregator_as
= as4_aggregator
;
1762 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1767 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1768 * That is bogus - but reading the conditions
1769 * we have to handle AS4_AGGREGATOR as if it were
1770 * AGGREGATOR in that case
1772 if ( BGP_DEBUG(as4
, AS4
))
1773 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1774 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1775 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1776 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1777 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1778 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1782 /* need to reconcile NEW_AS_PATH and AS_PATH */
1783 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1785 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1786 aspath_unintern (&attr
->aspath
);
1787 attr
->aspath
= aspath_intern (newpath
);
1789 return BGP_ATTR_PARSE_PROCEED
;
1792 /* Community attribute. */
1793 static bgp_attr_parse_ret_t
1794 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1796 struct peer
*const peer
= args
->peer
;
1797 struct attr
*const attr
= args
->attr
;
1798 const bgp_size_t length
= args
->length
;
1802 attr
->community
= NULL
;
1803 return BGP_ATTR_PARSE_PROCEED
;
1807 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1809 /* XXX: fix community_parse to use stream API and remove this */
1810 stream_forward_getp (peer
->ibuf
, length
);
1812 if (!attr
->community
)
1813 return bgp_attr_malformed (args
,
1814 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1817 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1819 return BGP_ATTR_PARSE_PROCEED
;
1822 /* Originator ID attribute. */
1823 static bgp_attr_parse_ret_t
1824 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1826 struct peer
*const peer
= args
->peer
;
1827 struct attr
*const attr
= args
->attr
;
1828 const bgp_size_t length
= args
->length
;
1833 zlog_err ("Bad originator ID length %d", length
);
1835 return bgp_attr_malformed (args
,
1836 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1840 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1841 = stream_get_ipv4 (peer
->ibuf
);
1843 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1845 return BGP_ATTR_PARSE_PROCEED
;
1848 /* Cluster list attribute. */
1849 static bgp_attr_parse_ret_t
1850 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1852 struct peer
*const peer
= args
->peer
;
1853 struct attr
*const attr
= args
->attr
;
1854 const bgp_size_t length
= args
->length
;
1859 zlog_err ("Bad cluster list length %d", length
);
1861 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1865 (bgp_attr_extra_get (attr
))->cluster
1866 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1868 /* XXX: Fix cluster_parse to use stream API and then remove this */
1869 stream_forward_getp (peer
->ibuf
, length
);
1871 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1873 return BGP_ATTR_PARSE_PROCEED
;
1876 /* Multiprotocol reachability information parse. */
1878 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1879 struct bgp_nlri
*mp_update
)
1883 safi_t pkt_safi
, safi
;
1884 bgp_size_t nlri_len
;
1887 struct peer
*const peer
= args
->peer
;
1888 struct attr
*const attr
= args
->attr
;
1889 const bgp_size_t length
= args
->length
;
1890 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1892 /* Set end of packet. */
1893 s
= BGP_INPUT(peer
);
1894 start
= stream_get_getp(s
);
1896 /* safe to read statically sized header? */
1897 #define BGP_MP_REACH_MIN_SIZE 5
1898 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1899 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1901 zlog_info ("%s: %s sent invalid length, %lu",
1902 __func__
, peer
->host
, (unsigned long)length
);
1903 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1906 /* Load AFI, SAFI. */
1907 pkt_afi
= stream_getw (s
);
1908 pkt_safi
= stream_getc (s
);
1910 /* Convert AFI, SAFI to internal values, check. */
1911 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
1913 /* Log if AFI or SAFI is unrecognized. This is not an error unless
1914 * the attribute is otherwise malformed.
1916 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1917 zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1918 peer
->host
, pkt_afi
, pkt_safi
);
1919 return BGP_ATTR_PARSE_ERROR
;
1922 /* Get nexthop length. */
1923 attre
->mp_nexthop_len
= stream_getc (s
);
1925 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1927 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1928 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1929 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1932 /* Nexthop length check. */
1933 switch (attre
->mp_nexthop_len
)
1935 case BGP_ATTR_NHLEN_IPV4
:
1936 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1937 /* Probably needed for RFC 2283 */
1938 if (attr
->nexthop
.s_addr
== 0)
1939 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1941 case BGP_ATTR_NHLEN_VPNV4
:
1942 stream_getl (s
); /* RD high */
1943 stream_getl (s
); /* RD low */
1944 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1946 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1947 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1948 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1950 stream_getl (s
); /* RD high */
1951 stream_getl (s
); /* RD low */
1953 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1955 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1956 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1957 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1959 stream_getl (s
); /* RD high */
1960 stream_getl (s
); /* RD low */
1962 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1963 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1965 stream_getl (s
); /* RD high */
1966 stream_getl (s
); /* RD low */
1968 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1969 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1971 char buf1
[INET6_ADDRSTRLEN
];
1972 char buf2
[INET6_ADDRSTRLEN
];
1974 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1975 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1977 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1978 buf1
, INET6_ADDRSTRLEN
),
1979 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1980 buf2
, INET6_ADDRSTRLEN
));
1982 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1986 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1987 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1988 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1993 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1994 __func__
, peer
->host
);
1995 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2000 if ((val
= stream_getc (s
)))
2001 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
2005 /* must have nrli_len, what is left of the attribute */
2006 nlri_len
= LEN_LEFT
;
2007 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
2009 zlog_info ("%s: (%s) Failed to read NLRI",
2010 __func__
, peer
->host
);
2011 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2014 mp_update
->afi
= afi
;
2015 mp_update
->safi
= safi
;
2016 mp_update
->nlri
= stream_pnt (s
);
2017 mp_update
->length
= nlri_len
;
2019 stream_forward_getp (s
, nlri_len
);
2021 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
2023 return BGP_ATTR_PARSE_PROCEED
;
2027 /* Multiprotocol unreachable parse */
2029 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
2030 struct bgp_nlri
*mp_withdraw
)
2035 safi_t pkt_safi
, safi
;
2036 u_int16_t withdraw_len
;
2037 struct peer
*const peer
= args
->peer
;
2038 struct attr
*const attr
= args
->attr
;
2039 const bgp_size_t length
= args
->length
;
2043 #define BGP_MP_UNREACH_MIN_SIZE 3
2044 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2045 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2047 pkt_afi
= stream_getw (s
);
2048 pkt_safi
= stream_getc (s
);
2050 /* Convert AFI, SAFI to internal values, check. */
2051 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
2053 /* Log if AFI or SAFI is unrecognized. This is not an error unless
2054 * the attribute is otherwise malformed.
2056 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2057 zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
2058 peer
->host
, pkt_afi
, pkt_safi
);
2059 return BGP_ATTR_PARSE_ERROR
;
2062 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2064 mp_withdraw
->afi
= afi
;
2065 mp_withdraw
->safi
= safi
;
2066 mp_withdraw
->nlri
= stream_pnt (s
);
2067 mp_withdraw
->length
= withdraw_len
;
2069 stream_forward_getp (s
, withdraw_len
);
2071 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
2073 return BGP_ATTR_PARSE_PROCEED
;
2076 /* Large Community attribute. */
2077 static bgp_attr_parse_ret_t
2078 bgp_attr_large_community (struct bgp_attr_parser_args
*args
)
2080 struct peer
*const peer
= args
->peer
;
2081 struct attr
*const attr
= args
->attr
;
2082 const bgp_size_t length
= args
->length
;
2085 * Large community follows new attribute format.
2090 attr
->extra
->lcommunity
= NULL
;
2091 /* Empty extcomm doesn't seem to be invalid per se */
2092 return BGP_ATTR_PARSE_PROCEED
;
2095 (bgp_attr_extra_get (attr
))->lcommunity
=
2096 lcommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2097 /* XXX: fix ecommunity_parse to use stream API */
2098 stream_forward_getp (peer
->ibuf
, length
);
2100 if (attr
->extra
&& !attr
->extra
->lcommunity
)
2101 return bgp_attr_malformed (args
,
2102 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2105 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
);
2107 return BGP_ATTR_PARSE_PROCEED
;
2110 /* Extended Community attribute. */
2111 static bgp_attr_parse_ret_t
2112 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
2114 struct peer
*const peer
= args
->peer
;
2115 struct attr
*const attr
= args
->attr
;
2116 const bgp_size_t length
= args
->length
;
2121 attr
->extra
->ecommunity
= NULL
;
2122 /* Empty extcomm doesn't seem to be invalid per se */
2123 return BGP_ATTR_PARSE_PROCEED
;
2126 (bgp_attr_extra_get (attr
))->ecommunity
=
2127 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2128 /* XXX: fix ecommunity_parse to use stream API */
2129 stream_forward_getp (peer
->ibuf
, length
);
2131 if (attr
->extra
&& !attr
->extra
->ecommunity
)
2132 return bgp_attr_malformed (args
,
2133 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2136 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
2138 return BGP_ATTR_PARSE_PROCEED
;
2141 /* Parse Tunnel Encap attribute in an UPDATE */
2145 struct peer
*peer
, /* IN */
2146 bgp_size_t length
, /* IN: attr's length field */
2147 struct attr
*attr
, /* IN: caller already allocated */
2148 u_char flag
, /* IN: attr's flags field */
2152 struct attr_extra
*attre
= NULL
;
2153 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2154 uint16_t tunneltype
= 0;
2156 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2158 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2159 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
2161 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
2162 bgp_notify_send_with_data (peer
,
2163 BGP_NOTIFY_UPDATE_ERR
,
2164 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2169 if (BGP_ATTR_ENCAP
== type
) {
2170 /* read outer TLV type and length */
2171 uint16_t tlv_length
;
2174 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2175 bgp_notify_send_with_data(peer
,
2176 BGP_NOTIFY_UPDATE_ERR
,
2177 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2181 tunneltype
= stream_getw (BGP_INPUT (peer
));
2182 tlv_length
= stream_getw (BGP_INPUT (peer
));
2185 if (tlv_length
!= length
) {
2186 zlog_info ("%s: tlv_length(%d) != length(%d)",
2187 __func__
, tlv_length
, length
);
2191 while (length
>= 4) {
2192 uint16_t subtype
= 0;
2193 uint16_t sublength
= 0;
2194 struct bgp_attr_encap_subtlv
*tlv
;
2196 if (BGP_ATTR_ENCAP
== type
) {
2197 subtype
= stream_getc (BGP_INPUT (peer
));
2198 sublength
= stream_getc (BGP_INPUT (peer
));
2202 subtype
= stream_getw (BGP_INPUT (peer
));
2203 sublength
= stream_getw (BGP_INPUT (peer
));
2208 if (sublength
> length
) {
2209 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2211 bgp_notify_send_with_data (peer
,
2212 BGP_NOTIFY_UPDATE_ERR
,
2213 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2218 /* alloc and copy sub-tlv */
2219 /* TBD make sure these are freed when attributes are released */
2220 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
2221 tlv
->type
= subtype
;
2222 tlv
->length
= sublength
;
2223 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2224 length
-= sublength
;
2226 /* attach tlv to encap chain */
2228 attre
= bgp_attr_extra_get(attr
);
2229 if (BGP_ATTR_ENCAP
== type
) {
2230 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
2231 stlv_last
= stlv_last
->next
);
2233 stlv_last
->next
= tlv
;
2235 attre
->encap_subtlvs
= tlv
;
2239 for (stlv_last
= attre
->vnc_subtlvs
; stlv_last
&& stlv_last
->next
;
2240 stlv_last
= stlv_last
->next
);
2242 stlv_last
->next
= tlv
;
2244 attre
->vnc_subtlvs
= tlv
;
2249 stlv_last
->next
= tlv
;
2254 if (BGP_ATTR_ENCAP
== type
) {
2256 attre
= bgp_attr_extra_get(attr
);
2257 attre
->encap_tunneltype
= tunneltype
;
2261 /* spurious leftover data */
2262 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2263 bgp_notify_send_with_data (peer
,
2264 BGP_NOTIFY_UPDATE_ERR
,
2265 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2273 /* Prefix SID attribute
2274 * draft-ietf-idr-bgp-prefix-sid-05
2276 static bgp_attr_parse_ret_t
2277 bgp_attr_prefix_sid (struct bgp_attr_parser_args
*args
, struct bgp_nlri
*mp_update
)
2279 struct peer
*const peer
= args
->peer
;
2280 struct attr
*const attr
= args
->attr
;
2283 u_int32_t label_index
;
2284 struct in6_addr ipv6_sid
;
2285 u_int32_t srgb_base
;
2286 u_int32_t srgb_range
;
2289 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
);
2291 type
= stream_getc (peer
->ibuf
);
2292 length
= stream_getw (peer
->ibuf
);
2294 if (type
== BGP_PREFIX_SID_LABEL_INDEX
)
2296 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
)
2298 zlog_err ("Prefix SID label index length is %d instead of %d", length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2299 return bgp_attr_malformed (args
,
2300 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2304 /* Ignore flags and reserved */
2305 stream_getc (peer
->ibuf
);
2306 stream_getw (peer
->ibuf
);
2308 /* Fetch the label index and see if it is valid. */
2309 label_index
= stream_getl (peer
->ibuf
);
2310 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2311 return bgp_attr_malformed (args
,
2312 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2315 /* Store label index; subsequently, we'll check on address-family */
2316 (bgp_attr_extra_get (attr
))->label_index
= label_index
;
2319 * Ignore the Label index attribute unless received for labeled-unicast
2322 if (!mp_update
->length
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2323 attr
->extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
2326 /* Placeholder code for the IPv6 SID type */
2327 else if (type
== BGP_PREFIX_SID_IPV6
)
2329 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
)
2331 zlog_err ("Prefix SID IPv6 length is %d instead of %d", length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2332 return bgp_attr_malformed (args
,
2333 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2337 /* Ignore reserved */
2338 stream_getc (peer
->ibuf
);
2339 stream_getw (peer
->ibuf
);
2341 stream_get (&ipv6_sid
, peer
->ibuf
, 16);
2344 /* Placeholder code for the Originator SRGB type */
2345 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
)
2348 stream_getw (peer
->ibuf
);
2352 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)
2354 zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2355 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2356 return bgp_attr_malformed (args
,
2357 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2361 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2363 for (int i
= 0; i
< srgb_count
; i
++)
2365 stream_get (&srgb_base
, peer
->ibuf
, 3);
2366 stream_get (&srgb_range
, peer
->ibuf
, 3);
2370 return BGP_ATTR_PARSE_PROCEED
;
2373 /* BGP unknown attribute treatment. */
2374 static bgp_attr_parse_ret_t
2375 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2377 bgp_size_t total
= args
->total
;
2378 struct transit
*transit
;
2379 struct attr_extra
*attre
;
2380 struct peer
*const peer
= args
->peer
;
2381 struct attr
*const attr
= args
->attr
;
2382 u_char
*const startp
= args
->startp
;
2383 const u_char type
= args
->type
;
2384 const u_char flag
= args
->flags
;
2385 const bgp_size_t length
= args
->length
;
2387 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2388 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2389 peer
->host
, type
, length
);
2391 /* Forward read pointer of input stream. */
2392 stream_forward_getp (peer
->ibuf
, length
);
2394 /* If any of the mandatory well-known attributes are not recognized,
2395 then the Error Subcode is set to Unrecognized Well-known
2396 Attribute. The Data field contains the unrecognized attribute
2397 (type, length and value). */
2398 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2400 return bgp_attr_malformed (args
,
2401 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2405 /* Unrecognized non-transitive optional attributes must be quietly
2406 ignored and not passed along to other BGP peers. */
2407 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2408 return BGP_ATTR_PARSE_PROCEED
;
2410 /* If a path with recognized transitive optional attribute is
2411 accepted and passed along to other BGP peers and the Partial bit
2412 in the Attribute Flags octet is set to 1 by some previous AS, it
2413 is not set back to 0 by the current AS. */
2414 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2416 /* Store transitive attribute to the end of attr->transit. */
2417 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2418 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2420 transit
= attre
->transit
;
2423 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2424 transit
->length
+ total
);
2426 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2428 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2429 transit
->length
+= total
;
2431 return BGP_ATTR_PARSE_PROCEED
;
2434 /* Well-known attribute check. */
2436 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2440 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2442 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2443 return BGP_ATTR_PARSE_PROCEED
;
2445 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2446 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2447 are present, it should. Check for any other attribute being present
2450 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2451 return BGP_ATTR_PARSE_PROCEED
;
2453 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2454 type
= BGP_ATTR_ORIGIN
;
2456 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2457 type
= BGP_ATTR_AS_PATH
;
2459 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2460 * NLRI is empty. We can't easily check NLRI empty here though.
2462 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2463 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2464 type
= BGP_ATTR_NEXT_HOP
;
2466 if (peer
->sort
== BGP_PEER_IBGP
2467 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2468 type
= BGP_ATTR_LOCAL_PREF
;
2472 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2473 LOOKUP (attr_str
, type
));
2474 bgp_notify_send_with_data (peer
,
2475 BGP_NOTIFY_UPDATE_ERR
,
2476 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2478 return BGP_ATTR_PARSE_ERROR
;
2480 return BGP_ATTR_PARSE_PROCEED
;
2483 /* Read attribute of update packet. This function is called from
2484 bgp_update_receive() in bgp_packet.c. */
2485 bgp_attr_parse_ret_t
2486 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2487 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2493 u_char
*startp
, *endp
;
2495 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2496 /* we need the as4_path only until we have synthesized the as_path with it */
2497 /* same goes for as4_aggregator */
2498 struct aspath
*as4_path
= NULL
;
2499 as_t as4_aggregator
= 0;
2500 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2502 /* Initialize bitmap. */
2503 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2505 /* End pointer of BGP attribute. */
2506 endp
= BGP_INPUT_PNT (peer
) + size
;
2508 /* Get attributes to the end of attribute length. */
2509 while (BGP_INPUT_PNT (peer
) < endp
)
2511 /* Check remaining length check.*/
2512 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2514 /* XXX warning: long int format, int arg (arg 5) */
2515 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2517 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2519 bgp_notify_send (peer
,
2520 BGP_NOTIFY_UPDATE_ERR
,
2521 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2522 return BGP_ATTR_PARSE_ERROR
;
2525 /* Fetch attribute flag and type. */
2526 startp
= BGP_INPUT_PNT (peer
);
2527 /* "The lower-order four bits of the Attribute Flags octet are
2528 unused. They MUST be zero when sent and MUST be ignored when
2530 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2531 type
= stream_getc (BGP_INPUT (peer
));
2533 /* Check whether Extended-Length applies and is in bounds */
2534 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2535 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2537 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2539 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2541 bgp_notify_send (peer
,
2542 BGP_NOTIFY_UPDATE_ERR
,
2543 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2544 return BGP_ATTR_PARSE_ERROR
;
2547 /* Check extended attribue length bit. */
2548 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2549 length
= stream_getw (BGP_INPUT (peer
));
2551 length
= stream_getc (BGP_INPUT (peer
));
2553 /* If any attribute appears more than once in the UPDATE
2554 message, then the Error Subcode is set to Malformed Attribute
2557 if (CHECK_BITMAP (seen
, type
))
2559 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2562 bgp_notify_send (peer
,
2563 BGP_NOTIFY_UPDATE_ERR
,
2564 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2565 return BGP_ATTR_PARSE_ERROR
;
2568 /* Set type to bitmap to check duplicate attribute. `type' is
2569 unsigned char so it never overflow bitmap range. */
2571 SET_BITMAP (seen
, type
);
2573 /* Overflow check. */
2574 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2576 if (attr_endp
> endp
)
2578 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
);
2579 bgp_notify_send_with_data (peer
,
2580 BGP_NOTIFY_UPDATE_ERR
,
2581 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2582 startp
, attr_endp
- startp
);
2583 return BGP_ATTR_PARSE_ERROR
;
2586 struct bgp_attr_parser_args attr_args
= {
2593 .total
= attr_endp
- startp
,
2597 /* If any recognized attribute has Attribute Flags that conflict
2598 with the Attribute Type Code, then the Error Subcode is set to
2599 Attribute Flags Error. The Data field contains the erroneous
2600 attribute (type, length and value). */
2601 if (bgp_attr_flag_invalid (&attr_args
))
2603 bgp_attr_parse_ret_t ret
;
2604 ret
= bgp_attr_malformed (&attr_args
,
2605 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2607 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2612 /* OK check attribute and store it's value. */
2615 case BGP_ATTR_ORIGIN
:
2616 ret
= bgp_attr_origin (&attr_args
);
2618 case BGP_ATTR_AS_PATH
:
2619 ret
= bgp_attr_aspath (&attr_args
);
2621 case BGP_ATTR_AS4_PATH
:
2622 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2624 case BGP_ATTR_NEXT_HOP
:
2625 ret
= bgp_attr_nexthop (&attr_args
);
2627 case BGP_ATTR_MULTI_EXIT_DISC
:
2628 ret
= bgp_attr_med (&attr_args
);
2630 case BGP_ATTR_LOCAL_PREF
:
2631 ret
= bgp_attr_local_pref (&attr_args
);
2633 case BGP_ATTR_ATOMIC_AGGREGATE
:
2634 ret
= bgp_attr_atomic (&attr_args
);
2636 case BGP_ATTR_AGGREGATOR
:
2637 ret
= bgp_attr_aggregator (&attr_args
);
2639 case BGP_ATTR_AS4_AGGREGATOR
:
2640 ret
= bgp_attr_as4_aggregator (&attr_args
,
2642 &as4_aggregator_addr
);
2644 case BGP_ATTR_COMMUNITIES
:
2645 ret
= bgp_attr_community (&attr_args
);
2647 case BGP_ATTR_LARGE_COMMUNITIES
:
2648 ret
= bgp_attr_large_community (&attr_args
);
2650 case BGP_ATTR_ORIGINATOR_ID
:
2651 ret
= bgp_attr_originator_id (&attr_args
);
2653 case BGP_ATTR_CLUSTER_LIST
:
2654 ret
= bgp_attr_cluster_list (&attr_args
);
2656 case BGP_ATTR_MP_REACH_NLRI
:
2657 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2659 case BGP_ATTR_MP_UNREACH_NLRI
:
2660 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2662 case BGP_ATTR_EXT_COMMUNITIES
:
2663 ret
= bgp_attr_ext_communities (&attr_args
);
2668 case BGP_ATTR_ENCAP
:
2669 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2671 case BGP_ATTR_PREFIX_SID
:
2672 ret
= bgp_attr_prefix_sid (&attr_args
, mp_update
);
2675 ret
= bgp_attr_unknown (&attr_args
);
2679 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2681 bgp_notify_send (peer
,
2682 BGP_NOTIFY_UPDATE_ERR
,
2683 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2684 ret
= BGP_ATTR_PARSE_ERROR
;
2687 /* If hard error occured immediately return to the caller. */
2688 if (ret
== BGP_ATTR_PARSE_ERROR
)
2690 zlog_warn ("%s: Attribute %s, parse error",
2692 LOOKUP (attr_str
, type
));
2694 aspath_unintern (&as4_path
);
2697 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2700 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2702 LOOKUP (attr_str
, type
));
2704 aspath_unintern (&as4_path
);
2708 /* Check the fetched length. */
2709 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2711 zlog_warn ("%s: BGP attribute %s, fetch error",
2712 peer
->host
, LOOKUP (attr_str
, type
));
2713 bgp_notify_send (peer
,
2714 BGP_NOTIFY_UPDATE_ERR
,
2715 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2717 aspath_unintern (&as4_path
);
2718 return BGP_ATTR_PARSE_ERROR
;
2722 /* Check final read pointer is same as end pointer. */
2723 if (BGP_INPUT_PNT (peer
) != endp
)
2725 zlog_warn ("%s: BGP attribute %s, length mismatch",
2726 peer
->host
, LOOKUP (attr_str
, type
));
2727 bgp_notify_send (peer
,
2728 BGP_NOTIFY_UPDATE_ERR
,
2729 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2731 aspath_unintern (&as4_path
);
2732 return BGP_ATTR_PARSE_ERROR
;
2735 /* Check all mandatory well-known attributes are present */
2737 bgp_attr_parse_ret_t ret
;
2738 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2741 aspath_unintern (&as4_path
);
2747 * At this place we can see whether we got AS4_PATH and/or
2748 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2749 * We can not do this before we've read all attributes because
2750 * the as4 handling does not say whether AS4_PATH has to be sent
2751 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2752 * in relationship to AGGREGATOR.
2753 * So, to be defensive, we are not relying on any order and read
2754 * all attributes first, including these 32bit ones, and now,
2755 * afterwards, we look what and if something is to be done for as4.
2757 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2760 /* actually... this doesn't ever return failure currently, but
2761 * better safe than sorry */
2762 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2763 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2764 as4_aggregator
, &as4_aggregator_addr
))
2766 bgp_notify_send (peer
,
2767 BGP_NOTIFY_UPDATE_ERR
,
2768 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2770 aspath_unintern (&as4_path
);
2771 return BGP_ATTR_PARSE_ERROR
;
2774 /* At this stage, we have done all fiddling with as4, and the
2775 * resulting info is in attr->aggregator resp. attr->aspath
2776 * so we can chuck as4_aggregator and as4_path alltogether in
2777 * order to save memory
2781 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2782 /* The flag that we got this is still there, but that does not
2787 * The "rest" of the code does nothing with as4_aggregator.
2788 * there is no memory attached specifically which is not part
2790 * so ignoring just means do nothing.
2793 * Finally do the checks on the aspath we did not do yet
2794 * because we waited for a potentially synthesized aspath.
2796 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2798 ret
= bgp_attr_aspath_check (peer
, attr
);
2799 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2804 /* Finally intern unknown attribute. */
2805 if (attr
->extra
->transit
)
2806 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2807 if (attr
->extra
->encap_subtlvs
)
2808 attr
->extra
->encap_subtlvs
= encap_intern (attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2810 if (attr
->extra
->vnc_subtlvs
)
2811 attr
->extra
->vnc_subtlvs
= encap_intern (attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2815 return BGP_ATTR_PARSE_PROCEED
;
2819 bgp_packet_mpattr_start (struct stream
*s
, struct peer
*peer
,
2820 afi_t afi
, safi_t safi
,
2821 struct bpacket_attr_vec_arr
*vecarr
,
2829 /* Set extended bit always to encode the attribute length as 2 bytes */
2830 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2831 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2832 sizep
= stream_get_endp (s
);
2833 stream_putw (s
, 0); /* Marker: Attribute length. */
2836 /* Convert AFI, SAFI to values for packet. */
2837 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
2839 stream_putw (s
, pkt_afi
); /* AFI */
2840 stream_putc (s
, pkt_safi
); /* SAFI */
2843 if (peer_cap_enhe(peer
, afi
, safi
)) {
2846 if (afi
== AFI_L2VPN
)
2848 else if (safi
== SAFI_LABELED_UNICAST
)
2851 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->extra
->mp_nexthop_len
);
2855 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2862 case SAFI_MULTICAST
:
2863 case SAFI_LABELED_UNICAST
:
2865 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2868 stream_putc (s
, 12);
2869 stream_putl (s
, 0); /* RD = 0, per RFC */
2871 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2875 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2885 case SAFI_MULTICAST
:
2886 case SAFI_LABELED_UNICAST
:
2888 struct attr_extra
*attre
= attr
->extra
;
2890 assert (attr
->extra
);
2892 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2893 stream_putc (s
, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2894 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2895 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2897 stream_putc (s
, IPV6_MAX_BYTELEN
);
2898 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2904 struct attr_extra
*attre
= attr
->extra
;
2906 assert (attr
->extra
);
2907 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2908 stream_putc (s
, 24);
2909 stream_putl (s
, 0); /* RD = 0, per RFC */
2911 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2912 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2913 stream_putc (s
, 48);
2914 stream_putl (s
, 0); /* RD = 0, per RFC */
2916 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2917 stream_putl (s
, 0); /* RD = 0, per RFC */
2919 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2924 assert (attr
->extra
);
2925 stream_putc (s
, IPV6_MAX_BYTELEN
);
2926 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2936 if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
)
2938 stream_putc (s
, 12);
2939 stream_putl (s
, 0); /* RD = 0, per RFC */
2941 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2943 else if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
)
2945 stream_putc (s
, 24);
2946 stream_putl (s
, 0); /* RD = 0, per RFC */
2948 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2950 else if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2952 stream_putc (s
, 48);
2953 stream_putl (s
, 0); /* RD = 0, per RFC */
2955 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2956 stream_putl (s
, 0); /* RD = 0, per RFC */
2958 stream_put (s
, &attr
->extra
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2975 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2976 struct prefix
*p
, struct prefix_rd
*prd
,
2977 mpls_label_t
*label
, int addpath_encode
,
2978 u_int32_t addpath_tx_id
, struct attr
*attr
)
2980 if (safi
== SAFI_MPLS_VPN
)
2983 stream_putl(s
, addpath_tx_id
);
2984 /* Label, RD, Prefix write. */
2985 stream_putc (s
, p
->prefixlen
+ 88);
2986 stream_put (s
, label
, BGP_LABEL_BYTES
);
2987 stream_put (s
, prd
->val
, 8);
2988 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2990 else if (safi
== SAFI_EVPN
)
2992 bgp_packet_mpattr_route_type_5(s
, p
, prd
, label
, attr
);
2994 else if (safi
== SAFI_LABELED_UNICAST
)
2996 /* Prefix write with label. */
2997 stream_put_labeled_prefix(s
, p
, label
);
3000 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
3004 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
3006 int size
= PSIZE (p
->prefixlen
);
3007 if (safi
== SAFI_MPLS_VPN
)
3013 * Encodes the tunnel encapsulation attribute,
3014 * and with ENABLE_BGP_VNC the VNC attribute which uses
3015 * almost the same TLV format
3018 bgp_packet_mpattr_tea(
3025 unsigned int attrlenfield
= 0;
3026 unsigned int attrhdrlen
= 0;
3027 struct bgp_attr_encap_subtlv
*subtlvs
;
3028 struct bgp_attr_encap_subtlv
*st
;
3029 const char *attrname
;
3031 if (!attr
|| !attr
->extra
||
3032 (attrtype
== BGP_ATTR_ENCAP
&&
3033 (!attr
->extra
->encap_tunneltype
||
3034 attr
->extra
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3038 case BGP_ATTR_ENCAP
:
3039 attrname
= "Tunnel Encap";
3040 subtlvs
= attr
->extra
->encap_subtlvs
;
3041 if (subtlvs
== NULL
) /* nothing to do */
3044 * The tunnel encap attr has an "outer" tlv.
3046 * L = total length of subtlvs,
3047 * V = concatenated subtlvs.
3049 attrlenfield
= 2 + 2; /* T + L */
3050 attrhdrlen
= 1 + 1; /* subTLV T + L */
3056 subtlvs
= attr
->extra
->vnc_subtlvs
;
3057 if (subtlvs
== NULL
) /* nothing to do */
3059 attrlenfield
= 0; /* no outer T + L */
3060 attrhdrlen
= 2 + 2; /* subTLV T + L */
3068 /* compute attr length */
3069 for (st
= subtlvs
; st
; st
= st
->next
) {
3070 attrlenfield
+= (attrhdrlen
+ st
->length
);
3073 if (attrlenfield
> 0xffff) {
3074 zlog_info ("%s attribute is too long (length=%d), can't send it",
3080 if (attrlenfield
> 0xff) {
3081 /* 2-octet length field */
3083 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3084 stream_putc (s
, attrtype
);
3085 stream_putw (s
, attrlenfield
& 0xffff);
3087 /* 1-octet length field */
3088 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
3089 stream_putc (s
, attrtype
);
3090 stream_putc (s
, attrlenfield
& 0xff);
3093 if (attrtype
== BGP_ATTR_ENCAP
) {
3094 /* write outer T+L */
3095 stream_putw(s
, attr
->extra
->encap_tunneltype
);
3096 stream_putw(s
, attrlenfield
- 4);
3099 /* write each sub-tlv */
3100 for (st
= subtlvs
; st
; st
= st
->next
) {
3101 if (attrtype
== BGP_ATTR_ENCAP
) {
3102 stream_putc (s
, st
->type
);
3103 stream_putc (s
, st
->length
);
3106 stream_putw (s
, st
->type
);
3107 stream_putw (s
, st
->length
);
3110 stream_put (s
, st
->value
, st
->length
);
3115 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
3117 /* Set MP attribute length. Don't count the (2) bytes used to encode
3119 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
3122 /* Make attribute packet. */
3124 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
3125 struct stream
*s
, struct attr
*attr
,
3126 struct bpacket_attr_vec_arr
*vecarr
,
3127 struct prefix
*p
, afi_t afi
, safi_t safi
,
3128 struct peer
*from
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3130 u_int32_t addpath_tx_id
)
3133 size_t aspath_sizep
;
3134 struct aspath
*aspath
;
3135 int send_as4_path
= 0;
3136 int send_as4_aggregator
= 0;
3137 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3142 /* Remember current pointer. */
3143 cp
= stream_get_endp (s
);
3145 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
3146 !peer_cap_enhe(peer
, afi
, safi
)))
3148 size_t mpattrlen_pos
= 0;
3150 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
, vecarr
, attr
);
3151 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3152 addpath_encode
, addpath_tx_id
, attr
);
3153 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3156 /* Origin attribute. */
3157 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3158 stream_putc (s
, BGP_ATTR_ORIGIN
);
3160 stream_putc (s
, attr
->origin
);
3162 /* AS path attribute. */
3164 /* If remote-peer is EBGP */
3165 if (peer
->sort
== BGP_PEER_EBGP
3166 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
3167 || attr
->aspath
->segments
== NULL
)
3168 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
3170 aspath
= aspath_dup (attr
->aspath
);
3172 /* Even though we may not be configured for confederations we may have
3173 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3174 aspath
= aspath_delete_confed_seq (aspath
);
3176 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
3178 /* Stuff our path CONFED_ID on the front */
3179 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
3183 if (peer
->change_local_as
) {
3184 /* If replace-as is specified, we only use the change_local_as when
3185 advertising routes. */
3186 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
3187 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3189 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
3191 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3195 else if (peer
->sort
== BGP_PEER_CONFED
)
3197 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
3198 aspath
= aspath_dup (attr
->aspath
);
3199 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
3202 aspath
= attr
->aspath
;
3204 /* If peer is not AS4 capable, then:
3205 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3206 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
3207 * types are in it (i.e. exclude them if they are there)
3208 * AND do this only if there is at least one asnum > 65535 in the path!
3209 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
3210 * all ASnums > 65535 to BGP_AS_TRANS
3213 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3214 stream_putc (s
, BGP_ATTR_AS_PATH
);
3215 aspath_sizep
= stream_get_endp (s
);
3217 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
3219 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3222 if (!use32bit
&& aspath_has_as4 (aspath
))
3223 send_as4_path
= 1; /* we'll do this later, at the correct place */
3225 /* Nexthop attribute. */
3226 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
, afi
, safi
))
3228 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
3230 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3231 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3232 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3234 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3236 else if (peer_cap_enhe(from
, afi
, safi
))
3239 * Likely this is the case when an IPv4 prefix was received with
3240 * Extended Next-hop capability and now being advertised to
3242 * Setting the mandatory (ipv4) next-hop attribute here to enable
3243 * implicit next-hop self with correct (ipv4 address family).
3245 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3246 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3247 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
3249 stream_put_ipv4 (s
, 0);
3253 /* MED attribute. */
3254 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
3257 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3258 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3260 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
3263 /* Local preference. */
3264 if (peer
->sort
== BGP_PEER_IBGP
||
3265 peer
->sort
== BGP_PEER_CONFED
)
3267 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3268 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3270 stream_putl (s
, attr
->local_pref
);
3273 /* Atomic aggregate. */
3274 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3276 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3277 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3282 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3284 assert (attr
->extra
);
3286 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3287 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3288 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3292 /* AS4 capable peer */
3294 stream_putl (s
, attr
->extra
->aggregator_as
);
3298 /* 2-byte AS peer */
3301 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3302 if ( attr
->extra
->aggregator_as
> 65535 )
3304 stream_putw (s
, BGP_AS_TRANS
);
3306 /* we have to send AS4_AGGREGATOR, too.
3307 * we'll do that later in order to send attributes in ascending
3310 send_as4_aggregator
= 1;
3313 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
3315 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3318 /* Community attribute. */
3319 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3320 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
3322 if (attr
->community
->size
* 4 > 255)
3324 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3325 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3326 stream_putw (s
, attr
->community
->size
* 4);
3330 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3331 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3332 stream_putc (s
, attr
->community
->size
* 4);
3334 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3338 * Large Community attribute.
3341 CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_LARGE_COMMUNITY
)
3342 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
)))
3344 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3346 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3347 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3348 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3352 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3353 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3354 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3356 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3359 /* Route Reflector. */
3360 if (peer
->sort
== BGP_PEER_IBGP
3362 && from
->sort
== BGP_PEER_IBGP
)
3364 /* Originator ID. */
3365 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3366 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
3369 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3370 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
3372 stream_put_in_addr (s
, &from
->remote_id
);
3375 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3376 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
3378 if (attr
->extra
&& attr
->extra
->cluster
)
3380 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
3381 /* If this peer configuration's parent BGP has cluster_id. */
3382 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3383 stream_put_in_addr (s
, &bgp
->cluster_id
);
3385 stream_put_in_addr (s
, &bgp
->router_id
);
3386 stream_put (s
, attr
->extra
->cluster
->list
,
3387 attr
->extra
->cluster
->length
);
3392 /* If this peer configuration's parent BGP has cluster_id. */
3393 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3394 stream_put_in_addr (s
, &bgp
->cluster_id
);
3396 stream_put_in_addr (s
, &bgp
->router_id
);
3400 /* Extended Communities attribute. */
3401 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3402 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
3404 struct attr_extra
*attre
= attr
->extra
;
3408 if (peer
->sort
== BGP_PEER_IBGP
3409 || peer
->sort
== BGP_PEER_CONFED
)
3411 if (attre
->ecommunity
->size
* 8 > 255)
3413 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3414 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3415 stream_putw (s
, attre
->ecommunity
->size
* 8);
3419 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3420 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3421 stream_putc (s
, attre
->ecommunity
->size
* 8);
3423 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
3429 int ecom_tr_size
= 0;
3432 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3434 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3437 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3445 if (ecom_tr_size
* 8 > 255)
3447 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3448 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3449 stream_putw (s
, ecom_tr_size
* 8);
3453 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3454 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3455 stream_putc (s
, ecom_tr_size
* 8);
3458 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3460 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3463 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3466 stream_put (s
, pnt
, 8);
3472 /* Label index attribute. */
3473 if (safi
== SAFI_LABELED_UNICAST
)
3475 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3477 u_int32_t label_index
;
3479 assert (attr
->extra
);
3480 label_index
= attr
->extra
->label_index
;
3482 if (label_index
!= BGP_INVALID_LABEL_INDEX
)
3484 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3485 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3486 stream_putc (s
, 10);
3487 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3488 stream_putw (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3489 stream_putc (s
, 0); // reserved
3490 stream_putw (s
, 0); // flags
3491 stream_putl (s
, label_index
);
3496 if ( send_as4_path
)
3498 /* If the peer is NOT As4 capable, AND */
3499 /* there are ASnums > 65535 in path THEN
3500 * give out AS4_PATH */
3502 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3504 * Hm, I wonder... confederation things *should* only be at
3505 * the beginning of an aspath, right? Then we should use
3506 * aspath_delete_confed_seq for this, because it is already
3508 * Folks, talk to me: what is reasonable here!?
3510 aspath
= aspath_delete_confed_seq (aspath
);
3512 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3513 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3514 aspath_sizep
= stream_get_endp (s
);
3516 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3519 if (aspath
!= attr
->aspath
)
3520 aspath_free (aspath
);
3522 if ( send_as4_aggregator
)
3524 assert (attr
->extra
);
3526 /* send AS4_AGGREGATOR, at this place */
3527 /* this section of code moved here in order to ensure the correct
3528 * *ascending* order of attributes
3530 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3531 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3533 stream_putl (s
, attr
->extra
->aggregator_as
);
3534 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3537 if (((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3538 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
)) ||
3539 (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3541 /* Tunnel Encap attribute */
3542 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3546 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3550 /* Unknown transit attribute. */
3551 if (attr
->extra
&& attr
->extra
->transit
)
3552 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3554 /* Return total size of attribute. */
3555 return stream_get_endp (s
) - cp
;
3559 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3561 unsigned long attrlen_pnt
;
3565 /* Set extended bit always to encode the attribute length as 2 bytes */
3566 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3567 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3569 attrlen_pnt
= stream_get_endp (s
);
3570 stream_putw (s
, 0); /* Length of this attribute. */
3572 /* Convert AFI, SAFI to values for packet. */
3573 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
3575 stream_putw (s
, pkt_afi
);
3576 stream_putc (s
, pkt_safi
);
3582 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3583 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3584 mpls_label_t
*label
, int addpath_encode
,
3585 u_int32_t addpath_tx_id
, struct attr
*attr
)
3587 u_char wlabel
[3] = {0x80, 0x00, 0x00};
3589 if (safi
== SAFI_LABELED_UNICAST
)
3590 label
= (mpls_label_t
*) wlabel
;
3592 return bgp_packet_mpattr_prefix (s
, afi
, safi
, p
, prd
,
3594 addpath_encode
, addpath_tx_id
, attr
);
3598 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3600 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3603 /* Initialization of attribute. */
3605 bgp_attr_init (void)
3618 bgp_attr_finish (void)
3622 community_finish ();
3623 ecommunity_finish ();
3624 lcommunity_finish ();
3630 /* Make attribute packet. */
3632 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3633 struct prefix
*prefix
)
3638 struct aspath
*aspath
;
3639 int addpath_encode
= 0;
3640 u_int32_t addpath_tx_id
= 0;
3642 /* Remember current pointer. */
3643 cp
= stream_get_endp (s
);
3645 /* Place holder of length. */
3648 /* Origin attribute. */
3649 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3650 stream_putc (s
, BGP_ATTR_ORIGIN
);
3652 stream_putc (s
, attr
->origin
);
3654 aspath
= attr
->aspath
;
3656 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3657 stream_putc (s
, BGP_ATTR_AS_PATH
);
3658 aspath_lenp
= stream_get_endp (s
);
3661 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3663 /* Nexthop attribute. */
3664 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3665 if(prefix
!= NULL
&& prefix
->family
!= AF_INET6
)
3667 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3668 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3670 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3673 /* MED attribute. */
3674 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3676 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3677 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3679 stream_putl (s
, attr
->med
);
3682 /* Local preference. */
3683 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3685 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3686 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3688 stream_putl (s
, attr
->local_pref
);
3691 /* Atomic aggregate. */
3692 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3694 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3695 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3700 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3702 assert (attr
->extra
);
3703 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3704 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3706 stream_putl (s
, attr
->extra
->aggregator_as
);
3707 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3710 /* Community attribute. */
3711 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3713 if (attr
->community
->size
* 4 > 255)
3715 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3716 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3717 stream_putw (s
, attr
->community
->size
* 4);
3721 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3722 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3723 stream_putc (s
, attr
->community
->size
* 4);
3725 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3728 /* Large Community attribute. */
3729 if (attr
->extra
&& attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
))
3731 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3733 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3734 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3735 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3739 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3740 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3741 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3744 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3747 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3748 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3749 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3750 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3753 struct attr_extra
*attre
= attr
->extra
;
3755 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3756 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3757 sizep
= stream_get_endp (s
);
3760 stream_putc (s
, 0); /* Marker: Attribute length. */
3761 stream_putw(s
, AFI_IP6
); /* AFI */
3762 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3765 stream_putc(s
, attre
->mp_nexthop_len
);
3766 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3767 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3768 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3774 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3776 /* Set MP attribute length. */
3777 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3781 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3783 assert (attr
->extra
);
3785 if (attr
->extra
->label_index
!= BGP_INVALID_LABEL_INDEX
)
3787 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3788 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3789 stream_putc (s
, 10);
3790 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3791 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3792 stream_putc (s
, 0); // reserved
3793 stream_putw (s
, 0); // flags
3794 stream_putl (s
, attr
->extra
->label_index
);
3798 /* Return total size of attribute. */
3799 len
= stream_get_endp (s
) - cp
- 2;
3800 stream_putw_at (s
, cp
, len
);