1 /* BGP attributes management routines.
2 Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 This file is part of GNU Zebra.
6 GNU Zebra is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 GNU Zebra is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_packet.h"
43 #include "bgpd/bgp_ecommunity.h"
44 #include "bgpd/bgp_lcommunity.h"
45 #include "bgpd/bgp_updgrp.h"
46 #include "bgpd/bgp_encap_types.h"
48 # include "bgpd/rfapi/bgp_rfapi_cfg.h"
49 # include "bgp_encap_types.h"
50 # include "bgp_vnc_types.h"
52 #include "bgp_encap_types.h"
55 /* Attribute strings for logging. */
56 static const struct message attr_str
[] =
58 { BGP_ATTR_ORIGIN
, "ORIGIN" },
59 { BGP_ATTR_AS_PATH
, "AS_PATH" },
60 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
61 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
62 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
63 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
64 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
65 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
66 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
67 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
68 { BGP_ATTR_DPA
, "DPA" },
69 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
70 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
71 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
72 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
73 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
74 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
75 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
76 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
77 { BGP_ATTR_ENCAP
, "ENCAP" },
79 { BGP_ATTR_VNC
, "VNC" },
81 { BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY" },
82 { BGP_ATTR_PREFIX_SID
, "PREFIX_SID" }
84 static const int attr_str_max
= array_size(attr_str
);
86 static const struct message attr_flag_str
[] =
88 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
89 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
90 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
91 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
92 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
95 static struct hash
*cluster_hash
;
98 cluster_hash_alloc (void *p
)
100 const struct cluster_list
*val
= (const struct cluster_list
*) p
;
101 struct cluster_list
*cluster
;
103 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
104 cluster
->length
= val
->length
;
108 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
109 memcpy (cluster
->list
, val
->list
, val
->length
);
112 cluster
->list
= NULL
;
119 /* Cluster list related functions. */
120 static struct cluster_list
*
121 cluster_parse (struct in_addr
* pnt
, int length
)
123 struct cluster_list tmp
;
124 struct cluster_list
*cluster
;
129 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
135 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
139 for (i
= 0; i
< cluster
->length
/ 4; i
++)
140 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
146 cluster_hash_key_make (void *p
)
148 const struct cluster_list
*cluster
= p
;
150 return jhash(cluster
->list
, cluster
->length
, 0);
154 cluster_hash_cmp (const void *p1
, const void *p2
)
156 const struct cluster_list
* cluster1
= p1
;
157 const struct cluster_list
* cluster2
= p2
;
159 return (cluster1
->length
== cluster2
->length
&&
160 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
164 cluster_free (struct cluster_list
*cluster
)
167 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
168 XFREE (MTYPE_CLUSTER
, cluster
);
171 static struct cluster_list
*
172 cluster_dup (struct cluster_list
*cluster
)
174 struct cluster_list
*new;
176 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
177 new->length
= cluster
->length
;
181 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
182 memcpy (new->list
, cluster
->list
, cluster
->length
);
190 static struct cluster_list
*
191 cluster_intern (struct cluster_list
*cluster
)
193 struct cluster_list
*find
;
195 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
202 cluster_unintern (struct cluster_list
*cluster
)
207 if (cluster
->refcnt
== 0)
209 hash_release (cluster_hash
, cluster
);
210 cluster_free (cluster
);
217 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
221 cluster_finish (void)
223 hash_clean (cluster_hash
, (void (*)(void *))cluster_free
);
224 hash_free (cluster_hash
);
228 static struct hash
*encap_hash
= NULL
;
230 static struct hash
*vnc_hash
= NULL
;
233 struct bgp_attr_encap_subtlv
*
234 encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
236 struct bgp_attr_encap_subtlv
*new;
237 struct bgp_attr_encap_subtlv
*tail
;
238 struct bgp_attr_encap_subtlv
*p
;
240 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
241 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
243 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
246 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
249 memcpy(tail
, p
, size
);
257 encap_free(struct bgp_attr_encap_subtlv
*p
)
259 struct bgp_attr_encap_subtlv
*next
;
263 XFREE(MTYPE_ENCAP_TLV
, p
);
269 bgp_attr_flush_encap(struct attr
*attr
)
271 if (!attr
|| !attr
->extra
)
274 if (attr
->extra
->encap_subtlvs
) {
275 encap_free(attr
->extra
->encap_subtlvs
);
276 attr
->extra
->encap_subtlvs
= NULL
;
279 if (attr
->extra
->vnc_subtlvs
) {
280 encap_free(attr
->extra
->vnc_subtlvs
);
281 attr
->extra
->vnc_subtlvs
= NULL
;
287 * Compare encap sub-tlv chains
292 * This algorithm could be made faster if needed
295 encap_same(struct bgp_attr_encap_subtlv
*h1
, struct bgp_attr_encap_subtlv
*h2
)
297 struct bgp_attr_encap_subtlv
*p
;
298 struct bgp_attr_encap_subtlv
*q
;
302 if (h1
== NULL
|| h2
== NULL
)
305 for (p
= h1
; p
; p
= p
->next
) {
306 for (q
= h2
; q
; q
= q
->next
) {
307 if ((p
->type
== q
->type
) &&
308 (p
->length
== q
->length
) &&
309 !memcmp(p
->value
, q
->value
, p
->length
)) {
318 for (p
= h2
; p
; p
= p
->next
) {
319 for (q
= h1
; q
; q
= q
->next
) {
320 if ((p
->type
== q
->type
) &&
321 (p
->length
== q
->length
) &&
322 !memcmp(p
->value
, q
->value
, p
->length
)) {
335 encap_hash_alloc (void *p
)
337 /* Encap structure is already allocated. */
349 static struct bgp_attr_encap_subtlv
*
350 encap_intern (struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
352 struct bgp_attr_encap_subtlv
*find
;
353 struct hash
*hash
= encap_hash
;
355 if (type
== VNC_SUBTLV_TYPE
)
359 find
= hash_get (hash
, encap
, encap_hash_alloc
);
368 encap_unintern (struct bgp_attr_encap_subtlv
**encapp
, encap_subtlv_type type
)
370 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
374 if (encap
->refcnt
== 0)
376 struct hash
*hash
= encap_hash
;
378 if (type
== VNC_SUBTLV_TYPE
)
381 hash_release (hash
, encap
);
388 encap_hash_key_make (void *p
)
390 const struct bgp_attr_encap_subtlv
* encap
= p
;
392 return jhash(encap
->value
, encap
->length
, 0);
396 encap_hash_cmp (const void *p1
, const void *p2
)
398 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
399 (struct bgp_attr_encap_subtlv
*)p2
);
405 encap_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
407 vnc_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
414 hash_clean (encap_hash
, (void (*)(void *))encap_free
);
415 hash_free (encap_hash
);
418 hash_clean (vnc_hash
, (void (*)(void *))encap_free
);
419 hash_free (vnc_hash
);
425 overlay_index_same(const struct attr_extra
*ae1
, const struct attr_extra
*ae2
)
433 return !memcmp(&(ae1
->evpn_overlay
), &(ae2
->evpn_overlay
), sizeof(struct overlay_index
));
436 /* Unknown transit attribute. */
437 static struct hash
*transit_hash
;
440 transit_free (struct transit
*transit
)
443 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
444 XFREE (MTYPE_TRANSIT
, transit
);
447 static struct transit
*
448 transit_dup (struct transit
*transit
)
452 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
453 new->length
= transit
->length
;
456 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
457 memcpy (new->val
, transit
->val
, transit
->length
);
466 transit_hash_alloc (void *p
)
468 /* Transit structure is already allocated. */
472 static struct transit
*
473 transit_intern (struct transit
*transit
)
475 struct transit
*find
;
477 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
479 transit_free (transit
);
486 transit_unintern (struct transit
*transit
)
491 if (transit
->refcnt
== 0)
493 hash_release (transit_hash
, transit
);
494 transit_free (transit
);
499 transit_hash_key_make (void *p
)
501 const struct transit
* transit
= p
;
503 return jhash(transit
->val
, transit
->length
, 0);
507 transit_hash_cmp (const void *p1
, const void *p2
)
509 const struct transit
* transit1
= p1
;
510 const struct transit
* transit2
= p2
;
512 return (transit1
->length
== transit2
->length
&&
513 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
519 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
523 transit_finish (void)
525 hash_clean (transit_hash
, (void (*)(void *))transit_free
);
526 hash_free (transit_hash
);
530 /* Attribute hash routines. */
531 static struct hash
*attrhash
;
533 static struct attr_extra
*
534 bgp_attr_extra_new (void)
536 struct attr_extra
*extra
;
537 extra
= XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
538 extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
543 bgp_attr_extra_free (struct attr
*attr
)
547 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
553 bgp_attr_extra_get (struct attr
*attr
)
556 attr
->extra
= bgp_attr_extra_new();
560 /* Shallow copy of an attribute
561 * Though, not so shallow that it doesn't copy the contents
562 * of the attr_extra pointed to by 'extra'
565 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
567 struct attr_extra
*extra
= new->extra
;
570 /* if caller provided attr_extra space, use it in any case.
572 * This is neccesary even if orig->extra equals NULL, because otherwise
573 * memory may be later allocated on the heap by bgp_attr_extra_get.
575 * That memory would eventually be leaked, because the caller must not
576 * call bgp_attr_extra_free if he provided attr_extra on the stack.
581 memset(new->extra
, 0, sizeof(struct attr_extra
));
583 *new->extra
= *orig
->extra
;
586 else if (orig
->extra
)
588 new->extra
= bgp_attr_extra_new();
589 *new->extra
= *orig
->extra
;
594 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
597 new->aspath
= aspath_dup(orig
->aspath
);
600 new->community
= community_dup(orig
->community
);
604 if (orig
->extra
->ecommunity
)
605 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
606 if (orig
->extra
->cluster
)
607 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
608 if (orig
->extra
->transit
)
609 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
610 if (orig
->extra
->encap_subtlvs
)
611 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
613 if (orig
->extra
->vnc_subtlvs
)
614 new->extra
->vnc_subtlvs
= encap_tlv_dup(orig
->extra
->vnc_subtlvs
);
620 bgp_attr_deep_free (struct attr
*attr
)
623 aspath_free(attr
->aspath
);
626 community_free(attr
->community
);
630 if (attr
->extra
->ecommunity
)
631 ecommunity_free(&attr
->extra
->ecommunity
);
632 if (attr
->extra
->cluster
)
633 cluster_free(attr
->extra
->cluster
);
634 if (attr
->extra
->transit
)
635 transit_free(attr
->extra
->transit
);
636 if (attr
->extra
->encap_subtlvs
)
637 encap_free(attr
->extra
->encap_subtlvs
);
639 if (attr
->extra
->vnc_subtlvs
)
640 encap_free(attr
->extra
->vnc_subtlvs
);
648 return attrhash
->count
;
652 attr_unknown_count (void)
654 return transit_hash
->count
;
658 attrhash_key_make (void *p
)
660 const struct attr
*attr
= (struct attr
*) p
;
661 const struct attr_extra
*extra
= attr
->extra
;
663 #define MIX(val) key = jhash_1word(val, key)
666 MIX(attr
->nexthop
.s_addr
);
668 MIX(attr
->local_pref
);
671 key
+= attr
->nexthop
.s_addr
;
673 key
+= attr
->local_pref
;
677 MIX(extra
->aggregator_as
);
678 MIX(extra
->aggregator_addr
.s_addr
);
680 MIX(extra
->mp_nexthop_global_in
.s_addr
);
681 MIX(extra
->originator_id
.s_addr
);
683 MIX(extra
->label_index
);
687 MIX(aspath_key_make (attr
->aspath
));
689 MIX(community_hash_make (attr
->community
));
693 if (extra
->lcommunity
)
694 MIX(lcommunity_hash_make (extra
->lcommunity
));
695 if (extra
->ecommunity
)
696 MIX(ecommunity_hash_make (extra
->ecommunity
));
698 MIX(cluster_hash_key_make (extra
->cluster
));
700 MIX(transit_hash_key_make (extra
->transit
));
701 if (extra
->encap_subtlvs
)
702 MIX(encap_hash_key_make (extra
->encap_subtlvs
));
704 if (extra
->vnc_subtlvs
)
705 MIX(encap_hash_key_make (extra
->vnc_subtlvs
));
707 MIX(extra
->mp_nexthop_len
);
708 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
709 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
716 attrhash_cmp (const void *p1
, const void *p2
)
718 const struct attr
* attr1
= p1
;
719 const struct attr
* attr2
= p2
;
721 if (attr1
->flag
== attr2
->flag
722 && attr1
->origin
== attr2
->origin
723 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
724 && attr1
->aspath
== attr2
->aspath
725 && attr1
->community
== attr2
->community
726 && attr1
->med
== attr2
->med
727 && attr1
->local_pref
== attr2
->local_pref
728 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
730 const struct attr_extra
*ae1
= attr1
->extra
;
731 const struct attr_extra
*ae2
= attr2
->extra
;
734 && ae1
->aggregator_as
== ae2
->aggregator_as
735 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
736 && ae1
->weight
== ae2
->weight
737 && ae1
->tag
== ae2
->tag
738 && ae1
->label_index
== ae2
->label_index
739 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
740 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
741 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
742 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
743 && ae1
->ecommunity
== ae2
->ecommunity
744 && ae1
->lcommunity
== ae2
->lcommunity
745 && ae1
->cluster
== ae2
->cluster
746 && ae1
->transit
== ae2
->transit
747 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
748 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
750 && encap_same(ae1
->vnc_subtlvs
, ae2
->vnc_subtlvs
)
752 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
)
753 && overlay_index_same(ae1
, ae2
))
757 /* neither attribute has extra attributes, so they're same */
767 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
771 * special for hash_clean below
774 attr_vfree (void *attr
)
776 bgp_attr_extra_free ((struct attr
*)attr
);
777 XFREE (MTYPE_ATTR
, attr
);
781 attrhash_finish (void)
783 hash_clean(attrhash
, attr_vfree
);
784 hash_free (attrhash
);
789 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
791 struct attr
*attr
= backet
->data
;
793 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
794 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
798 attr_show_all (struct vty
*vty
)
800 hash_iterate (attrhash
,
801 (void (*)(struct hash_backet
*, void *))
802 attr_show_all_iterator
,
807 bgp_attr_hash_alloc (void *p
)
809 const struct attr
* val
= (const struct attr
*) p
;
812 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
816 attr
->extra
= bgp_attr_extra_new ();
817 *attr
->extra
= *val
->extra
;
818 if (val
->extra
->encap_subtlvs
) {
819 val
->extra
->encap_subtlvs
= NULL
;
822 if (val
->extra
->vnc_subtlvs
) {
823 val
->extra
->vnc_subtlvs
= NULL
;
831 /* Internet argument attribute. */
833 bgp_attr_intern (struct attr
*attr
)
837 /* Intern referenced strucutre. */
840 if (! attr
->aspath
->refcnt
)
841 attr
->aspath
= aspath_intern (attr
->aspath
);
843 attr
->aspath
->refcnt
++;
847 if (! attr
->community
->refcnt
)
848 attr
->community
= community_intern (attr
->community
);
850 attr
->community
->refcnt
++;
854 struct attr_extra
*attre
= attr
->extra
;
856 if (attre
->ecommunity
)
858 if (! attre
->ecommunity
->refcnt
)
859 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
861 attre
->ecommunity
->refcnt
++;
864 if (attre
->lcommunity
)
866 if (! attre
->lcommunity
->refcnt
)
867 attre
->lcommunity
= lcommunity_intern (attre
->lcommunity
);
869 attre
->lcommunity
->refcnt
++;
873 if (! attre
->cluster
->refcnt
)
874 attre
->cluster
= cluster_intern (attre
->cluster
);
876 attre
->cluster
->refcnt
++;
880 if (! attre
->transit
->refcnt
)
881 attre
->transit
= transit_intern (attre
->transit
);
883 attre
->transit
->refcnt
++;
885 if (attre
->encap_subtlvs
)
887 if (! attre
->encap_subtlvs
->refcnt
)
888 attre
->encap_subtlvs
= encap_intern (attre
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
890 attre
->encap_subtlvs
->refcnt
++;
893 if (attre
->vnc_subtlvs
)
895 if (! attre
->vnc_subtlvs
->refcnt
)
896 attre
->vnc_subtlvs
= encap_intern (attre
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
898 attre
->vnc_subtlvs
->refcnt
++;
903 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
910 * Increment the refcount on various structures that attr holds.
911 * Note on usage: call _only_ when the 'attr' object has already
912 * been 'intern'ed and exists in 'attrhash' table. The function
913 * serves to hold a reference to that (real) object.
914 * Note also that the caller can safely call bgp_attr_unintern()
915 * after calling bgp_attr_refcount(). That would release the
916 * reference and could result in a free() of the attr object.
919 bgp_attr_refcount (struct attr
*attr
)
921 /* Intern referenced strucutre. */
923 attr
->aspath
->refcnt
++;
926 attr
->community
->refcnt
++;
930 struct attr_extra
*attre
= attr
->extra
;
931 if (attre
->ecommunity
)
932 attre
->ecommunity
->refcnt
++;
935 attre
->cluster
->refcnt
++;
938 attre
->transit
->refcnt
++;
940 if (attre
->encap_subtlvs
)
941 attre
->encap_subtlvs
->refcnt
++;
944 if (attre
->vnc_subtlvs
)
945 attre
->vnc_subtlvs
->refcnt
++;
952 /* Make network statement's attribute. */
954 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
956 memset (attr
, 0, sizeof (struct attr
));
957 bgp_attr_extra_get (attr
);
959 attr
->origin
= origin
;
960 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
961 attr
->aspath
= aspath_empty ();
962 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
963 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
964 attr
->extra
->tag
= 0;
965 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
966 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
972 /* Make network statement's attribute. */
974 bgp_attr_default_intern (u_char origin
)
979 memset (&attr
, 0, sizeof (struct attr
));
980 bgp_attr_extra_get (&attr
);
982 bgp_attr_default_set(&attr
, origin
);
984 new = bgp_attr_intern (&attr
);
985 bgp_attr_extra_free (&attr
);
987 aspath_unintern (&new->aspath
);
991 /* Create the attributes for an aggregate */
993 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
994 struct aspath
*aspath
,
995 struct community
*community
, int as_set
,
996 u_char atomic_aggregate
)
1000 struct attr_extra attre
;
1002 memset (&attr
, 0, sizeof (struct attr
));
1003 memset (&attre
, 0, sizeof (struct attr_extra
));
1004 attr
.extra
= &attre
;
1006 /* Origin attribute. */
1007 attr
.origin
= origin
;
1008 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1010 /* AS path attribute. */
1012 attr
.aspath
= aspath_intern (aspath
);
1014 attr
.aspath
= aspath_empty ();
1015 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1017 /* Next hop attribute. */
1018 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1022 attr
.community
= community
;
1023 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1026 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1027 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1028 if (! as_set
|| atomic_aggregate
)
1029 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1030 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1031 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1032 attre
.aggregator_as
= bgp
->confed_id
;
1034 attre
.aggregator_as
= bgp
->as
;
1035 attre
.aggregator_addr
= bgp
->router_id
;
1037 new = bgp_attr_intern (&attr
);
1039 aspath_unintern (&new->aspath
);
1043 /* Unintern just the sub-components of the attr, but not the attr */
1045 bgp_attr_unintern_sub (struct attr
*attr
)
1047 /* aspath refcount shoud be decrement. */
1049 aspath_unintern (&attr
->aspath
);
1050 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
1052 if (attr
->community
)
1053 community_unintern (&attr
->community
);
1054 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
1058 if (attr
->extra
->ecommunity
)
1059 ecommunity_unintern (&attr
->extra
->ecommunity
);
1060 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
1062 if (attr
->extra
->lcommunity
)
1063 lcommunity_unintern (&attr
->extra
->lcommunity
);
1064 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
));
1066 if (attr
->extra
->cluster
)
1067 cluster_unintern (attr
->extra
->cluster
);
1068 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
1070 if (attr
->extra
->transit
)
1071 transit_unintern (attr
->extra
->transit
);
1073 if (attr
->extra
->encap_subtlvs
)
1074 encap_unintern (&attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1077 if (attr
->extra
->vnc_subtlvs
)
1078 encap_unintern (&attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1083 /* Free bgp attribute and aspath. */
1085 bgp_attr_unintern (struct attr
**pattr
)
1087 struct attr
*attr
= *pattr
;
1090 struct attr_extra tmp_extra
;
1092 /* Decrement attribute reference. */
1099 tmp
.extra
= &tmp_extra
;
1100 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
1103 /* If reference becomes zero then free attribute object. */
1104 if (attr
->refcnt
== 0)
1106 ret
= hash_release (attrhash
, attr
);
1107 assert (ret
!= NULL
);
1108 bgp_attr_extra_free (attr
);
1109 XFREE (MTYPE_ATTR
, attr
);
1113 bgp_attr_unintern_sub (&tmp
);
1117 bgp_attr_flush (struct attr
*attr
)
1119 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
1121 aspath_free (attr
->aspath
);
1122 attr
->aspath
= NULL
;
1124 if (attr
->community
&& ! attr
->community
->refcnt
)
1126 community_free (attr
->community
);
1127 attr
->community
= NULL
;
1131 struct attr_extra
*attre
= attr
->extra
;
1133 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
1134 ecommunity_free (&attre
->ecommunity
);
1135 if (attre
->lcommunity
&& ! attre
->lcommunity
->refcnt
)
1136 lcommunity_free (&attre
->lcommunity
);
1137 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
1139 cluster_free (attre
->cluster
);
1140 attre
->cluster
= NULL
;
1142 if (attre
->transit
&& ! attre
->transit
->refcnt
)
1144 transit_free (attre
->transit
);
1145 attre
->transit
= NULL
;
1147 if (attre
->encap_subtlvs
&& ! attre
->encap_subtlvs
->refcnt
)
1149 encap_free(attre
->encap_subtlvs
);
1150 attre
->encap_subtlvs
= NULL
;
1153 if (attre
->vnc_subtlvs
&& ! attre
->vnc_subtlvs
->refcnt
)
1155 encap_free(attre
->vnc_subtlvs
);
1156 attre
->vnc_subtlvs
= NULL
;
1162 /* Implement draft-scudder-idr-optional-transitive behaviour and
1163 * avoid resetting sessions for malformed attributes which are
1164 * are partial/optional and hence where the error likely was not
1165 * introduced by the sending neighbour.
1167 static bgp_attr_parse_ret_t
1168 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
1171 struct peer
*const peer
= args
->peer
;
1172 const u_int8_t flags
= args
->flags
;
1173 /* startp and length must be special-cased, as whether or not to
1174 * send the attribute data with the NOTIFY depends on the error,
1175 * the caller therefore signals this with the seperate length argument
1177 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1179 /* Only relax error handling for eBGP peers */
1180 if (peer
->sort
!= BGP_PEER_EBGP
)
1182 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1183 notify_datap
, length
);
1184 return BGP_ATTR_PARSE_ERROR
;
1188 /* Adjust the stream getp to the end of the attribute, in case we can
1189 * still proceed but the caller hasn't read all the attribute.
1191 stream_set_getp (BGP_INPUT (peer
),
1192 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
1195 switch (args
->type
) {
1196 /* where an attribute is relatively inconsequential, e.g. it does not
1197 * affect route selection, and can be safely ignored, then any such
1198 * attributes which are malformed should just be ignored and the route
1199 * processed as normal.
1201 case BGP_ATTR_AS4_AGGREGATOR
:
1202 case BGP_ATTR_AGGREGATOR
:
1203 case BGP_ATTR_ATOMIC_AGGREGATE
:
1204 return BGP_ATTR_PARSE_PROCEED
;
1206 /* Core attributes, particularly ones which may influence route
1207 * selection, should always cause session resets
1209 case BGP_ATTR_ORIGIN
:
1210 case BGP_ATTR_AS_PATH
:
1211 case BGP_ATTR_NEXT_HOP
:
1212 case BGP_ATTR_MULTI_EXIT_DISC
:
1213 case BGP_ATTR_LOCAL_PREF
:
1214 case BGP_ATTR_COMMUNITIES
:
1215 case BGP_ATTR_ORIGINATOR_ID
:
1216 case BGP_ATTR_CLUSTER_LIST
:
1217 case BGP_ATTR_MP_REACH_NLRI
:
1218 case BGP_ATTR_MP_UNREACH_NLRI
:
1219 case BGP_ATTR_EXT_COMMUNITIES
:
1220 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1221 notify_datap
, length
);
1222 return BGP_ATTR_PARSE_ERROR
;
1225 /* Partial optional attributes that are malformed should not cause
1226 * the whole session to be reset. Instead treat it as a withdrawal
1227 * of the routes, if possible.
1229 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1230 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1231 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1232 return BGP_ATTR_PARSE_WITHDRAW
;
1234 /* default to reset */
1235 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1238 /* Find out what is wrong with the path attribute flag bits and log the error.
1239 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1240 Extended Length. Checking O/T/P bits at once implies, that the attribute
1241 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1242 non-transitive" attribute. */
1244 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1245 u_int8_t desired_flags
/* how RFC says it must be */
1249 u_char real_flags
= args
->flags
;
1250 const u_int8_t attr_code
= args
->type
;
1252 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1253 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1254 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1257 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1258 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1261 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1262 LOOKUP (attr_str
, attr_code
),
1263 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1264 attr_flag_str
[i
].str
);
1269 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1270 " (real flags 0x%x, desired 0x%x)",
1271 __func__
, LOOKUP (attr_str
, attr_code
),
1272 real_flags
, desired_flags
);
1276 /* Required flags for attributes. EXTLEN will be masked off when testing,
1277 * as will PARTIAL for optional+transitive attributes.
1279 const u_int8_t attr_flags_values
[] = {
1280 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1281 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1282 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1283 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1284 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1285 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1286 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1287 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1288 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1289 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1290 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1291 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1292 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1293 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1294 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1295 [BGP_ATTR_LARGE_COMMUNITIES
]= BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1296 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1298 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1301 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1303 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1304 const u_int8_t flags
= args
->flags
;
1305 const u_int8_t attr_code
= args
->type
;
1307 /* there may be attributes we don't know about */
1308 if (attr_code
> attr_flags_values_max
)
1310 if (attr_flags_values
[attr_code
] == 0)
1313 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1316 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1317 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1319 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1320 LOOKUP (attr_str
, attr_code
), flags
);
1324 /* "For well-known attributes and for optional non-transitive attributes,
1325 * the Partial bit MUST be set to 0."
1327 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1329 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1331 zlog_err ("%s well-known attribute "
1332 "must NOT have the partial flag set (%x)",
1333 LOOKUP (attr_str
, attr_code
), flags
);
1336 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1337 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1339 zlog_err ("%s optional + transitive attribute "
1340 "must NOT have the partial flag set (%x)",
1341 LOOKUP (attr_str
, attr_code
), flags
);
1346 /* Optional transitive attributes may go through speakers that don't
1347 * reocgnise them and set the Partial bit.
1349 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1350 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1351 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1354 == attr_flags_values
[attr_code
])
1357 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1361 /* Get origin attribute of the update message. */
1362 static bgp_attr_parse_ret_t
1363 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1365 struct peer
*const peer
= args
->peer
;
1366 struct attr
*const attr
= args
->attr
;
1367 const bgp_size_t length
= args
->length
;
1369 /* If any recognized attribute has Attribute Length that conflicts
1370 with the expected length (based on the attribute type code), then
1371 the Error Subcode is set to Attribute Length Error. The Data
1372 field contains the erroneous attribute (type, length and
1376 zlog_err ("Origin attribute length is not one %d", length
);
1377 return bgp_attr_malformed (args
,
1378 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1382 /* Fetch origin attribute. */
1383 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1385 /* If the ORIGIN attribute has an undefined value, then the Error
1386 Subcode is set to Invalid Origin Attribute. The Data field
1387 contains the unrecognized attribute (type, length and value). */
1388 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1389 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1390 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1392 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1393 return bgp_attr_malformed (args
,
1394 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1398 /* Set oring attribute flag. */
1399 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1404 /* Parse AS path information. This function is wrapper of
1407 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1409 struct attr
*const attr
= args
->attr
;
1410 struct peer
*const peer
= args
->peer
;
1411 const bgp_size_t length
= args
->length
;
1414 * peer with AS4 => will get 4Byte ASnums
1415 * otherwise, will get 16 Bit
1417 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1418 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1420 /* In case of IBGP, length will be zero. */
1423 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1424 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1427 /* Set aspath attribute flag. */
1428 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1430 return BGP_ATTR_PARSE_PROCEED
;
1433 static bgp_attr_parse_ret_t
1434 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1436 /* These checks were part of bgp_attr_aspath, but with
1437 * as4 we should to check aspath things when
1438 * aspath synthesizing with as4_path has already taken place.
1439 * Otherwise we check ASPATH and use the synthesized thing, and that is
1441 * So do the checks later, i.e. here
1443 struct bgp
*bgp
= peer
->bgp
;
1444 struct aspath
*aspath
;
1446 /* Confederation sanity check. */
1447 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1448 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1450 zlog_err ("Malformed AS path from %s", peer
->host
);
1451 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1452 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1453 return BGP_ATTR_PARSE_ERROR
;
1456 /* First AS check for EBGP. */
1457 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1459 if (peer
->sort
== BGP_PEER_EBGP
1460 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1462 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1463 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1464 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1465 return BGP_ATTR_PARSE_ERROR
;
1469 /* local-as prepend */
1470 if (peer
->change_local_as
&&
1471 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1473 aspath
= aspath_dup (attr
->aspath
);
1474 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1475 aspath_unintern (&attr
->aspath
);
1476 attr
->aspath
= aspath_intern (aspath
);
1479 return BGP_ATTR_PARSE_PROCEED
;
1482 /* Parse AS4 path information. This function is another wrapper of
1485 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1487 struct peer
*const peer
= args
->peer
;
1488 struct attr
*const attr
= args
->attr
;
1489 const bgp_size_t length
= args
->length
;
1491 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1493 /* In case of IBGP, length will be zero. */
1496 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1497 return bgp_attr_malformed (args
,
1498 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1502 /* Set aspath attribute flag. */
1504 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1506 return BGP_ATTR_PARSE_PROCEED
;
1509 /* Nexthop attribute. */
1510 static bgp_attr_parse_ret_t
1511 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1513 struct peer
*const peer
= args
->peer
;
1514 struct attr
*const attr
= args
->attr
;
1515 const bgp_size_t length
= args
->length
;
1517 in_addr_t nexthop_h
, nexthop_n
;
1519 /* Check nexthop attribute length. */
1522 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1524 return bgp_attr_malformed (args
,
1525 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1529 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1530 attribute must result in a NOTIFICATION message (this is implemented below).
1531 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1532 logged locally (this is implemented somewhere else). The UPDATE message
1533 gets ignored in any of these cases. */
1534 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1535 nexthop_h
= ntohl (nexthop_n
);
1536 if ((IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1537 && !BGP_DEBUG (allow_martians
, ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1539 char buf
[INET_ADDRSTRLEN
];
1540 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1541 zlog_err ("Martian nexthop %s", buf
);
1542 return bgp_attr_malformed (args
,
1543 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1547 attr
->nexthop
.s_addr
= nexthop_n
;
1548 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1550 return BGP_ATTR_PARSE_PROCEED
;
1553 /* MED atrribute. */
1554 static bgp_attr_parse_ret_t
1555 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1557 struct peer
*const peer
= args
->peer
;
1558 struct attr
*const attr
= args
->attr
;
1559 const bgp_size_t length
= args
->length
;
1564 zlog_err ("MED attribute length isn't four [%d]", length
);
1566 return bgp_attr_malformed (args
,
1567 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1571 attr
->med
= stream_getl (peer
->ibuf
);
1573 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1575 return BGP_ATTR_PARSE_PROCEED
;
1578 /* Local preference attribute. */
1579 static bgp_attr_parse_ret_t
1580 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1582 struct peer
*const peer
= args
->peer
;
1583 struct attr
*const attr
= args
->attr
;
1584 const bgp_size_t length
= args
->length
;
1589 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1590 return bgp_attr_malformed (args
,
1591 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1595 /* If it is contained in an UPDATE message that is received from an
1596 external peer, then this attribute MUST be ignored by the
1597 receiving speaker. */
1598 if (peer
->sort
== BGP_PEER_EBGP
)
1600 stream_forward_getp (peer
->ibuf
, length
);
1601 return BGP_ATTR_PARSE_PROCEED
;
1604 attr
->local_pref
= stream_getl (peer
->ibuf
);
1606 /* Set atomic aggregate flag. */
1607 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1609 return BGP_ATTR_PARSE_PROCEED
;
1612 /* Atomic aggregate. */
1614 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1616 struct attr
*const attr
= args
->attr
;
1617 const bgp_size_t length
= args
->length
;
1622 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1623 return bgp_attr_malformed (args
,
1624 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1628 /* Set atomic aggregate flag. */
1629 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1631 return BGP_ATTR_PARSE_PROCEED
;
1634 /* Aggregator attribute */
1636 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1638 struct peer
*const peer
= args
->peer
;
1639 struct attr
*const attr
= args
->attr
;
1640 const bgp_size_t length
= args
->length
;
1643 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1645 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1646 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1649 if (length
!= wantedlen
)
1651 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1652 return bgp_attr_malformed (args
,
1653 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1657 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1658 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1660 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1661 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1663 /* Set atomic aggregate flag. */
1664 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1666 return BGP_ATTR_PARSE_PROCEED
;
1669 /* New Aggregator attribute */
1670 static bgp_attr_parse_ret_t
1671 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1672 as_t
*as4_aggregator_as
,
1673 struct in_addr
*as4_aggregator_addr
)
1675 struct peer
*const peer
= args
->peer
;
1676 struct attr
*const attr
= args
->attr
;
1677 const bgp_size_t length
= args
->length
;
1681 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1682 return bgp_attr_malformed (args
,
1683 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1687 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1688 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1690 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1692 return BGP_ATTR_PARSE_PROCEED
;
1695 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1697 static bgp_attr_parse_ret_t
1698 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1699 struct attr
*const attr
,
1700 struct aspath
*as4_path
, as_t as4_aggregator
,
1701 struct in_addr
*as4_aggregator_addr
)
1703 int ignore_as4_path
= 0;
1704 struct aspath
*newpath
;
1705 struct attr_extra
*attre
= attr
->extra
;
1709 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1710 * checked that all well-known, mandatory attributes were present.
1712 * Can only be a problem with peer itself - hard error
1714 return BGP_ATTR_PARSE_ERROR
;
1717 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1719 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1721 * It is worth a warning though, because the peer really
1722 * should not send them
1724 if (BGP_DEBUG(as4
, AS4
))
1726 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1727 zlog_debug ("[AS4] %s %s AS4_PATH",
1728 peer
->host
, "AS4 capable peer, yet it sent");
1730 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1731 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1732 peer
->host
, "AS4 capable peer, yet it sent");
1735 return BGP_ATTR_PARSE_PROCEED
;
1738 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1739 * because that may override AS4_PATH
1741 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1743 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1748 * if the as_number in aggregator is not AS_TRANS,
1749 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1750 * and the Aggregator shall be taken as
1751 * info on the aggregating node, and the AS_PATH
1752 * shall be taken as the AS_PATH
1754 * the Aggregator shall be ignored and the
1755 * AS4_AGGREGATOR shall be taken as the
1756 * Aggregating node and the AS_PATH is to be
1757 * constructed "as in all other cases"
1759 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1762 if ( BGP_DEBUG(as4
, AS4
))
1763 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1764 " send AGGREGATOR != AS_TRANS and"
1765 " AS4_AGGREGATOR, so ignore"
1766 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1767 ignore_as4_path
= 1;
1771 /* "New_aggregator shall be taken as aggregator" */
1772 attre
->aggregator_as
= as4_aggregator
;
1773 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1778 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1779 * That is bogus - but reading the conditions
1780 * we have to handle AS4_AGGREGATOR as if it were
1781 * AGGREGATOR in that case
1783 if ( BGP_DEBUG(as4
, AS4
))
1784 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1785 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1786 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1787 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1788 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1789 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1793 /* need to reconcile NEW_AS_PATH and AS_PATH */
1794 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1796 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1797 aspath_unintern (&attr
->aspath
);
1798 attr
->aspath
= aspath_intern (newpath
);
1800 return BGP_ATTR_PARSE_PROCEED
;
1803 /* Community attribute. */
1804 static bgp_attr_parse_ret_t
1805 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1807 struct peer
*const peer
= args
->peer
;
1808 struct attr
*const attr
= args
->attr
;
1809 const bgp_size_t length
= args
->length
;
1813 attr
->community
= NULL
;
1814 return BGP_ATTR_PARSE_PROCEED
;
1818 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1820 /* XXX: fix community_parse to use stream API and remove this */
1821 stream_forward_getp (peer
->ibuf
, length
);
1823 if (!attr
->community
)
1824 return bgp_attr_malformed (args
,
1825 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1828 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1830 return BGP_ATTR_PARSE_PROCEED
;
1833 /* Originator ID attribute. */
1834 static bgp_attr_parse_ret_t
1835 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1837 struct peer
*const peer
= args
->peer
;
1838 struct attr
*const attr
= args
->attr
;
1839 const bgp_size_t length
= args
->length
;
1844 zlog_err ("Bad originator ID length %d", length
);
1846 return bgp_attr_malformed (args
,
1847 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1851 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1852 = stream_get_ipv4 (peer
->ibuf
);
1854 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1856 return BGP_ATTR_PARSE_PROCEED
;
1859 /* Cluster list attribute. */
1860 static bgp_attr_parse_ret_t
1861 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1863 struct peer
*const peer
= args
->peer
;
1864 struct attr
*const attr
= args
->attr
;
1865 const bgp_size_t length
= args
->length
;
1870 zlog_err ("Bad cluster list length %d", length
);
1872 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1876 (bgp_attr_extra_get (attr
))->cluster
1877 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1879 /* XXX: Fix cluster_parse to use stream API and then remove this */
1880 stream_forward_getp (peer
->ibuf
, length
);
1882 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1884 return BGP_ATTR_PARSE_PROCEED
;
1887 /* Multiprotocol reachability information parse. */
1889 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1890 struct bgp_nlri
*mp_update
)
1894 safi_t pkt_safi
, safi
;
1895 bgp_size_t nlri_len
;
1898 struct peer
*const peer
= args
->peer
;
1899 struct attr
*const attr
= args
->attr
;
1900 const bgp_size_t length
= args
->length
;
1901 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1903 /* Set end of packet. */
1904 s
= BGP_INPUT(peer
);
1905 start
= stream_get_getp(s
);
1907 /* safe to read statically sized header? */
1908 #define BGP_MP_REACH_MIN_SIZE 5
1909 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1910 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1912 zlog_info ("%s: %s sent invalid length, %lu",
1913 __func__
, peer
->host
, (unsigned long)length
);
1914 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1917 /* Load AFI, SAFI. */
1918 pkt_afi
= stream_getw (s
);
1919 pkt_safi
= stream_getc (s
);
1921 /* Convert AFI, SAFI to internal values, check. */
1922 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
1924 /* Log if AFI or SAFI is unrecognized. This is not an error unless
1925 * the attribute is otherwise malformed.
1927 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1928 zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1929 peer
->host
, pkt_afi
, pkt_safi
);
1930 return BGP_ATTR_PARSE_ERROR
;
1933 /* Get nexthop length. */
1934 attre
->mp_nexthop_len
= stream_getc (s
);
1936 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1938 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1939 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1940 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1943 /* Nexthop length check. */
1944 switch (attre
->mp_nexthop_len
)
1946 case BGP_ATTR_NHLEN_IPV4
:
1947 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1948 /* Probably needed for RFC 2283 */
1949 if (attr
->nexthop
.s_addr
== 0)
1950 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1952 case BGP_ATTR_NHLEN_VPNV4
:
1953 stream_getl (s
); /* RD high */
1954 stream_getl (s
); /* RD low */
1955 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1957 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1958 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1959 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1961 stream_getl (s
); /* RD high */
1962 stream_getl (s
); /* RD low */
1964 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1966 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1967 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1968 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1970 stream_getl (s
); /* RD high */
1971 stream_getl (s
); /* RD low */
1973 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1974 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1976 stream_getl (s
); /* RD high */
1977 stream_getl (s
); /* RD low */
1979 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1980 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1982 char buf1
[INET6_ADDRSTRLEN
];
1983 char buf2
[INET6_ADDRSTRLEN
];
1985 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1986 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1988 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1989 buf1
, INET6_ADDRSTRLEN
),
1990 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1991 buf2
, INET6_ADDRSTRLEN
));
1993 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1997 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1998 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1999 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2004 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
2005 __func__
, peer
->host
);
2006 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2011 if ((val
= stream_getc (s
)))
2012 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
2016 /* must have nrli_len, what is left of the attribute */
2017 nlri_len
= LEN_LEFT
;
2018 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
2020 zlog_info ("%s: (%s) Failed to read NLRI",
2021 __func__
, peer
->host
);
2022 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2025 mp_update
->afi
= afi
;
2026 mp_update
->safi
= safi
;
2027 mp_update
->nlri
= stream_pnt (s
);
2028 mp_update
->length
= nlri_len
;
2030 stream_forward_getp (s
, nlri_len
);
2032 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
2034 return BGP_ATTR_PARSE_PROCEED
;
2038 /* Multiprotocol unreachable parse */
2040 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
2041 struct bgp_nlri
*mp_withdraw
)
2046 safi_t pkt_safi
, safi
;
2047 u_int16_t withdraw_len
;
2048 struct peer
*const peer
= args
->peer
;
2049 struct attr
*const attr
= args
->attr
;
2050 const bgp_size_t length
= args
->length
;
2054 #define BGP_MP_UNREACH_MIN_SIZE 3
2055 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2056 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2058 pkt_afi
= stream_getw (s
);
2059 pkt_safi
= stream_getc (s
);
2061 /* Convert AFI, SAFI to internal values, check. */
2062 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
2064 /* Log if AFI or SAFI is unrecognized. This is not an error unless
2065 * the attribute is otherwise malformed.
2067 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2068 zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
2069 peer
->host
, pkt_afi
, pkt_safi
);
2070 return BGP_ATTR_PARSE_ERROR
;
2073 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2075 mp_withdraw
->afi
= afi
;
2076 mp_withdraw
->safi
= safi
;
2077 mp_withdraw
->nlri
= stream_pnt (s
);
2078 mp_withdraw
->length
= withdraw_len
;
2080 stream_forward_getp (s
, withdraw_len
);
2082 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
2084 return BGP_ATTR_PARSE_PROCEED
;
2087 /* Large Community attribute. */
2088 static bgp_attr_parse_ret_t
2089 bgp_attr_large_community (struct bgp_attr_parser_args
*args
)
2091 struct peer
*const peer
= args
->peer
;
2092 struct attr
*const attr
= args
->attr
;
2093 const bgp_size_t length
= args
->length
;
2096 * Large community follows new attribute format.
2101 attr
->extra
->lcommunity
= NULL
;
2102 /* Empty extcomm doesn't seem to be invalid per se */
2103 return BGP_ATTR_PARSE_PROCEED
;
2106 (bgp_attr_extra_get (attr
))->lcommunity
=
2107 lcommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2108 /* XXX: fix ecommunity_parse to use stream API */
2109 stream_forward_getp (peer
->ibuf
, length
);
2111 if (attr
->extra
&& !attr
->extra
->lcommunity
)
2112 return bgp_attr_malformed (args
,
2113 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2116 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
);
2118 return BGP_ATTR_PARSE_PROCEED
;
2121 /* Extended Community attribute. */
2122 static bgp_attr_parse_ret_t
2123 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
2125 struct peer
*const peer
= args
->peer
;
2126 struct attr
*const attr
= args
->attr
;
2127 const bgp_size_t length
= args
->length
;
2132 attr
->extra
->ecommunity
= NULL
;
2133 /* Empty extcomm doesn't seem to be invalid per se */
2134 return BGP_ATTR_PARSE_PROCEED
;
2137 (bgp_attr_extra_get (attr
))->ecommunity
=
2138 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2139 /* XXX: fix ecommunity_parse to use stream API */
2140 stream_forward_getp (peer
->ibuf
, length
);
2142 if (attr
->extra
&& !attr
->extra
->ecommunity
)
2143 return bgp_attr_malformed (args
,
2144 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2147 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
2149 return BGP_ATTR_PARSE_PROCEED
;
2152 /* Parse Tunnel Encap attribute in an UPDATE */
2156 struct peer
*peer
, /* IN */
2157 bgp_size_t length
, /* IN: attr's length field */
2158 struct attr
*attr
, /* IN: caller already allocated */
2159 u_char flag
, /* IN: attr's flags field */
2163 struct attr_extra
*attre
= NULL
;
2164 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2165 uint16_t tunneltype
= 0;
2167 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2169 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2170 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
2172 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
2173 bgp_notify_send_with_data (peer
,
2174 BGP_NOTIFY_UPDATE_ERR
,
2175 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2180 if (BGP_ATTR_ENCAP
== type
) {
2181 /* read outer TLV type and length */
2182 uint16_t tlv_length
;
2185 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2186 bgp_notify_send_with_data(peer
,
2187 BGP_NOTIFY_UPDATE_ERR
,
2188 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2192 tunneltype
= stream_getw (BGP_INPUT (peer
));
2193 tlv_length
= stream_getw (BGP_INPUT (peer
));
2196 if (tlv_length
!= length
) {
2197 zlog_info ("%s: tlv_length(%d) != length(%d)",
2198 __func__
, tlv_length
, length
);
2202 while (length
>= 4) {
2203 uint16_t subtype
= 0;
2204 uint16_t sublength
= 0;
2205 struct bgp_attr_encap_subtlv
*tlv
;
2207 if (BGP_ATTR_ENCAP
== type
) {
2208 subtype
= stream_getc (BGP_INPUT (peer
));
2209 sublength
= stream_getc (BGP_INPUT (peer
));
2213 subtype
= stream_getw (BGP_INPUT (peer
));
2214 sublength
= stream_getw (BGP_INPUT (peer
));
2219 if (sublength
> length
) {
2220 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2222 bgp_notify_send_with_data (peer
,
2223 BGP_NOTIFY_UPDATE_ERR
,
2224 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2229 /* alloc and copy sub-tlv */
2230 /* TBD make sure these are freed when attributes are released */
2231 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
2232 tlv
->type
= subtype
;
2233 tlv
->length
= sublength
;
2234 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2235 length
-= sublength
;
2237 /* attach tlv to encap chain */
2239 attre
= bgp_attr_extra_get(attr
);
2240 if (BGP_ATTR_ENCAP
== type
) {
2241 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
2242 stlv_last
= stlv_last
->next
);
2244 stlv_last
->next
= tlv
;
2246 attre
->encap_subtlvs
= tlv
;
2250 for (stlv_last
= attre
->vnc_subtlvs
; stlv_last
&& stlv_last
->next
;
2251 stlv_last
= stlv_last
->next
);
2253 stlv_last
->next
= tlv
;
2255 attre
->vnc_subtlvs
= tlv
;
2260 stlv_last
->next
= tlv
;
2265 if (BGP_ATTR_ENCAP
== type
) {
2267 attre
= bgp_attr_extra_get(attr
);
2268 attre
->encap_tunneltype
= tunneltype
;
2272 /* spurious leftover data */
2273 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2274 bgp_notify_send_with_data (peer
,
2275 BGP_NOTIFY_UPDATE_ERR
,
2276 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2284 /* Prefix SID attribute
2285 * draft-ietf-idr-bgp-prefix-sid-05
2287 static bgp_attr_parse_ret_t
2288 bgp_attr_prefix_sid (struct bgp_attr_parser_args
*args
, struct bgp_nlri
*mp_update
)
2290 struct peer
*const peer
= args
->peer
;
2291 struct attr
*const attr
= args
->attr
;
2294 u_int32_t label_index
;
2295 struct in6_addr ipv6_sid
;
2296 u_int32_t srgb_base
;
2297 u_int32_t srgb_range
;
2300 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
);
2302 type
= stream_getc (peer
->ibuf
);
2303 length
= stream_getw (peer
->ibuf
);
2305 if (type
== BGP_PREFIX_SID_LABEL_INDEX
)
2307 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
)
2309 zlog_err ("Prefix SID label index length is %d instead of %d", length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2310 return bgp_attr_malformed (args
,
2311 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2315 /* Ignore flags and reserved */
2316 stream_getc (peer
->ibuf
);
2317 stream_getw (peer
->ibuf
);
2319 /* Fetch the label index and see if it is valid. */
2320 label_index
= stream_getl (peer
->ibuf
);
2321 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2322 return bgp_attr_malformed (args
,
2323 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2326 /* Store label index; subsequently, we'll check on address-family */
2327 (bgp_attr_extra_get (attr
))->label_index
= label_index
;
2330 * Ignore the Label index attribute unless received for labeled-unicast
2333 if (!mp_update
->length
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2334 attr
->extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
2337 /* Placeholder code for the IPv6 SID type */
2338 else if (type
== BGP_PREFIX_SID_IPV6
)
2340 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
)
2342 zlog_err ("Prefix SID IPv6 length is %d instead of %d", length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2343 return bgp_attr_malformed (args
,
2344 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2348 /* Ignore reserved */
2349 stream_getc (peer
->ibuf
);
2350 stream_getw (peer
->ibuf
);
2352 stream_get (&ipv6_sid
, peer
->ibuf
, 16);
2355 /* Placeholder code for the Originator SRGB type */
2356 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
)
2359 stream_getw (peer
->ibuf
);
2363 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)
2365 zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2366 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2367 return bgp_attr_malformed (args
,
2368 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2372 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2374 for (int i
= 0; i
< srgb_count
; i
++)
2376 stream_get (&srgb_base
, peer
->ibuf
, 3);
2377 stream_get (&srgb_range
, peer
->ibuf
, 3);
2381 return BGP_ATTR_PARSE_PROCEED
;
2384 /* BGP unknown attribute treatment. */
2385 static bgp_attr_parse_ret_t
2386 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2388 bgp_size_t total
= args
->total
;
2389 struct transit
*transit
;
2390 struct attr_extra
*attre
;
2391 struct peer
*const peer
= args
->peer
;
2392 struct attr
*const attr
= args
->attr
;
2393 u_char
*const startp
= args
->startp
;
2394 const u_char type
= args
->type
;
2395 const u_char flag
= args
->flags
;
2396 const bgp_size_t length
= args
->length
;
2398 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2399 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2400 peer
->host
, type
, length
);
2402 /* Forward read pointer of input stream. */
2403 stream_forward_getp (peer
->ibuf
, length
);
2405 /* If any of the mandatory well-known attributes are not recognized,
2406 then the Error Subcode is set to Unrecognized Well-known
2407 Attribute. The Data field contains the unrecognized attribute
2408 (type, length and value). */
2409 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2411 return bgp_attr_malformed (args
,
2412 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2416 /* Unrecognized non-transitive optional attributes must be quietly
2417 ignored and not passed along to other BGP peers. */
2418 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2419 return BGP_ATTR_PARSE_PROCEED
;
2421 /* If a path with recognized transitive optional attribute is
2422 accepted and passed along to other BGP peers and the Partial bit
2423 in the Attribute Flags octet is set to 1 by some previous AS, it
2424 is not set back to 0 by the current AS. */
2425 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2427 /* Store transitive attribute to the end of attr->transit. */
2428 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2429 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2431 transit
= attre
->transit
;
2434 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2435 transit
->length
+ total
);
2437 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2439 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2440 transit
->length
+= total
;
2442 return BGP_ATTR_PARSE_PROCEED
;
2445 /* Well-known attribute check. */
2447 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2451 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2453 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2454 return BGP_ATTR_PARSE_PROCEED
;
2456 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2457 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2458 are present, it should. Check for any other attribute being present
2461 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2462 return BGP_ATTR_PARSE_PROCEED
;
2464 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2465 type
= BGP_ATTR_ORIGIN
;
2467 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2468 type
= BGP_ATTR_AS_PATH
;
2470 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2471 * NLRI is empty. We can't easily check NLRI empty here though.
2473 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2474 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2475 type
= BGP_ATTR_NEXT_HOP
;
2477 if (peer
->sort
== BGP_PEER_IBGP
2478 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2479 type
= BGP_ATTR_LOCAL_PREF
;
2483 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2484 LOOKUP (attr_str
, type
));
2485 bgp_notify_send_with_data (peer
,
2486 BGP_NOTIFY_UPDATE_ERR
,
2487 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2489 return BGP_ATTR_PARSE_ERROR
;
2491 return BGP_ATTR_PARSE_PROCEED
;
2494 /* Read attribute of update packet. This function is called from
2495 bgp_update_receive() in bgp_packet.c. */
2496 bgp_attr_parse_ret_t
2497 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2498 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2504 u_char
*startp
, *endp
;
2506 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2507 /* we need the as4_path only until we have synthesized the as_path with it */
2508 /* same goes for as4_aggregator */
2509 struct aspath
*as4_path
= NULL
;
2510 as_t as4_aggregator
= 0;
2511 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2513 /* Initialize bitmap. */
2514 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2516 /* End pointer of BGP attribute. */
2517 endp
= BGP_INPUT_PNT (peer
) + size
;
2519 /* Get attributes to the end of attribute length. */
2520 while (BGP_INPUT_PNT (peer
) < endp
)
2522 /* Check remaining length check.*/
2523 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2525 /* XXX warning: long int format, int arg (arg 5) */
2526 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2528 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2530 bgp_notify_send (peer
,
2531 BGP_NOTIFY_UPDATE_ERR
,
2532 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2533 return BGP_ATTR_PARSE_ERROR
;
2536 /* Fetch attribute flag and type. */
2537 startp
= BGP_INPUT_PNT (peer
);
2538 /* "The lower-order four bits of the Attribute Flags octet are
2539 unused. They MUST be zero when sent and MUST be ignored when
2541 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2542 type
= stream_getc (BGP_INPUT (peer
));
2544 /* Check whether Extended-Length applies and is in bounds */
2545 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2546 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2548 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2550 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2552 bgp_notify_send (peer
,
2553 BGP_NOTIFY_UPDATE_ERR
,
2554 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2555 return BGP_ATTR_PARSE_ERROR
;
2558 /* Check extended attribue length bit. */
2559 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2560 length
= stream_getw (BGP_INPUT (peer
));
2562 length
= stream_getc (BGP_INPUT (peer
));
2564 /* If any attribute appears more than once in the UPDATE
2565 message, then the Error Subcode is set to Malformed Attribute
2568 if (CHECK_BITMAP (seen
, type
))
2570 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2573 bgp_notify_send (peer
,
2574 BGP_NOTIFY_UPDATE_ERR
,
2575 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2576 return BGP_ATTR_PARSE_ERROR
;
2579 /* Set type to bitmap to check duplicate attribute. `type' is
2580 unsigned char so it never overflow bitmap range. */
2582 SET_BITMAP (seen
, type
);
2584 /* Overflow check. */
2585 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2587 if (attr_endp
> endp
)
2589 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
);
2590 bgp_notify_send_with_data (peer
,
2591 BGP_NOTIFY_UPDATE_ERR
,
2592 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2593 startp
, attr_endp
- startp
);
2594 return BGP_ATTR_PARSE_ERROR
;
2597 struct bgp_attr_parser_args attr_args
= {
2604 .total
= attr_endp
- startp
,
2608 /* If any recognized attribute has Attribute Flags that conflict
2609 with the Attribute Type Code, then the Error Subcode is set to
2610 Attribute Flags Error. The Data field contains the erroneous
2611 attribute (type, length and value). */
2612 if (bgp_attr_flag_invalid (&attr_args
))
2614 bgp_attr_parse_ret_t ret
;
2615 ret
= bgp_attr_malformed (&attr_args
,
2616 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2618 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2623 /* OK check attribute and store it's value. */
2626 case BGP_ATTR_ORIGIN
:
2627 ret
= bgp_attr_origin (&attr_args
);
2629 case BGP_ATTR_AS_PATH
:
2630 ret
= bgp_attr_aspath (&attr_args
);
2632 case BGP_ATTR_AS4_PATH
:
2633 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2635 case BGP_ATTR_NEXT_HOP
:
2636 ret
= bgp_attr_nexthop (&attr_args
);
2638 case BGP_ATTR_MULTI_EXIT_DISC
:
2639 ret
= bgp_attr_med (&attr_args
);
2641 case BGP_ATTR_LOCAL_PREF
:
2642 ret
= bgp_attr_local_pref (&attr_args
);
2644 case BGP_ATTR_ATOMIC_AGGREGATE
:
2645 ret
= bgp_attr_atomic (&attr_args
);
2647 case BGP_ATTR_AGGREGATOR
:
2648 ret
= bgp_attr_aggregator (&attr_args
);
2650 case BGP_ATTR_AS4_AGGREGATOR
:
2651 ret
= bgp_attr_as4_aggregator (&attr_args
,
2653 &as4_aggregator_addr
);
2655 case BGP_ATTR_COMMUNITIES
:
2656 ret
= bgp_attr_community (&attr_args
);
2658 case BGP_ATTR_LARGE_COMMUNITIES
:
2659 ret
= bgp_attr_large_community (&attr_args
);
2661 case BGP_ATTR_ORIGINATOR_ID
:
2662 ret
= bgp_attr_originator_id (&attr_args
);
2664 case BGP_ATTR_CLUSTER_LIST
:
2665 ret
= bgp_attr_cluster_list (&attr_args
);
2667 case BGP_ATTR_MP_REACH_NLRI
:
2668 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2670 case BGP_ATTR_MP_UNREACH_NLRI
:
2671 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2673 case BGP_ATTR_EXT_COMMUNITIES
:
2674 ret
= bgp_attr_ext_communities (&attr_args
);
2679 case BGP_ATTR_ENCAP
:
2680 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2682 case BGP_ATTR_PREFIX_SID
:
2683 ret
= bgp_attr_prefix_sid (&attr_args
, mp_update
);
2686 ret
= bgp_attr_unknown (&attr_args
);
2690 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2692 bgp_notify_send (peer
,
2693 BGP_NOTIFY_UPDATE_ERR
,
2694 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2695 ret
= BGP_ATTR_PARSE_ERROR
;
2698 /* If hard error occured immediately return to the caller. */
2699 if (ret
== BGP_ATTR_PARSE_ERROR
)
2701 zlog_warn ("%s: Attribute %s, parse error",
2703 LOOKUP (attr_str
, type
));
2705 aspath_unintern (&as4_path
);
2708 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2711 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2713 LOOKUP (attr_str
, type
));
2715 aspath_unintern (&as4_path
);
2719 /* Check the fetched length. */
2720 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2722 zlog_warn ("%s: BGP attribute %s, fetch error",
2723 peer
->host
, LOOKUP (attr_str
, type
));
2724 bgp_notify_send (peer
,
2725 BGP_NOTIFY_UPDATE_ERR
,
2726 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2728 aspath_unintern (&as4_path
);
2729 return BGP_ATTR_PARSE_ERROR
;
2733 /* Check final read pointer is same as end pointer. */
2734 if (BGP_INPUT_PNT (peer
) != endp
)
2736 zlog_warn ("%s: BGP attribute %s, length mismatch",
2737 peer
->host
, LOOKUP (attr_str
, type
));
2738 bgp_notify_send (peer
,
2739 BGP_NOTIFY_UPDATE_ERR
,
2740 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2742 aspath_unintern (&as4_path
);
2743 return BGP_ATTR_PARSE_ERROR
;
2746 /* Check all mandatory well-known attributes are present */
2748 bgp_attr_parse_ret_t ret
;
2749 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2752 aspath_unintern (&as4_path
);
2758 * At this place we can see whether we got AS4_PATH and/or
2759 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2760 * We can not do this before we've read all attributes because
2761 * the as4 handling does not say whether AS4_PATH has to be sent
2762 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2763 * in relationship to AGGREGATOR.
2764 * So, to be defensive, we are not relying on any order and read
2765 * all attributes first, including these 32bit ones, and now,
2766 * afterwards, we look what and if something is to be done for as4.
2768 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2771 /* actually... this doesn't ever return failure currently, but
2772 * better safe than sorry */
2773 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2774 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2775 as4_aggregator
, &as4_aggregator_addr
))
2777 bgp_notify_send (peer
,
2778 BGP_NOTIFY_UPDATE_ERR
,
2779 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2781 aspath_unintern (&as4_path
);
2782 return BGP_ATTR_PARSE_ERROR
;
2785 /* At this stage, we have done all fiddling with as4, and the
2786 * resulting info is in attr->aggregator resp. attr->aspath
2787 * so we can chuck as4_aggregator and as4_path alltogether in
2788 * order to save memory
2792 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2793 /* The flag that we got this is still there, but that does not
2798 * The "rest" of the code does nothing with as4_aggregator.
2799 * there is no memory attached specifically which is not part
2801 * so ignoring just means do nothing.
2804 * Finally do the checks on the aspath we did not do yet
2805 * because we waited for a potentially synthesized aspath.
2807 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2809 ret
= bgp_attr_aspath_check (peer
, attr
);
2810 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2815 /* Finally intern unknown attribute. */
2816 if (attr
->extra
->transit
)
2817 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2818 if (attr
->extra
->encap_subtlvs
)
2819 attr
->extra
->encap_subtlvs
= encap_intern (attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2821 if (attr
->extra
->vnc_subtlvs
)
2822 attr
->extra
->vnc_subtlvs
= encap_intern (attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2826 return BGP_ATTR_PARSE_PROCEED
;
2830 bgp_packet_mpattr_start (struct stream
*s
, afi_t afi
, safi_t safi
, afi_t nh_afi
,
2831 struct bpacket_attr_vec_arr
*vecarr
,
2838 /* Set extended bit always to encode the attribute length as 2 bytes */
2839 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2840 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2841 sizep
= stream_get_endp (s
);
2842 stream_putw (s
, 0); /* Marker: Attribute length. */
2845 /* Convert AFI, SAFI to values for packet. */
2846 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
2848 stream_putw (s
, pkt_afi
); /* AFI */
2849 stream_putc (s
, pkt_safi
); /* SAFI */
2850 if (afi
== AFI_L2VPN
)
2852 else if (nh_afi
== AFI_MAX
)
2853 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->extra
->mp_nexthop_len
);
2862 case SAFI_MULTICAST
:
2863 case SAFI_LABELED_UNICAST
:
2864 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2866 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2869 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2870 stream_putc (s
, 12);
2871 stream_putl (s
, 0); /* RD = 0, per RFC */
2873 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2877 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2887 case SAFI_MULTICAST
:
2888 case SAFI_LABELED_UNICAST
:
2890 struct attr_extra
*attre
= attr
->extra
;
2892 assert (attr
->extra
);
2893 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2894 stream_putc (s
, attre
->mp_nexthop_len
);
2895 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2896 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2897 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2902 struct attr_extra
*attre
= attr
->extra
;
2904 assert (attr
->extra
);
2905 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2906 stream_putc (s
, 24);
2907 stream_putl (s
, 0); /* RD = 0, per RFC */
2909 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2910 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2911 stream_putc (s
, 48);
2912 stream_putl (s
, 0); /* RD = 0, per RFC */
2914 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2915 stream_putl (s
, 0); /* RD = 0, per RFC */
2917 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2922 assert (attr
->extra
);
2923 stream_putc (s
, IPV6_MAX_BYTELEN
);
2924 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2934 if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
)
2936 stream_putc (s
, 12);
2937 stream_putl (s
, 0); /* RD = 0, per RFC */
2939 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2941 else if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
)
2943 stream_putc (s
, 24);
2944 stream_putl (s
, 0); /* RD = 0, per RFC */
2946 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2948 else if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2950 stream_putc (s
, 48);
2951 stream_putl (s
, 0); /* RD = 0, per RFC */
2953 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2954 stream_putl (s
, 0); /* RD = 0, per RFC */
2956 stream_put (s
, &attr
->extra
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2973 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2974 struct prefix
*p
, struct prefix_rd
*prd
,
2975 u_char
*tag
, int addpath_encode
,
2976 u_int32_t addpath_tx_id
, struct attr
*attr
)
2978 if (safi
== SAFI_MPLS_VPN
)
2981 stream_putl(s
, addpath_tx_id
);
2982 /* Tag, RD, Prefix write. */
2983 stream_putc (s
, p
->prefixlen
+ 88);
2984 stream_put (s
, tag
, 3);
2985 stream_put (s
, prd
->val
, 8);
2986 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2988 else if (safi
== SAFI_EVPN
)
2990 bgp_packet_mpattr_route_type_5(s
, p
, prd
, tag
, attr
);
2992 else if (safi
== SAFI_LABELED_UNICAST
)
2994 /* Prefix write with label. */
2995 stream_put_labeled_prefix(s
, p
, tag
);
2998 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
3002 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
3004 int size
= PSIZE (p
->prefixlen
);
3005 if (safi
== SAFI_MPLS_VPN
)
3011 * Encodes the tunnel encapsulation attribute,
3012 * and with ENABLE_BGP_VNC the VNC attribute which uses
3013 * almost the same TLV format
3016 bgp_packet_mpattr_tea(
3023 unsigned int attrlenfield
= 0;
3024 unsigned int attrhdrlen
= 0;
3025 struct bgp_attr_encap_subtlv
*subtlvs
;
3026 struct bgp_attr_encap_subtlv
*st
;
3027 const char *attrname
;
3029 if (!attr
|| !attr
->extra
||
3030 (attrtype
== BGP_ATTR_ENCAP
&&
3031 (!attr
->extra
->encap_tunneltype
||
3032 attr
->extra
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3036 case BGP_ATTR_ENCAP
:
3037 attrname
= "Tunnel Encap";
3038 subtlvs
= attr
->extra
->encap_subtlvs
;
3041 * The tunnel encap attr has an "outer" tlv.
3043 * L = total length of subtlvs,
3044 * V = concatenated subtlvs.
3046 attrlenfield
= 2 + 2; /* T + L */
3047 attrhdrlen
= 1 + 1; /* subTLV T + L */
3053 subtlvs
= attr
->extra
->vnc_subtlvs
;
3054 attrlenfield
= 0; /* no outer T + L */
3055 attrhdrlen
= 2 + 2; /* subTLV T + L */
3063 /* compute attr length */
3064 for (st
= subtlvs
; st
; st
= st
->next
) {
3065 attrlenfield
+= (attrhdrlen
+ st
->length
);
3068 if (attrlenfield
> 0xffff) {
3069 zlog_info ("%s attribute is too long (length=%d), can't send it",
3075 if (attrlenfield
> 0xff) {
3076 /* 2-octet length field */
3078 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3079 stream_putc (s
, attrtype
);
3080 stream_putw (s
, attrlenfield
& 0xffff);
3082 /* 1-octet length field */
3083 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
3084 stream_putc (s
, attrtype
);
3085 stream_putc (s
, attrlenfield
& 0xff);
3088 if (attrtype
== BGP_ATTR_ENCAP
) {
3089 /* write outer T+L */
3090 stream_putw(s
, attr
->extra
->encap_tunneltype
);
3091 stream_putw(s
, attrlenfield
- 4);
3094 /* write each sub-tlv */
3095 for (st
= subtlvs
; st
; st
= st
->next
) {
3096 if (attrtype
== BGP_ATTR_ENCAP
) {
3097 stream_putc (s
, st
->type
);
3098 stream_putc (s
, st
->length
);
3101 stream_putw (s
, st
->type
);
3102 stream_putw (s
, st
->length
);
3105 stream_put (s
, st
->value
, st
->length
);
3110 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
3112 /* Set MP attribute length. Don't count the (2) bytes used to encode
3114 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
3117 /* Make attribute packet. */
3119 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
3120 struct stream
*s
, struct attr
*attr
,
3121 struct bpacket_attr_vec_arr
*vecarr
,
3122 struct prefix
*p
, afi_t afi
, safi_t safi
,
3123 struct peer
*from
, struct prefix_rd
*prd
, u_char
*tag
,
3125 u_int32_t addpath_tx_id
)
3128 size_t aspath_sizep
;
3129 struct aspath
*aspath
;
3130 int send_as4_path
= 0;
3131 int send_as4_aggregator
= 0;
3132 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3137 /* Remember current pointer. */
3138 cp
= stream_get_endp (s
);
3140 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
3141 !peer_cap_enhe(peer
)))
3143 size_t mpattrlen_pos
= 0;
3145 mpattrlen_pos
= bgp_packet_mpattr_start(s
, afi
, safi
,
3146 (peer_cap_enhe(peer
) ? AFI_IP6
:
3147 AFI_MAX
), /* get from NH */
3149 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
3150 addpath_encode
, addpath_tx_id
, attr
);
3151 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3154 /* Origin attribute. */
3155 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3156 stream_putc (s
, BGP_ATTR_ORIGIN
);
3158 stream_putc (s
, attr
->origin
);
3160 /* AS path attribute. */
3162 /* If remote-peer is EBGP */
3163 if (peer
->sort
== BGP_PEER_EBGP
3164 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
3165 || attr
->aspath
->segments
== NULL
)
3166 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
3168 aspath
= aspath_dup (attr
->aspath
);
3170 /* Even though we may not be configured for confederations we may have
3171 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3172 aspath
= aspath_delete_confed_seq (aspath
);
3174 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
3176 /* Stuff our path CONFED_ID on the front */
3177 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
3181 if (peer
->change_local_as
) {
3182 /* If replace-as is specified, we only use the change_local_as when
3183 advertising routes. */
3184 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
3185 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3187 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
3189 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3193 else if (peer
->sort
== BGP_PEER_CONFED
)
3195 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
3196 aspath
= aspath_dup (attr
->aspath
);
3197 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
3200 aspath
= attr
->aspath
;
3202 /* If peer is not AS4 capable, then:
3203 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3204 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
3205 * types are in it (i.e. exclude them if they are there)
3206 * AND do this only if there is at least one asnum > 65535 in the path!
3207 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
3208 * all ASnums > 65535 to BGP_AS_TRANS
3211 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3212 stream_putc (s
, BGP_ATTR_AS_PATH
);
3213 aspath_sizep
= stream_get_endp (s
);
3215 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
3217 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3220 if (!use32bit
&& aspath_has_as4 (aspath
))
3221 send_as4_path
= 1; /* we'll do this later, at the correct place */
3223 /* Nexthop attribute. */
3224 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
))
3226 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
3228 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3229 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3230 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3232 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3234 else if (peer_cap_enhe(from
))
3237 * Likely this is the case when an IPv4 prefix was received with
3238 * Extended Next-hop capability and now being advertised to
3240 * Setting the mandatory (ipv4) next-hop attribute here to enable
3241 * implicit next-hop self with correct (ipv4 address family).
3243 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3244 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3245 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
3247 stream_put_ipv4 (s
, 0);
3251 /* MED attribute. */
3252 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
3255 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3256 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3258 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
3261 /* Local preference. */
3262 if (peer
->sort
== BGP_PEER_IBGP
||
3263 peer
->sort
== BGP_PEER_CONFED
)
3265 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3266 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3268 stream_putl (s
, attr
->local_pref
);
3271 /* Atomic aggregate. */
3272 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3274 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3275 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3280 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3282 assert (attr
->extra
);
3284 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3285 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3286 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3290 /* AS4 capable peer */
3292 stream_putl (s
, attr
->extra
->aggregator_as
);
3296 /* 2-byte AS peer */
3299 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3300 if ( attr
->extra
->aggregator_as
> 65535 )
3302 stream_putw (s
, BGP_AS_TRANS
);
3304 /* we have to send AS4_AGGREGATOR, too.
3305 * we'll do that later in order to send attributes in ascending
3308 send_as4_aggregator
= 1;
3311 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
3313 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3316 /* Community attribute. */
3317 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3318 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
3320 if (attr
->community
->size
* 4 > 255)
3322 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3323 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3324 stream_putw (s
, attr
->community
->size
* 4);
3328 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3329 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3330 stream_putc (s
, attr
->community
->size
* 4);
3332 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3336 * Large Community attribute.
3339 CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_LARGE_COMMUNITY
)
3340 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
)))
3342 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3344 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3345 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3346 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3350 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3351 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3352 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3354 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3357 /* Route Reflector. */
3358 if (peer
->sort
== BGP_PEER_IBGP
3360 && from
->sort
== BGP_PEER_IBGP
)
3362 /* Originator ID. */
3363 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3364 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
3367 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3368 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
3370 stream_put_in_addr (s
, &from
->remote_id
);
3373 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3374 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
3376 if (attr
->extra
&& attr
->extra
->cluster
)
3378 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
3379 /* If this peer configuration's parent BGP has cluster_id. */
3380 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3381 stream_put_in_addr (s
, &bgp
->cluster_id
);
3383 stream_put_in_addr (s
, &bgp
->router_id
);
3384 stream_put (s
, attr
->extra
->cluster
->list
,
3385 attr
->extra
->cluster
->length
);
3390 /* If this peer configuration's parent BGP has cluster_id. */
3391 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3392 stream_put_in_addr (s
, &bgp
->cluster_id
);
3394 stream_put_in_addr (s
, &bgp
->router_id
);
3398 /* Extended Communities attribute. */
3399 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3400 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
3402 struct attr_extra
*attre
= attr
->extra
;
3406 if (peer
->sort
== BGP_PEER_IBGP
3407 || peer
->sort
== BGP_PEER_CONFED
)
3409 if (attre
->ecommunity
->size
* 8 > 255)
3411 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3412 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3413 stream_putw (s
, attre
->ecommunity
->size
* 8);
3417 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3418 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3419 stream_putc (s
, attre
->ecommunity
->size
* 8);
3421 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
3427 int ecom_tr_size
= 0;
3430 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3432 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3435 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3443 if (ecom_tr_size
* 8 > 255)
3445 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3446 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3447 stream_putw (s
, ecom_tr_size
* 8);
3451 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3452 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3453 stream_putc (s
, ecom_tr_size
* 8);
3456 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3458 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3461 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3464 stream_put (s
, pnt
, 8);
3470 /* Label index attribute. */
3471 if (safi
== SAFI_LABELED_UNICAST
)
3473 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3475 u_int32_t label_index
;
3477 assert (attr
->extra
);
3478 label_index
= attr
->extra
->label_index
;
3480 if (label_index
!= BGP_INVALID_LABEL_INDEX
)
3482 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3483 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3484 stream_putc (s
, 10);
3485 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3486 stream_putw (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3487 stream_putc (s
, 0); // reserved
3488 stream_putw (s
, 0); // flags
3489 stream_putl (s
, label_index
);
3494 if ( send_as4_path
)
3496 /* If the peer is NOT As4 capable, AND */
3497 /* there are ASnums > 65535 in path THEN
3498 * give out AS4_PATH */
3500 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3502 * Hm, I wonder... confederation things *should* only be at
3503 * the beginning of an aspath, right? Then we should use
3504 * aspath_delete_confed_seq for this, because it is already
3506 * Folks, talk to me: what is reasonable here!?
3508 aspath
= aspath_delete_confed_seq (aspath
);
3510 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3511 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3512 aspath_sizep
= stream_get_endp (s
);
3514 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3517 if (aspath
!= attr
->aspath
)
3518 aspath_free (aspath
);
3520 if ( send_as4_aggregator
)
3522 assert (attr
->extra
);
3524 /* send AS4_AGGREGATOR, at this place */
3525 /* this section of code moved here in order to ensure the correct
3526 * *ascending* order of attributes
3528 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3529 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3531 stream_putl (s
, attr
->extra
->aggregator_as
);
3532 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3535 if (((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3536 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
)) ||
3537 (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3539 /* Tunnel Encap attribute */
3540 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3544 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3548 /* Unknown transit attribute. */
3549 if (attr
->extra
&& attr
->extra
->transit
)
3550 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3552 /* Return total size of attribute. */
3553 return stream_get_endp (s
) - cp
;
3557 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3559 unsigned long attrlen_pnt
;
3563 /* Set extended bit always to encode the attribute length as 2 bytes */
3564 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3565 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3567 attrlen_pnt
= stream_get_endp (s
);
3568 stream_putw (s
, 0); /* Length of this attribute. */
3570 /* Convert AFI, SAFI to values for packet. */
3571 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
3573 stream_putw (s
, pkt_afi
);
3574 stream_putc (s
, pkt_safi
);
3580 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3581 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3582 u_char
*tag
, int addpath_encode
,
3583 u_int32_t addpath_tx_id
, struct attr
*attr
)
3585 u_char wlabel
[3] = {0x80, 0x00, 0x00};
3587 if (safi
== SAFI_LABELED_UNICAST
)
3590 return bgp_packet_mpattr_prefix (s
, afi
, safi
, p
, prd
,
3591 tag
, addpath_encode
, addpath_tx_id
, attr
);
3595 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3597 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3600 /* Initialization of attribute. */
3602 bgp_attr_init (void)
3615 bgp_attr_finish (void)
3619 community_finish ();
3620 ecommunity_finish ();
3621 lcommunity_finish ();
3627 /* Make attribute packet. */
3629 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3630 struct prefix
*prefix
)
3635 struct aspath
*aspath
;
3636 int addpath_encode
= 0;
3637 u_int32_t addpath_tx_id
= 0;
3639 /* Remember current pointer. */
3640 cp
= stream_get_endp (s
);
3642 /* Place holder of length. */
3645 /* Origin attribute. */
3646 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3647 stream_putc (s
, BGP_ATTR_ORIGIN
);
3649 stream_putc (s
, attr
->origin
);
3651 aspath
= attr
->aspath
;
3653 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3654 stream_putc (s
, BGP_ATTR_AS_PATH
);
3655 aspath_lenp
= stream_get_endp (s
);
3658 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3660 /* Nexthop attribute. */
3661 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3662 if(prefix
!= NULL
&& prefix
->family
!= AF_INET6
)
3664 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3665 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3667 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3670 /* MED attribute. */
3671 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3673 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3674 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3676 stream_putl (s
, attr
->med
);
3679 /* Local preference. */
3680 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3682 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3683 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3685 stream_putl (s
, attr
->local_pref
);
3688 /* Atomic aggregate. */
3689 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3691 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3692 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3697 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3699 assert (attr
->extra
);
3700 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3701 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3703 stream_putl (s
, attr
->extra
->aggregator_as
);
3704 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3707 /* Community attribute. */
3708 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3710 if (attr
->community
->size
* 4 > 255)
3712 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3713 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3714 stream_putw (s
, attr
->community
->size
* 4);
3718 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3719 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3720 stream_putc (s
, attr
->community
->size
* 4);
3722 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3725 /* Large Community attribute. */
3726 if (attr
->extra
&& attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
))
3728 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3730 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3731 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3732 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3736 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3737 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3738 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3741 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3744 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3745 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3746 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3747 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3750 struct attr_extra
*attre
= attr
->extra
;
3752 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3753 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3754 sizep
= stream_get_endp (s
);
3757 stream_putc (s
, 0); /* Marker: Attribute length. */
3758 stream_putw(s
, AFI_IP6
); /* AFI */
3759 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3762 stream_putc(s
, attre
->mp_nexthop_len
);
3763 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3764 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3765 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3771 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3773 /* Set MP attribute length. */
3774 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3778 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3780 assert (attr
->extra
);
3782 if (attr
->extra
->label_index
!= BGP_INVALID_LABEL_INDEX
)
3784 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3785 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3786 stream_putc (s
, 10);
3787 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3788 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3789 stream_putc (s
, 0); // reserved
3790 stream_putw (s
, 0); // flags
3791 stream_putl (s
, attr
->extra
->label_index
);
3795 /* Return total size of attribute. */
3796 len
= stream_get_endp (s
) - cp
- 2;
3797 stream_putw_at (s
, cp
, len
);