1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_label.h"
43 #include "bgpd/bgp_packet.h"
44 #include "bgpd/bgp_ecommunity.h"
45 #include "bgpd/bgp_lcommunity.h"
46 #include "bgpd/bgp_updgrp.h"
47 #include "bgpd/bgp_encap_types.h"
49 # include "bgpd/rfapi/bgp_rfapi_cfg.h"
50 # include "bgp_encap_types.h"
51 # include "bgp_vnc_types.h"
53 #include "bgp_encap_types.h"
56 /* Attribute strings for logging. */
57 static const struct message attr_str
[] =
59 { BGP_ATTR_ORIGIN
, "ORIGIN" },
60 { BGP_ATTR_AS_PATH
, "AS_PATH" },
61 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
62 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
63 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
64 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
65 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
66 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
67 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
68 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
69 { BGP_ATTR_DPA
, "DPA" },
70 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
71 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
72 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
73 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
74 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
75 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
76 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
77 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
78 { BGP_ATTR_ENCAP
, "ENCAP" },
80 { BGP_ATTR_VNC
, "VNC" },
82 { BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY" },
83 { BGP_ATTR_PREFIX_SID
, "PREFIX_SID" },
87 static const struct message attr_flag_str
[] =
89 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
90 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
91 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
92 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
93 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
97 static struct hash
*cluster_hash
;
100 cluster_hash_alloc (void *p
)
102 const struct cluster_list
*val
= (const struct cluster_list
*) p
;
103 struct cluster_list
*cluster
;
105 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
106 cluster
->length
= val
->length
;
110 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
111 memcpy (cluster
->list
, val
->list
, val
->length
);
114 cluster
->list
= NULL
;
121 /* Cluster list related functions. */
122 static struct cluster_list
*
123 cluster_parse (struct in_addr
* pnt
, int length
)
125 struct cluster_list tmp
;
126 struct cluster_list
*cluster
;
131 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
137 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
141 for (i
= 0; i
< cluster
->length
/ 4; i
++)
142 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
148 cluster_hash_key_make (void *p
)
150 const struct cluster_list
*cluster
= p
;
152 return jhash(cluster
->list
, cluster
->length
, 0);
156 cluster_hash_cmp (const void *p1
, const void *p2
)
158 const struct cluster_list
* cluster1
= p1
;
159 const struct cluster_list
* cluster2
= p2
;
161 return (cluster1
->length
== cluster2
->length
&&
162 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
166 cluster_free (struct cluster_list
*cluster
)
169 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
170 XFREE (MTYPE_CLUSTER
, cluster
);
173 static struct cluster_list
*
174 cluster_dup (struct cluster_list
*cluster
)
176 struct cluster_list
*new;
178 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
179 new->length
= cluster
->length
;
183 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
184 memcpy (new->list
, cluster
->list
, cluster
->length
);
192 static struct cluster_list
*
193 cluster_intern (struct cluster_list
*cluster
)
195 struct cluster_list
*find
;
197 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
204 cluster_unintern (struct cluster_list
*cluster
)
209 if (cluster
->refcnt
== 0)
211 hash_release (cluster_hash
, cluster
);
212 cluster_free (cluster
);
219 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
, NULL
);
223 cluster_finish (void)
225 hash_clean (cluster_hash
, (void (*)(void *))cluster_free
);
226 hash_free (cluster_hash
);
230 static struct hash
*encap_hash
= NULL
;
232 static struct hash
*vnc_hash
= NULL
;
235 struct bgp_attr_encap_subtlv
*
236 encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
238 struct bgp_attr_encap_subtlv
*new;
239 struct bgp_attr_encap_subtlv
*tail
;
240 struct bgp_attr_encap_subtlv
*p
;
242 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
243 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
245 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
248 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
251 memcpy(tail
, p
, size
);
259 encap_free(struct bgp_attr_encap_subtlv
*p
)
261 struct bgp_attr_encap_subtlv
*next
;
265 XFREE(MTYPE_ENCAP_TLV
, p
);
271 bgp_attr_flush_encap(struct attr
*attr
)
273 if (!attr
|| !attr
->extra
)
276 if (attr
->extra
->encap_subtlvs
) {
277 encap_free(attr
->extra
->encap_subtlvs
);
278 attr
->extra
->encap_subtlvs
= NULL
;
281 if (attr
->extra
->vnc_subtlvs
) {
282 encap_free(attr
->extra
->vnc_subtlvs
);
283 attr
->extra
->vnc_subtlvs
= NULL
;
289 * Compare encap sub-tlv chains
294 * This algorithm could be made faster if needed
297 encap_same(struct bgp_attr_encap_subtlv
*h1
, struct bgp_attr_encap_subtlv
*h2
)
299 struct bgp_attr_encap_subtlv
*p
;
300 struct bgp_attr_encap_subtlv
*q
;
304 if (h1
== NULL
|| h2
== NULL
)
307 for (p
= h1
; p
; p
= p
->next
) {
308 for (q
= h2
; q
; q
= q
->next
) {
309 if ((p
->type
== q
->type
) &&
310 (p
->length
== q
->length
) &&
311 !memcmp(p
->value
, q
->value
, p
->length
)) {
320 for (p
= h2
; p
; p
= p
->next
) {
321 for (q
= h1
; q
; q
= q
->next
) {
322 if ((p
->type
== q
->type
) &&
323 (p
->length
== q
->length
) &&
324 !memcmp(p
->value
, q
->value
, p
->length
)) {
337 encap_hash_alloc (void *p
)
339 /* Encap structure is already allocated. */
351 static struct bgp_attr_encap_subtlv
*
352 encap_intern (struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
354 struct bgp_attr_encap_subtlv
*find
;
355 struct hash
*hash
= encap_hash
;
357 if (type
== VNC_SUBTLV_TYPE
)
361 find
= hash_get (hash
, encap
, encap_hash_alloc
);
370 encap_unintern (struct bgp_attr_encap_subtlv
**encapp
, encap_subtlv_type type
)
372 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
376 if (encap
->refcnt
== 0)
378 struct hash
*hash
= encap_hash
;
380 if (type
== VNC_SUBTLV_TYPE
)
383 hash_release (hash
, encap
);
390 encap_hash_key_make (void *p
)
392 const struct bgp_attr_encap_subtlv
* encap
= p
;
394 return jhash(encap
->value
, encap
->length
, 0);
398 encap_hash_cmp (const void *p1
, const void *p2
)
400 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
401 (struct bgp_attr_encap_subtlv
*)p2
);
407 encap_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
, NULL
);
409 vnc_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
, NULL
);
416 hash_clean (encap_hash
, (void (*)(void *))encap_free
);
417 hash_free (encap_hash
);
420 hash_clean (vnc_hash
, (void (*)(void *))encap_free
);
421 hash_free (vnc_hash
);
427 overlay_index_same(const struct attr_extra
*ae1
, const struct attr_extra
*ae2
)
435 return !memcmp(&(ae1
->evpn_overlay
), &(ae2
->evpn_overlay
), sizeof(struct overlay_index
));
438 /* Unknown transit attribute. */
439 static struct hash
*transit_hash
;
442 transit_free (struct transit
*transit
)
445 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
446 XFREE (MTYPE_TRANSIT
, transit
);
449 static struct transit
*
450 transit_dup (struct transit
*transit
)
454 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
455 new->length
= transit
->length
;
458 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
459 memcpy (new->val
, transit
->val
, transit
->length
);
468 transit_hash_alloc (void *p
)
470 /* Transit structure is already allocated. */
474 static struct transit
*
475 transit_intern (struct transit
*transit
)
477 struct transit
*find
;
479 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
481 transit_free (transit
);
488 transit_unintern (struct transit
*transit
)
493 if (transit
->refcnt
== 0)
495 hash_release (transit_hash
, transit
);
496 transit_free (transit
);
501 transit_hash_key_make (void *p
)
503 const struct transit
* transit
= p
;
505 return jhash(transit
->val
, transit
->length
, 0);
509 transit_hash_cmp (const void *p1
, const void *p2
)
511 const struct transit
* transit1
= p1
;
512 const struct transit
* transit2
= p2
;
514 return (transit1
->length
== transit2
->length
&&
515 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
521 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
, NULL
);
525 transit_finish (void)
527 hash_clean (transit_hash
, (void (*)(void *))transit_free
);
528 hash_free (transit_hash
);
532 /* Attribute hash routines. */
533 static struct hash
*attrhash
;
535 static struct attr_extra
*
536 bgp_attr_extra_new (void)
538 struct attr_extra
*extra
;
539 extra
= XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
540 extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
541 extra
->label
= MPLS_INVALID_LABEL
;
546 bgp_attr_extra_free (struct attr
*attr
)
550 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
556 bgp_attr_extra_get (struct attr
*attr
)
559 attr
->extra
= bgp_attr_extra_new();
563 /* Shallow copy of an attribute
564 * Though, not so shallow that it doesn't copy the contents
565 * of the attr_extra pointed to by 'extra'
568 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
570 struct attr_extra
*extra
= new->extra
;
573 /* if caller provided attr_extra space, use it in any case.
575 * This is neccesary even if orig->extra equals NULL, because otherwise
576 * memory may be later allocated on the heap by bgp_attr_extra_get.
578 * That memory would eventually be leaked, because the caller must not
579 * call bgp_attr_extra_free if he provided attr_extra on the stack.
584 memset(new->extra
, 0, sizeof(struct attr_extra
));
585 new->extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
586 new->extra
->label
= MPLS_INVALID_LABEL
;
589 *new->extra
= *orig
->extra
;
592 else if (orig
->extra
)
594 new->extra
= bgp_attr_extra_new();
595 *new->extra
= *orig
->extra
;
600 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
603 new->aspath
= aspath_dup(orig
->aspath
);
606 new->community
= community_dup(orig
->community
);
610 if (orig
->extra
->ecommunity
)
611 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
612 if (orig
->extra
->cluster
)
613 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
614 if (orig
->extra
->transit
)
615 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
616 if (orig
->extra
->encap_subtlvs
)
617 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
619 if (orig
->extra
->vnc_subtlvs
)
620 new->extra
->vnc_subtlvs
= encap_tlv_dup(orig
->extra
->vnc_subtlvs
);
626 bgp_attr_deep_free (struct attr
*attr
)
629 aspath_free(attr
->aspath
);
632 community_free(attr
->community
);
636 if (attr
->extra
->ecommunity
)
637 ecommunity_free(&attr
->extra
->ecommunity
);
638 if (attr
->extra
->cluster
)
639 cluster_free(attr
->extra
->cluster
);
640 if (attr
->extra
->transit
)
641 transit_free(attr
->extra
->transit
);
642 if (attr
->extra
->encap_subtlvs
)
643 encap_free(attr
->extra
->encap_subtlvs
);
645 if (attr
->extra
->vnc_subtlvs
)
646 encap_free(attr
->extra
->vnc_subtlvs
);
654 return attrhash
->count
;
658 attr_unknown_count (void)
660 return transit_hash
->count
;
664 attrhash_key_make (void *p
)
666 const struct attr
*attr
= (struct attr
*) p
;
667 const struct attr_extra
*extra
= attr
->extra
;
669 #define MIX(val) key = jhash_1word(val, key)
672 MIX(attr
->nexthop
.s_addr
);
674 MIX(attr
->local_pref
);
677 key
+= attr
->nexthop
.s_addr
;
679 key
+= attr
->local_pref
;
683 MIX(extra
->aggregator_as
);
684 MIX(extra
->aggregator_addr
.s_addr
);
686 MIX(extra
->mp_nexthop_global_in
.s_addr
);
687 MIX(extra
->originator_id
.s_addr
);
690 MIX(extra
->label_index
);
694 MIX(aspath_key_make (attr
->aspath
));
696 MIX(community_hash_make (attr
->community
));
700 if (extra
->lcommunity
)
701 MIX(lcommunity_hash_make (extra
->lcommunity
));
702 if (extra
->ecommunity
)
703 MIX(ecommunity_hash_make (extra
->ecommunity
));
705 MIX(cluster_hash_key_make (extra
->cluster
));
707 MIX(transit_hash_key_make (extra
->transit
));
708 if (extra
->encap_subtlvs
)
709 MIX(encap_hash_key_make (extra
->encap_subtlvs
));
711 if (extra
->vnc_subtlvs
)
712 MIX(encap_hash_key_make (extra
->vnc_subtlvs
));
714 MIX(extra
->mp_nexthop_len
);
715 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
716 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
723 attrhash_cmp (const void *p1
, const void *p2
)
725 const struct attr
* attr1
= p1
;
726 const struct attr
* attr2
= p2
;
728 if (attr1
->flag
== attr2
->flag
729 && attr1
->origin
== attr2
->origin
730 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
731 && attr1
->aspath
== attr2
->aspath
732 && attr1
->community
== attr2
->community
733 && attr1
->med
== attr2
->med
734 && attr1
->local_pref
== attr2
->local_pref
735 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
737 const struct attr_extra
*ae1
= attr1
->extra
;
738 const struct attr_extra
*ae2
= attr2
->extra
;
741 && ae1
->aggregator_as
== ae2
->aggregator_as
742 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
743 && ae1
->weight
== ae2
->weight
744 && ae1
->tag
== ae2
->tag
745 && ae1
->label_index
== ae2
->label_index
746 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
747 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
748 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
749 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
750 && ae1
->ecommunity
== ae2
->ecommunity
751 && ae1
->lcommunity
== ae2
->lcommunity
752 && ae1
->cluster
== ae2
->cluster
753 && ae1
->transit
== ae2
->transit
754 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
755 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
757 && encap_same(ae1
->vnc_subtlvs
, ae2
->vnc_subtlvs
)
759 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
)
760 && overlay_index_same(ae1
, ae2
))
764 /* neither attribute has extra attributes, so they're same */
774 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
778 * special for hash_clean below
781 attr_vfree (void *attr
)
783 bgp_attr_extra_free ((struct attr
*)attr
);
784 XFREE (MTYPE_ATTR
, attr
);
788 attrhash_finish (void)
790 hash_clean(attrhash
, attr_vfree
);
791 hash_free (attrhash
);
796 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
798 struct attr
*attr
= backet
->data
;
800 vty_outln (vty
, "attr[%ld] nexthop %s", attr
->refcnt
,
801 inet_ntoa(attr
->nexthop
));
805 attr_show_all (struct vty
*vty
)
807 hash_iterate (attrhash
,
808 (void (*)(struct hash_backet
*, void *))
809 attr_show_all_iterator
,
814 bgp_attr_hash_alloc (void *p
)
816 const struct attr
* val
= (const struct attr
*) p
;
819 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
823 attr
->extra
= bgp_attr_extra_new ();
824 *attr
->extra
= *val
->extra
;
825 if (val
->extra
->encap_subtlvs
) {
826 val
->extra
->encap_subtlvs
= NULL
;
829 if (val
->extra
->vnc_subtlvs
) {
830 val
->extra
->vnc_subtlvs
= NULL
;
838 /* Internet argument attribute. */
840 bgp_attr_intern (struct attr
*attr
)
844 /* Intern referenced strucutre. */
847 if (! attr
->aspath
->refcnt
)
848 attr
->aspath
= aspath_intern (attr
->aspath
);
850 attr
->aspath
->refcnt
++;
854 if (! attr
->community
->refcnt
)
855 attr
->community
= community_intern (attr
->community
);
857 attr
->community
->refcnt
++;
861 struct attr_extra
*attre
= attr
->extra
;
863 if (attre
->ecommunity
)
865 if (! attre
->ecommunity
->refcnt
)
866 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
868 attre
->ecommunity
->refcnt
++;
871 if (attre
->lcommunity
)
873 if (! attre
->lcommunity
->refcnt
)
874 attre
->lcommunity
= lcommunity_intern (attre
->lcommunity
);
876 attre
->lcommunity
->refcnt
++;
880 if (! attre
->cluster
->refcnt
)
881 attre
->cluster
= cluster_intern (attre
->cluster
);
883 attre
->cluster
->refcnt
++;
887 if (! attre
->transit
->refcnt
)
888 attre
->transit
= transit_intern (attre
->transit
);
890 attre
->transit
->refcnt
++;
892 if (attre
->encap_subtlvs
)
894 if (! attre
->encap_subtlvs
->refcnt
)
895 attre
->encap_subtlvs
= encap_intern (attre
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
897 attre
->encap_subtlvs
->refcnt
++;
900 if (attre
->vnc_subtlvs
)
902 if (! attre
->vnc_subtlvs
->refcnt
)
903 attre
->vnc_subtlvs
= encap_intern (attre
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
905 attre
->vnc_subtlvs
->refcnt
++;
910 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
917 * Increment the refcount on various structures that attr holds.
918 * Note on usage: call _only_ when the 'attr' object has already
919 * been 'intern'ed and exists in 'attrhash' table. The function
920 * serves to hold a reference to that (real) object.
921 * Note also that the caller can safely call bgp_attr_unintern()
922 * after calling bgp_attr_refcount(). That would release the
923 * reference and could result in a free() of the attr object.
926 bgp_attr_refcount (struct attr
*attr
)
928 /* Intern referenced strucutre. */
930 attr
->aspath
->refcnt
++;
933 attr
->community
->refcnt
++;
937 struct attr_extra
*attre
= attr
->extra
;
938 if (attre
->ecommunity
)
939 attre
->ecommunity
->refcnt
++;
942 attre
->cluster
->refcnt
++;
945 attre
->transit
->refcnt
++;
947 if (attre
->encap_subtlvs
)
948 attre
->encap_subtlvs
->refcnt
++;
951 if (attre
->vnc_subtlvs
)
952 attre
->vnc_subtlvs
->refcnt
++;
959 /* Make network statement's attribute. */
961 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
963 memset (attr
, 0, sizeof (struct attr
));
964 bgp_attr_extra_get (attr
);
966 attr
->origin
= origin
;
967 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
968 attr
->aspath
= aspath_empty ();
969 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
970 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
971 attr
->extra
->tag
= 0;
972 attr
->extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
973 attr
->extra
->label
= MPLS_INVALID_LABEL
;
974 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
975 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
980 /* Create the attributes for an aggregate */
982 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
983 struct aspath
*aspath
,
984 struct community
*community
, int as_set
,
985 u_char atomic_aggregate
)
989 struct attr_extra attre
;
991 memset (&attr
, 0, sizeof (struct attr
));
992 memset (&attre
, 0, sizeof (struct attr_extra
));
995 /* Origin attribute. */
996 attr
.origin
= origin
;
997 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
999 /* AS path attribute. */
1001 attr
.aspath
= aspath_intern (aspath
);
1003 attr
.aspath
= aspath_empty ();
1004 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1006 /* Next hop attribute. */
1007 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1011 attr
.community
= community
;
1012 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1015 attre
.label_index
= BGP_INVALID_LABEL_INDEX
;
1016 attre
.label
= MPLS_INVALID_LABEL
;
1017 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1018 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1019 if (! as_set
|| atomic_aggregate
)
1020 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1021 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1022 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1023 attre
.aggregator_as
= bgp
->confed_id
;
1025 attre
.aggregator_as
= bgp
->as
;
1026 attre
.aggregator_addr
= bgp
->router_id
;
1028 new = bgp_attr_intern (&attr
);
1030 aspath_unintern (&new->aspath
);
1034 /* Unintern just the sub-components of the attr, but not the attr */
1036 bgp_attr_unintern_sub (struct attr
*attr
)
1038 /* aspath refcount shoud be decrement. */
1040 aspath_unintern (&attr
->aspath
);
1041 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
1043 if (attr
->community
)
1044 community_unintern (&attr
->community
);
1045 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
1049 if (attr
->extra
->ecommunity
)
1050 ecommunity_unintern (&attr
->extra
->ecommunity
);
1051 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
1053 if (attr
->extra
->lcommunity
)
1054 lcommunity_unintern (&attr
->extra
->lcommunity
);
1055 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
));
1057 if (attr
->extra
->cluster
)
1058 cluster_unintern (attr
->extra
->cluster
);
1059 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
1061 if (attr
->extra
->transit
)
1062 transit_unintern (attr
->extra
->transit
);
1064 if (attr
->extra
->encap_subtlvs
)
1065 encap_unintern (&attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1068 if (attr
->extra
->vnc_subtlvs
)
1069 encap_unintern (&attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1074 /* Free bgp attribute and aspath. */
1076 bgp_attr_unintern (struct attr
**pattr
)
1078 struct attr
*attr
= *pattr
;
1081 struct attr_extra tmp_extra
;
1083 /* Decrement attribute reference. */
1090 tmp
.extra
= &tmp_extra
;
1091 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
1094 /* If reference becomes zero then free attribute object. */
1095 if (attr
->refcnt
== 0)
1097 ret
= hash_release (attrhash
, attr
);
1098 assert (ret
!= NULL
);
1099 bgp_attr_extra_free (attr
);
1100 XFREE (MTYPE_ATTR
, attr
);
1104 bgp_attr_unintern_sub (&tmp
);
1108 bgp_attr_flush (struct attr
*attr
)
1110 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
1112 aspath_free (attr
->aspath
);
1113 attr
->aspath
= NULL
;
1115 if (attr
->community
&& ! attr
->community
->refcnt
)
1117 community_free (attr
->community
);
1118 attr
->community
= NULL
;
1122 struct attr_extra
*attre
= attr
->extra
;
1124 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
1125 ecommunity_free (&attre
->ecommunity
);
1126 if (attre
->lcommunity
&& ! attre
->lcommunity
->refcnt
)
1127 lcommunity_free (&attre
->lcommunity
);
1128 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
1130 cluster_free (attre
->cluster
);
1131 attre
->cluster
= NULL
;
1133 if (attre
->transit
&& ! attre
->transit
->refcnt
)
1135 transit_free (attre
->transit
);
1136 attre
->transit
= NULL
;
1138 if (attre
->encap_subtlvs
&& ! attre
->encap_subtlvs
->refcnt
)
1140 encap_free(attre
->encap_subtlvs
);
1141 attre
->encap_subtlvs
= NULL
;
1144 if (attre
->vnc_subtlvs
&& ! attre
->vnc_subtlvs
->refcnt
)
1146 encap_free(attre
->vnc_subtlvs
);
1147 attre
->vnc_subtlvs
= NULL
;
1153 /* Implement draft-scudder-idr-optional-transitive behaviour and
1154 * avoid resetting sessions for malformed attributes which are
1155 * are partial/optional and hence where the error likely was not
1156 * introduced by the sending neighbour.
1158 static bgp_attr_parse_ret_t
1159 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
1162 struct peer
*const peer
= args
->peer
;
1163 const u_int8_t flags
= args
->flags
;
1164 /* startp and length must be special-cased, as whether or not to
1165 * send the attribute data with the NOTIFY depends on the error,
1166 * the caller therefore signals this with the seperate length argument
1168 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1170 /* Only relax error handling for eBGP peers */
1171 if (peer
->sort
!= BGP_PEER_EBGP
)
1173 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1174 notify_datap
, length
);
1175 return BGP_ATTR_PARSE_ERROR
;
1179 /* Adjust the stream getp to the end of the attribute, in case we can
1180 * still proceed but the caller hasn't read all the attribute.
1182 stream_set_getp (BGP_INPUT (peer
),
1183 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
1186 switch (args
->type
) {
1187 /* where an attribute is relatively inconsequential, e.g. it does not
1188 * affect route selection, and can be safely ignored, then any such
1189 * attributes which are malformed should just be ignored and the route
1190 * processed as normal.
1192 case BGP_ATTR_AS4_AGGREGATOR
:
1193 case BGP_ATTR_AGGREGATOR
:
1194 case BGP_ATTR_ATOMIC_AGGREGATE
:
1195 return BGP_ATTR_PARSE_PROCEED
;
1197 /* Core attributes, particularly ones which may influence route
1198 * selection, should always cause session resets
1200 case BGP_ATTR_ORIGIN
:
1201 case BGP_ATTR_AS_PATH
:
1202 case BGP_ATTR_NEXT_HOP
:
1203 case BGP_ATTR_MULTI_EXIT_DISC
:
1204 case BGP_ATTR_LOCAL_PREF
:
1205 case BGP_ATTR_COMMUNITIES
:
1206 case BGP_ATTR_ORIGINATOR_ID
:
1207 case BGP_ATTR_CLUSTER_LIST
:
1208 case BGP_ATTR_MP_REACH_NLRI
:
1209 case BGP_ATTR_MP_UNREACH_NLRI
:
1210 case BGP_ATTR_EXT_COMMUNITIES
:
1211 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1212 notify_datap
, length
);
1213 return BGP_ATTR_PARSE_ERROR
;
1216 /* Partial optional attributes that are malformed should not cause
1217 * the whole session to be reset. Instead treat it as a withdrawal
1218 * of the routes, if possible.
1220 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1221 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1222 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1223 return BGP_ATTR_PARSE_WITHDRAW
;
1225 /* default to reset */
1226 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1229 /* Find out what is wrong with the path attribute flag bits and log the error.
1230 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1231 Extended Length. Checking O/T/P bits at once implies, that the attribute
1232 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1233 non-transitive" attribute. */
1235 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1236 u_int8_t desired_flags
/* how RFC says it must be */
1240 u_char real_flags
= args
->flags
;
1241 const u_int8_t attr_code
= args
->type
;
1243 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1244 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1245 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1248 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1249 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1252 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1253 lookup_msg(attr_str
, attr_code
, NULL
),
1254 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1255 attr_flag_str
[i
].str
);
1260 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1261 " (real flags 0x%x, desired 0x%x)",
1262 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1263 real_flags
, desired_flags
);
1267 /* Required flags for attributes. EXTLEN will be masked off when testing,
1268 * as will PARTIAL for optional+transitive attributes.
1270 const u_int8_t attr_flags_values
[] = {
1271 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1272 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1273 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1274 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1275 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1276 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1277 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1278 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1279 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1280 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1281 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1282 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1283 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1284 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1285 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1286 [BGP_ATTR_LARGE_COMMUNITIES
]= BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1287 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1289 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1292 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1294 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1295 const u_int8_t flags
= args
->flags
;
1296 const u_int8_t attr_code
= args
->type
;
1298 /* there may be attributes we don't know about */
1299 if (attr_code
> attr_flags_values_max
)
1301 if (attr_flags_values
[attr_code
] == 0)
1304 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1307 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1308 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1310 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1311 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1315 /* "For well-known attributes and for optional non-transitive attributes,
1316 * the Partial bit MUST be set to 0."
1318 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1320 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1322 zlog_err ("%s well-known attribute "
1323 "must NOT have the partial flag set (%x)",
1324 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1327 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1328 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1330 zlog_err ("%s optional + transitive attribute "
1331 "must NOT have the partial flag set (%x)",
1332 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1337 /* Optional transitive attributes may go through speakers that don't
1338 * reocgnise them and set the Partial bit.
1340 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1341 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1342 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1345 == attr_flags_values
[attr_code
])
1348 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1352 /* Get origin attribute of the update message. */
1353 static bgp_attr_parse_ret_t
1354 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1356 struct peer
*const peer
= args
->peer
;
1357 struct attr
*const attr
= args
->attr
;
1358 const bgp_size_t length
= args
->length
;
1360 /* If any recognized attribute has Attribute Length that conflicts
1361 with the expected length (based on the attribute type code), then
1362 the Error Subcode is set to Attribute Length Error. The Data
1363 field contains the erroneous attribute (type, length and
1367 zlog_err ("Origin attribute length is not one %d", length
);
1368 return bgp_attr_malformed (args
,
1369 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1373 /* Fetch origin attribute. */
1374 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1376 /* If the ORIGIN attribute has an undefined value, then the Error
1377 Subcode is set to Invalid Origin Attribute. The Data field
1378 contains the unrecognized attribute (type, length and value). */
1379 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1380 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1381 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1383 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1384 return bgp_attr_malformed (args
,
1385 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1389 /* Set oring attribute flag. */
1390 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1395 /* Parse AS path information. This function is wrapper of
1398 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1400 struct attr
*const attr
= args
->attr
;
1401 struct peer
*const peer
= args
->peer
;
1402 const bgp_size_t length
= args
->length
;
1405 * peer with AS4 => will get 4Byte ASnums
1406 * otherwise, will get 16 Bit
1408 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1409 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1411 /* In case of IBGP, length will be zero. */
1414 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1415 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1418 /* Set aspath attribute flag. */
1419 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1421 return BGP_ATTR_PARSE_PROCEED
;
1424 static bgp_attr_parse_ret_t
1425 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1427 /* These checks were part of bgp_attr_aspath, but with
1428 * as4 we should to check aspath things when
1429 * aspath synthesizing with as4_path has already taken place.
1430 * Otherwise we check ASPATH and use the synthesized thing, and that is
1432 * So do the checks later, i.e. here
1434 struct bgp
*bgp
= peer
->bgp
;
1435 struct aspath
*aspath
;
1437 /* Confederation sanity check. */
1438 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1439 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1441 zlog_err ("Malformed AS path from %s", peer
->host
);
1442 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1443 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1444 return BGP_ATTR_PARSE_ERROR
;
1447 /* First AS check for EBGP. */
1448 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1450 if (peer
->sort
== BGP_PEER_EBGP
1451 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1453 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1454 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1455 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1456 return BGP_ATTR_PARSE_ERROR
;
1460 /* local-as prepend */
1461 if (peer
->change_local_as
&&
1462 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1464 aspath
= aspath_dup (attr
->aspath
);
1465 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1466 aspath_unintern (&attr
->aspath
);
1467 attr
->aspath
= aspath_intern (aspath
);
1470 return BGP_ATTR_PARSE_PROCEED
;
1473 /* Parse AS4 path information. This function is another wrapper of
1476 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1478 struct peer
*const peer
= args
->peer
;
1479 struct attr
*const attr
= args
->attr
;
1480 const bgp_size_t length
= args
->length
;
1482 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1484 /* In case of IBGP, length will be zero. */
1487 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1488 return bgp_attr_malformed (args
,
1489 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1493 /* Set aspath attribute flag. */
1494 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1496 return BGP_ATTR_PARSE_PROCEED
;
1499 /* Nexthop attribute. */
1500 static bgp_attr_parse_ret_t
1501 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1503 struct peer
*const peer
= args
->peer
;
1504 struct attr
*const attr
= args
->attr
;
1505 const bgp_size_t length
= args
->length
;
1507 in_addr_t nexthop_h
, nexthop_n
;
1509 /* Check nexthop attribute length. */
1512 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1514 return bgp_attr_malformed (args
,
1515 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1519 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1520 attribute must result in a NOTIFICATION message (this is implemented below).
1521 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1522 logged locally (this is implemented somewhere else). The UPDATE message
1523 gets ignored in any of these cases. */
1524 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1525 nexthop_h
= ntohl (nexthop_n
);
1526 if ((IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1527 && !BGP_DEBUG (allow_martians
, ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1529 char buf
[INET_ADDRSTRLEN
];
1530 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1531 zlog_err ("Martian nexthop %s", buf
);
1532 return bgp_attr_malformed (args
,
1533 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1537 attr
->nexthop
.s_addr
= nexthop_n
;
1538 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1540 return BGP_ATTR_PARSE_PROCEED
;
1543 /* MED atrribute. */
1544 static bgp_attr_parse_ret_t
1545 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1547 struct peer
*const peer
= args
->peer
;
1548 struct attr
*const attr
= args
->attr
;
1549 const bgp_size_t length
= args
->length
;
1554 zlog_err ("MED attribute length isn't four [%d]", length
);
1556 return bgp_attr_malformed (args
,
1557 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1561 attr
->med
= stream_getl (peer
->ibuf
);
1563 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1565 return BGP_ATTR_PARSE_PROCEED
;
1568 /* Local preference attribute. */
1569 static bgp_attr_parse_ret_t
1570 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1572 struct peer
*const peer
= args
->peer
;
1573 struct attr
*const attr
= args
->attr
;
1574 const bgp_size_t length
= args
->length
;
1579 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1580 return bgp_attr_malformed (args
,
1581 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1585 /* If it is contained in an UPDATE message that is received from an
1586 external peer, then this attribute MUST be ignored by the
1587 receiving speaker. */
1588 if (peer
->sort
== BGP_PEER_EBGP
)
1590 stream_forward_getp (peer
->ibuf
, length
);
1591 return BGP_ATTR_PARSE_PROCEED
;
1594 attr
->local_pref
= stream_getl (peer
->ibuf
);
1596 /* Set atomic aggregate flag. */
1597 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1599 return BGP_ATTR_PARSE_PROCEED
;
1602 /* Atomic aggregate. */
1604 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1606 struct attr
*const attr
= args
->attr
;
1607 const bgp_size_t length
= args
->length
;
1612 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1613 return bgp_attr_malformed (args
,
1614 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1618 /* Set atomic aggregate flag. */
1619 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1621 return BGP_ATTR_PARSE_PROCEED
;
1624 /* Aggregator attribute */
1626 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1628 struct peer
*const peer
= args
->peer
;
1629 struct attr
*const attr
= args
->attr
;
1630 const bgp_size_t length
= args
->length
;
1633 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1635 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1636 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1639 if (length
!= wantedlen
)
1641 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1642 return bgp_attr_malformed (args
,
1643 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1647 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1648 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1650 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1651 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1653 /* Set atomic aggregate flag. */
1654 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1656 return BGP_ATTR_PARSE_PROCEED
;
1659 /* New Aggregator attribute */
1660 static bgp_attr_parse_ret_t
1661 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1662 as_t
*as4_aggregator_as
,
1663 struct in_addr
*as4_aggregator_addr
)
1665 struct peer
*const peer
= args
->peer
;
1666 struct attr
*const attr
= args
->attr
;
1667 const bgp_size_t length
= args
->length
;
1671 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1672 return bgp_attr_malformed (args
,
1673 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1677 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1678 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1680 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1682 return BGP_ATTR_PARSE_PROCEED
;
1685 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1687 static bgp_attr_parse_ret_t
1688 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1689 struct attr
*const attr
,
1690 struct aspath
*as4_path
, as_t as4_aggregator
,
1691 struct in_addr
*as4_aggregator_addr
)
1693 int ignore_as4_path
= 0;
1694 struct aspath
*newpath
;
1695 struct attr_extra
*attre
= attr
->extra
;
1699 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1700 * checked that all well-known, mandatory attributes were present.
1702 * Can only be a problem with peer itself - hard error
1704 return BGP_ATTR_PARSE_ERROR
;
1707 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1709 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1711 * It is worth a warning though, because the peer really
1712 * should not send them
1714 if (BGP_DEBUG(as4
, AS4
))
1716 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1717 zlog_debug ("[AS4] %s %s AS4_PATH",
1718 peer
->host
, "AS4 capable peer, yet it sent");
1720 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1721 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1722 peer
->host
, "AS4 capable peer, yet it sent");
1725 return BGP_ATTR_PARSE_PROCEED
;
1728 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1729 * because that may override AS4_PATH
1731 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1733 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1738 * if the as_number in aggregator is not AS_TRANS,
1739 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1740 * and the Aggregator shall be taken as
1741 * info on the aggregating node, and the AS_PATH
1742 * shall be taken as the AS_PATH
1744 * the Aggregator shall be ignored and the
1745 * AS4_AGGREGATOR shall be taken as the
1746 * Aggregating node and the AS_PATH is to be
1747 * constructed "as in all other cases"
1749 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1752 if ( BGP_DEBUG(as4
, AS4
))
1753 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1754 " send AGGREGATOR != AS_TRANS and"
1755 " AS4_AGGREGATOR, so ignore"
1756 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1757 ignore_as4_path
= 1;
1761 /* "New_aggregator shall be taken as aggregator" */
1762 attre
->aggregator_as
= as4_aggregator
;
1763 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1768 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1769 * That is bogus - but reading the conditions
1770 * we have to handle AS4_AGGREGATOR as if it were
1771 * AGGREGATOR in that case
1773 if ( BGP_DEBUG(as4
, AS4
))
1774 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1775 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1776 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1777 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1778 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1779 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1783 /* need to reconcile NEW_AS_PATH and AS_PATH */
1784 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1786 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1787 aspath_unintern (&attr
->aspath
);
1788 attr
->aspath
= aspath_intern (newpath
);
1790 return BGP_ATTR_PARSE_PROCEED
;
1793 /* Community attribute. */
1794 static bgp_attr_parse_ret_t
1795 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1797 struct peer
*const peer
= args
->peer
;
1798 struct attr
*const attr
= args
->attr
;
1799 const bgp_size_t length
= args
->length
;
1803 attr
->community
= NULL
;
1804 return BGP_ATTR_PARSE_PROCEED
;
1808 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1810 /* XXX: fix community_parse to use stream API and remove this */
1811 stream_forward_getp (peer
->ibuf
, length
);
1813 if (!attr
->community
)
1814 return bgp_attr_malformed (args
,
1815 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1818 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1820 return BGP_ATTR_PARSE_PROCEED
;
1823 /* Originator ID attribute. */
1824 static bgp_attr_parse_ret_t
1825 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1827 struct peer
*const peer
= args
->peer
;
1828 struct attr
*const attr
= args
->attr
;
1829 const bgp_size_t length
= args
->length
;
1834 zlog_err ("Bad originator ID length %d", length
);
1836 return bgp_attr_malformed (args
,
1837 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1841 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1842 = stream_get_ipv4 (peer
->ibuf
);
1844 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1846 return BGP_ATTR_PARSE_PROCEED
;
1849 /* Cluster list attribute. */
1850 static bgp_attr_parse_ret_t
1851 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1853 struct peer
*const peer
= args
->peer
;
1854 struct attr
*const attr
= args
->attr
;
1855 const bgp_size_t length
= args
->length
;
1860 zlog_err ("Bad cluster list length %d", length
);
1862 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1866 (bgp_attr_extra_get (attr
))->cluster
1867 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1869 /* XXX: Fix cluster_parse to use stream API and then remove this */
1870 stream_forward_getp (peer
->ibuf
, length
);
1872 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1874 return BGP_ATTR_PARSE_PROCEED
;
1877 /* Multiprotocol reachability information parse. */
1879 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1880 struct bgp_nlri
*mp_update
)
1884 safi_t pkt_safi
, safi
;
1885 bgp_size_t nlri_len
;
1888 struct peer
*const peer
= args
->peer
;
1889 struct attr
*const attr
= args
->attr
;
1890 const bgp_size_t length
= args
->length
;
1891 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1893 /* Set end of packet. */
1894 s
= BGP_INPUT(peer
);
1895 start
= stream_get_getp(s
);
1897 /* safe to read statically sized header? */
1898 #define BGP_MP_REACH_MIN_SIZE 5
1899 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1900 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1902 zlog_info ("%s: %s sent invalid length, %lu",
1903 __func__
, peer
->host
, (unsigned long)length
);
1904 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1907 /* Load AFI, SAFI. */
1908 pkt_afi
= stream_getw (s
);
1909 pkt_safi
= stream_getc (s
);
1911 /* Convert AFI, SAFI to internal values, check. */
1912 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
1914 /* Log if AFI or SAFI is unrecognized. This is not an error unless
1915 * the attribute is otherwise malformed.
1917 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1918 zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1919 peer
->host
, pkt_afi
, pkt_safi
);
1920 return BGP_ATTR_PARSE_ERROR
;
1923 /* Get nexthop length. */
1924 attre
->mp_nexthop_len
= stream_getc (s
);
1926 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1928 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1929 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1930 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1933 /* Nexthop length check. */
1934 switch (attre
->mp_nexthop_len
)
1936 case BGP_ATTR_NHLEN_IPV4
:
1937 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1938 /* Probably needed for RFC 2283 */
1939 if (attr
->nexthop
.s_addr
== 0)
1940 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1942 case BGP_ATTR_NHLEN_VPNV4
:
1943 stream_getl (s
); /* RD high */
1944 stream_getl (s
); /* RD low */
1945 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1947 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1948 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1949 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1951 stream_getl (s
); /* RD high */
1952 stream_getl (s
); /* RD low */
1954 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1956 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1957 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1958 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1960 stream_getl (s
); /* RD high */
1961 stream_getl (s
); /* RD low */
1963 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1964 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1966 stream_getl (s
); /* RD high */
1967 stream_getl (s
); /* RD low */
1969 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1970 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1972 char buf1
[INET6_ADDRSTRLEN
];
1973 char buf2
[INET6_ADDRSTRLEN
];
1975 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1976 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1978 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1979 buf1
, INET6_ADDRSTRLEN
),
1980 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1981 buf2
, INET6_ADDRSTRLEN
));
1983 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1987 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1988 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1989 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1994 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1995 __func__
, peer
->host
);
1996 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2001 if ((val
= stream_getc (s
)))
2002 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
2006 /* must have nrli_len, what is left of the attribute */
2007 nlri_len
= LEN_LEFT
;
2008 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
2010 zlog_info ("%s: (%s) Failed to read NLRI",
2011 __func__
, peer
->host
);
2012 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2015 mp_update
->afi
= afi
;
2016 mp_update
->safi
= safi
;
2017 mp_update
->nlri
= stream_pnt (s
);
2018 mp_update
->length
= nlri_len
;
2020 stream_forward_getp (s
, nlri_len
);
2022 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
2024 return BGP_ATTR_PARSE_PROCEED
;
2028 /* Multiprotocol unreachable parse */
2030 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
2031 struct bgp_nlri
*mp_withdraw
)
2036 safi_t pkt_safi
, safi
;
2037 u_int16_t withdraw_len
;
2038 struct peer
*const peer
= args
->peer
;
2039 struct attr
*const attr
= args
->attr
;
2040 const bgp_size_t length
= args
->length
;
2044 #define BGP_MP_UNREACH_MIN_SIZE 3
2045 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2046 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2048 pkt_afi
= stream_getw (s
);
2049 pkt_safi
= stream_getc (s
);
2051 /* Convert AFI, SAFI to internal values, check. */
2052 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
2054 /* Log if AFI or SAFI is unrecognized. This is not an error unless
2055 * the attribute is otherwise malformed.
2057 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2058 zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
2059 peer
->host
, pkt_afi
, pkt_safi
);
2060 return BGP_ATTR_PARSE_ERROR
;
2063 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2065 mp_withdraw
->afi
= afi
;
2066 mp_withdraw
->safi
= safi
;
2067 mp_withdraw
->nlri
= stream_pnt (s
);
2068 mp_withdraw
->length
= withdraw_len
;
2070 stream_forward_getp (s
, withdraw_len
);
2072 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
2074 return BGP_ATTR_PARSE_PROCEED
;
2077 /* Large Community attribute. */
2078 static bgp_attr_parse_ret_t
2079 bgp_attr_large_community (struct bgp_attr_parser_args
*args
)
2081 struct peer
*const peer
= args
->peer
;
2082 struct attr
*const attr
= args
->attr
;
2083 const bgp_size_t length
= args
->length
;
2086 * Large community follows new attribute format.
2091 attr
->extra
->lcommunity
= NULL
;
2092 /* Empty extcomm doesn't seem to be invalid per se */
2093 return BGP_ATTR_PARSE_PROCEED
;
2096 (bgp_attr_extra_get (attr
))->lcommunity
=
2097 lcommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2098 /* XXX: fix ecommunity_parse to use stream API */
2099 stream_forward_getp (peer
->ibuf
, length
);
2101 if (attr
->extra
&& !attr
->extra
->lcommunity
)
2102 return bgp_attr_malformed (args
,
2103 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2106 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
);
2108 return BGP_ATTR_PARSE_PROCEED
;
2111 /* Extended Community attribute. */
2112 static bgp_attr_parse_ret_t
2113 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
2115 struct peer
*const peer
= args
->peer
;
2116 struct attr
*const attr
= args
->attr
;
2117 const bgp_size_t length
= args
->length
;
2122 attr
->extra
->ecommunity
= NULL
;
2123 /* Empty extcomm doesn't seem to be invalid per se */
2124 return BGP_ATTR_PARSE_PROCEED
;
2127 (bgp_attr_extra_get (attr
))->ecommunity
=
2128 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2129 /* XXX: fix ecommunity_parse to use stream API */
2130 stream_forward_getp (peer
->ibuf
, length
);
2132 if (attr
->extra
&& !attr
->extra
->ecommunity
)
2133 return bgp_attr_malformed (args
,
2134 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2137 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
2139 return BGP_ATTR_PARSE_PROCEED
;
2142 /* Parse Tunnel Encap attribute in an UPDATE */
2146 struct peer
*peer
, /* IN */
2147 bgp_size_t length
, /* IN: attr's length field */
2148 struct attr
*attr
, /* IN: caller already allocated */
2149 u_char flag
, /* IN: attr's flags field */
2153 struct attr_extra
*attre
= NULL
;
2154 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2155 uint16_t tunneltype
= 0;
2157 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2159 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2160 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
2162 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
2163 bgp_notify_send_with_data (peer
,
2164 BGP_NOTIFY_UPDATE_ERR
,
2165 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2170 if (BGP_ATTR_ENCAP
== type
) {
2171 /* read outer TLV type and length */
2172 uint16_t tlv_length
;
2175 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2176 bgp_notify_send_with_data(peer
,
2177 BGP_NOTIFY_UPDATE_ERR
,
2178 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2182 tunneltype
= stream_getw (BGP_INPUT (peer
));
2183 tlv_length
= stream_getw (BGP_INPUT (peer
));
2186 if (tlv_length
!= length
) {
2187 zlog_info ("%s: tlv_length(%d) != length(%d)",
2188 __func__
, tlv_length
, length
);
2192 while (length
>= 4) {
2193 uint16_t subtype
= 0;
2194 uint16_t sublength
= 0;
2195 struct bgp_attr_encap_subtlv
*tlv
;
2197 if (BGP_ATTR_ENCAP
== type
) {
2198 subtype
= stream_getc (BGP_INPUT (peer
));
2199 sublength
= stream_getc (BGP_INPUT (peer
));
2203 subtype
= stream_getw (BGP_INPUT (peer
));
2204 sublength
= stream_getw (BGP_INPUT (peer
));
2209 if (sublength
> length
) {
2210 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2212 bgp_notify_send_with_data (peer
,
2213 BGP_NOTIFY_UPDATE_ERR
,
2214 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2219 /* alloc and copy sub-tlv */
2220 /* TBD make sure these are freed when attributes are released */
2221 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
2222 tlv
->type
= subtype
;
2223 tlv
->length
= sublength
;
2224 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2225 length
-= sublength
;
2227 /* attach tlv to encap chain */
2229 attre
= bgp_attr_extra_get(attr
);
2230 if (BGP_ATTR_ENCAP
== type
) {
2231 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
2232 stlv_last
= stlv_last
->next
);
2234 stlv_last
->next
= tlv
;
2236 attre
->encap_subtlvs
= tlv
;
2240 for (stlv_last
= attre
->vnc_subtlvs
; stlv_last
&& stlv_last
->next
;
2241 stlv_last
= stlv_last
->next
);
2243 stlv_last
->next
= tlv
;
2245 attre
->vnc_subtlvs
= tlv
;
2250 stlv_last
->next
= tlv
;
2255 if (BGP_ATTR_ENCAP
== type
) {
2257 attre
= bgp_attr_extra_get(attr
);
2258 attre
->encap_tunneltype
= tunneltype
;
2262 /* spurious leftover data */
2263 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2264 bgp_notify_send_with_data (peer
,
2265 BGP_NOTIFY_UPDATE_ERR
,
2266 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2274 /* Prefix SID attribute
2275 * draft-ietf-idr-bgp-prefix-sid-05
2277 static bgp_attr_parse_ret_t
2278 bgp_attr_prefix_sid (struct bgp_attr_parser_args
*args
, struct bgp_nlri
*mp_update
)
2280 struct peer
*const peer
= args
->peer
;
2281 struct attr
*const attr
= args
->attr
;
2284 u_int32_t label_index
;
2285 struct in6_addr ipv6_sid
;
2286 u_int32_t srgb_base
;
2287 u_int32_t srgb_range
;
2290 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
);
2292 type
= stream_getc (peer
->ibuf
);
2293 length
= stream_getw (peer
->ibuf
);
2295 if (type
== BGP_PREFIX_SID_LABEL_INDEX
)
2297 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
)
2299 zlog_err ("Prefix SID label index length is %d instead of %d", length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2300 return bgp_attr_malformed (args
,
2301 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2305 /* Ignore flags and reserved */
2306 stream_getc (peer
->ibuf
);
2307 stream_getw (peer
->ibuf
);
2309 /* Fetch the label index and see if it is valid. */
2310 label_index
= stream_getl (peer
->ibuf
);
2311 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2312 return bgp_attr_malformed (args
,
2313 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2316 /* Store label index; subsequently, we'll check on address-family */
2317 (bgp_attr_extra_get (attr
))->label_index
= label_index
;
2320 * Ignore the Label index attribute unless received for labeled-unicast
2323 if (!mp_update
->length
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2324 attr
->extra
->label_index
= BGP_INVALID_LABEL_INDEX
;
2327 /* Placeholder code for the IPv6 SID type */
2328 else if (type
== BGP_PREFIX_SID_IPV6
)
2330 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
)
2332 zlog_err ("Prefix SID IPv6 length is %d instead of %d", length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2333 return bgp_attr_malformed (args
,
2334 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2338 /* Ignore reserved */
2339 stream_getc (peer
->ibuf
);
2340 stream_getw (peer
->ibuf
);
2342 stream_get (&ipv6_sid
, peer
->ibuf
, 16);
2345 /* Placeholder code for the Originator SRGB type */
2346 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
)
2349 stream_getw (peer
->ibuf
);
2353 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)
2355 zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2356 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2357 return bgp_attr_malformed (args
,
2358 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2362 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2364 for (int i
= 0; i
< srgb_count
; i
++)
2366 stream_get (&srgb_base
, peer
->ibuf
, 3);
2367 stream_get (&srgb_range
, peer
->ibuf
, 3);
2371 return BGP_ATTR_PARSE_PROCEED
;
2374 /* BGP unknown attribute treatment. */
2375 static bgp_attr_parse_ret_t
2376 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2378 bgp_size_t total
= args
->total
;
2379 struct transit
*transit
;
2380 struct attr_extra
*attre
;
2381 struct peer
*const peer
= args
->peer
;
2382 struct attr
*const attr
= args
->attr
;
2383 u_char
*const startp
= args
->startp
;
2384 const u_char type
= args
->type
;
2385 const u_char flag
= args
->flags
;
2386 const bgp_size_t length
= args
->length
;
2388 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2389 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2390 peer
->host
, type
, length
);
2392 /* Forward read pointer of input stream. */
2393 stream_forward_getp (peer
->ibuf
, length
);
2395 /* If any of the mandatory well-known attributes are not recognized,
2396 then the Error Subcode is set to Unrecognized Well-known
2397 Attribute. The Data field contains the unrecognized attribute
2398 (type, length and value). */
2399 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2401 return bgp_attr_malformed (args
,
2402 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2406 /* Unrecognized non-transitive optional attributes must be quietly
2407 ignored and not passed along to other BGP peers. */
2408 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2409 return BGP_ATTR_PARSE_PROCEED
;
2411 /* If a path with recognized transitive optional attribute is
2412 accepted and passed along to other BGP peers and the Partial bit
2413 in the Attribute Flags octet is set to 1 by some previous AS, it
2414 is not set back to 0 by the current AS. */
2415 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2417 /* Store transitive attribute to the end of attr->transit. */
2418 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2419 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2421 transit
= attre
->transit
;
2424 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2425 transit
->length
+ total
);
2427 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2429 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2430 transit
->length
+= total
;
2432 return BGP_ATTR_PARSE_PROCEED
;
2435 /* Well-known attribute check. */
2437 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2441 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2443 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2444 return BGP_ATTR_PARSE_PROCEED
;
2446 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2447 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2448 are present, it should. Check for any other attribute being present
2451 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2452 return BGP_ATTR_PARSE_PROCEED
;
2454 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2455 type
= BGP_ATTR_ORIGIN
;
2457 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2458 type
= BGP_ATTR_AS_PATH
;
2460 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2461 * NLRI is empty. We can't easily check NLRI empty here though.
2463 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2464 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2465 type
= BGP_ATTR_NEXT_HOP
;
2467 if (peer
->sort
== BGP_PEER_IBGP
2468 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2469 type
= BGP_ATTR_LOCAL_PREF
;
2473 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2474 lookup_msg(attr_str
, type
, NULL
));
2475 bgp_notify_send_with_data (peer
,
2476 BGP_NOTIFY_UPDATE_ERR
,
2477 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2479 return BGP_ATTR_PARSE_ERROR
;
2481 return BGP_ATTR_PARSE_PROCEED
;
2484 /* Read attribute of update packet. This function is called from
2485 bgp_update_receive() in bgp_packet.c. */
2486 bgp_attr_parse_ret_t
2487 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2488 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2494 u_char
*startp
, *endp
;
2496 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2497 /* we need the as4_path only until we have synthesized the as_path with it */
2498 /* same goes for as4_aggregator */
2499 struct aspath
*as4_path
= NULL
;
2500 as_t as4_aggregator
= 0;
2501 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2503 /* Initialize bitmap. */
2504 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2506 /* End pointer of BGP attribute. */
2507 endp
= BGP_INPUT_PNT (peer
) + size
;
2509 /* Get attributes to the end of attribute length. */
2510 while (BGP_INPUT_PNT (peer
) < endp
)
2512 /* Check remaining length check.*/
2513 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2515 /* XXX warning: long int format, int arg (arg 5) */
2516 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2518 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2520 bgp_notify_send (peer
,
2521 BGP_NOTIFY_UPDATE_ERR
,
2522 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2523 return BGP_ATTR_PARSE_ERROR
;
2526 /* Fetch attribute flag and type. */
2527 startp
= BGP_INPUT_PNT (peer
);
2528 /* "The lower-order four bits of the Attribute Flags octet are
2529 unused. They MUST be zero when sent and MUST be ignored when
2531 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2532 type
= stream_getc (BGP_INPUT (peer
));
2534 /* Check whether Extended-Length applies and is in bounds */
2535 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2536 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2538 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2540 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2542 bgp_notify_send (peer
,
2543 BGP_NOTIFY_UPDATE_ERR
,
2544 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2545 return BGP_ATTR_PARSE_ERROR
;
2548 /* Check extended attribue length bit. */
2549 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2550 length
= stream_getw (BGP_INPUT (peer
));
2552 length
= stream_getc (BGP_INPUT (peer
));
2554 /* If any attribute appears more than once in the UPDATE
2555 message, then the Error Subcode is set to Malformed Attribute
2558 if (CHECK_BITMAP (seen
, type
))
2560 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2563 bgp_notify_send (peer
,
2564 BGP_NOTIFY_UPDATE_ERR
,
2565 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2566 return BGP_ATTR_PARSE_ERROR
;
2569 /* Set type to bitmap to check duplicate attribute. `type' is
2570 unsigned char so it never overflow bitmap range. */
2572 SET_BITMAP (seen
, type
);
2574 /* Overflow check. */
2575 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2577 if (attr_endp
> endp
)
2579 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
);
2580 bgp_notify_send_with_data (peer
,
2581 BGP_NOTIFY_UPDATE_ERR
,
2582 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2583 startp
, attr_endp
- startp
);
2584 return BGP_ATTR_PARSE_ERROR
;
2587 struct bgp_attr_parser_args attr_args
= {
2594 .total
= attr_endp
- startp
,
2598 /* If any recognized attribute has Attribute Flags that conflict
2599 with the Attribute Type Code, then the Error Subcode is set to
2600 Attribute Flags Error. The Data field contains the erroneous
2601 attribute (type, length and value). */
2602 if (bgp_attr_flag_invalid (&attr_args
))
2604 bgp_attr_parse_ret_t ret
;
2605 ret
= bgp_attr_malformed (&attr_args
,
2606 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2608 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2613 /* OK check attribute and store it's value. */
2616 case BGP_ATTR_ORIGIN
:
2617 ret
= bgp_attr_origin (&attr_args
);
2619 case BGP_ATTR_AS_PATH
:
2620 ret
= bgp_attr_aspath (&attr_args
);
2622 case BGP_ATTR_AS4_PATH
:
2623 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2625 case BGP_ATTR_NEXT_HOP
:
2626 ret
= bgp_attr_nexthop (&attr_args
);
2628 case BGP_ATTR_MULTI_EXIT_DISC
:
2629 ret
= bgp_attr_med (&attr_args
);
2631 case BGP_ATTR_LOCAL_PREF
:
2632 ret
= bgp_attr_local_pref (&attr_args
);
2634 case BGP_ATTR_ATOMIC_AGGREGATE
:
2635 ret
= bgp_attr_atomic (&attr_args
);
2637 case BGP_ATTR_AGGREGATOR
:
2638 ret
= bgp_attr_aggregator (&attr_args
);
2640 case BGP_ATTR_AS4_AGGREGATOR
:
2641 ret
= bgp_attr_as4_aggregator (&attr_args
,
2643 &as4_aggregator_addr
);
2645 case BGP_ATTR_COMMUNITIES
:
2646 ret
= bgp_attr_community (&attr_args
);
2648 case BGP_ATTR_LARGE_COMMUNITIES
:
2649 ret
= bgp_attr_large_community (&attr_args
);
2651 case BGP_ATTR_ORIGINATOR_ID
:
2652 ret
= bgp_attr_originator_id (&attr_args
);
2654 case BGP_ATTR_CLUSTER_LIST
:
2655 ret
= bgp_attr_cluster_list (&attr_args
);
2657 case BGP_ATTR_MP_REACH_NLRI
:
2658 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2660 case BGP_ATTR_MP_UNREACH_NLRI
:
2661 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2663 case BGP_ATTR_EXT_COMMUNITIES
:
2664 ret
= bgp_attr_ext_communities (&attr_args
);
2669 case BGP_ATTR_ENCAP
:
2670 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2672 case BGP_ATTR_PREFIX_SID
:
2673 ret
= bgp_attr_prefix_sid (&attr_args
, mp_update
);
2676 ret
= bgp_attr_unknown (&attr_args
);
2680 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2682 bgp_notify_send (peer
,
2683 BGP_NOTIFY_UPDATE_ERR
,
2684 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2685 ret
= BGP_ATTR_PARSE_ERROR
;
2688 /* If hard error occured immediately return to the caller. */
2689 if (ret
== BGP_ATTR_PARSE_ERROR
)
2691 zlog_warn ("%s: Attribute %s, parse error",
2693 lookup_msg(attr_str
, type
, NULL
));
2695 aspath_unintern (&as4_path
);
2698 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2701 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2703 lookup_msg(attr_str
, type
, NULL
));
2705 aspath_unintern (&as4_path
);
2709 /* Check the fetched length. */
2710 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2712 zlog_warn ("%s: BGP attribute %s, fetch error",
2713 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2714 bgp_notify_send (peer
,
2715 BGP_NOTIFY_UPDATE_ERR
,
2716 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2718 aspath_unintern (&as4_path
);
2719 return BGP_ATTR_PARSE_ERROR
;
2723 /* Check final read pointer is same as end pointer. */
2724 if (BGP_INPUT_PNT (peer
) != endp
)
2726 zlog_warn ("%s: BGP attribute %s, length mismatch",
2727 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2728 bgp_notify_send (peer
,
2729 BGP_NOTIFY_UPDATE_ERR
,
2730 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2732 aspath_unintern (&as4_path
);
2733 return BGP_ATTR_PARSE_ERROR
;
2736 /* Check all mandatory well-known attributes are present */
2738 bgp_attr_parse_ret_t ret
;
2739 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2742 aspath_unintern (&as4_path
);
2748 * At this place we can see whether we got AS4_PATH and/or
2749 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2750 * We can not do this before we've read all attributes because
2751 * the as4 handling does not say whether AS4_PATH has to be sent
2752 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2753 * in relationship to AGGREGATOR.
2754 * So, to be defensive, we are not relying on any order and read
2755 * all attributes first, including these 32bit ones, and now,
2756 * afterwards, we look what and if something is to be done for as4.
2758 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2761 /* actually... this doesn't ever return failure currently, but
2762 * better safe than sorry */
2763 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2764 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2765 as4_aggregator
, &as4_aggregator_addr
))
2767 bgp_notify_send (peer
,
2768 BGP_NOTIFY_UPDATE_ERR
,
2769 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2771 aspath_unintern (&as4_path
);
2772 return BGP_ATTR_PARSE_ERROR
;
2775 /* At this stage, we have done all fiddling with as4, and the
2776 * resulting info is in attr->aggregator resp. attr->aspath
2777 * so we can chuck as4_aggregator and as4_path alltogether in
2778 * order to save memory
2782 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2783 /* The flag that we got this is still there, but that does not
2788 * The "rest" of the code does nothing with as4_aggregator.
2789 * there is no memory attached specifically which is not part
2791 * so ignoring just means do nothing.
2794 * Finally do the checks on the aspath we did not do yet
2795 * because we waited for a potentially synthesized aspath.
2797 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2799 ret
= bgp_attr_aspath_check (peer
, attr
);
2800 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2805 /* Finally intern unknown attribute. */
2806 if (attr
->extra
->transit
)
2807 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2808 if (attr
->extra
->encap_subtlvs
)
2809 attr
->extra
->encap_subtlvs
= encap_intern (attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2811 if (attr
->extra
->vnc_subtlvs
)
2812 attr
->extra
->vnc_subtlvs
= encap_intern (attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2816 return BGP_ATTR_PARSE_PROCEED
;
2820 bgp_packet_mpattr_start (struct stream
*s
, struct peer
*peer
,
2821 afi_t afi
, safi_t safi
,
2822 struct bpacket_attr_vec_arr
*vecarr
,
2830 /* Set extended bit always to encode the attribute length as 2 bytes */
2831 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2832 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2833 sizep
= stream_get_endp (s
);
2834 stream_putw (s
, 0); /* Marker: Attribute length. */
2837 /* Convert AFI, SAFI to values for packet. */
2838 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
2840 stream_putw (s
, pkt_afi
); /* AFI */
2841 stream_putc (s
, pkt_safi
); /* SAFI */
2844 if (peer_cap_enhe(peer
, afi
, safi
)) {
2847 if (afi
== AFI_L2VPN
)
2849 else if (safi
== SAFI_LABELED_UNICAST
)
2852 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->extra
->mp_nexthop_len
);
2856 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2863 case SAFI_MULTICAST
:
2864 case SAFI_LABELED_UNICAST
:
2866 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2869 stream_putc (s
, 12);
2870 stream_putl (s
, 0); /* RD = 0, per RFC */
2872 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2876 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2886 case SAFI_MULTICAST
:
2887 case SAFI_LABELED_UNICAST
:
2889 struct attr_extra
*attre
= attr
->extra
;
2891 assert (attr
->extra
);
2893 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2894 stream_putc (s
, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2895 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2896 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2898 stream_putc (s
, IPV6_MAX_BYTELEN
);
2899 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2905 struct attr_extra
*attre
= attr
->extra
;
2907 assert (attr
->extra
);
2908 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2909 stream_putc (s
, 24);
2910 stream_putl (s
, 0); /* RD = 0, per RFC */
2912 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2913 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2914 stream_putc (s
, 48);
2915 stream_putl (s
, 0); /* RD = 0, per RFC */
2917 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2918 stream_putl (s
, 0); /* RD = 0, per RFC */
2920 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2925 assert (attr
->extra
);
2926 stream_putc (s
, IPV6_MAX_BYTELEN
);
2927 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2937 if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
)
2939 stream_putc (s
, 12);
2940 stream_putl (s
, 0); /* RD = 0, per RFC */
2942 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2944 else if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
)
2946 stream_putc (s
, 24);
2947 stream_putl (s
, 0); /* RD = 0, per RFC */
2949 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2951 else if (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2953 stream_putc (s
, 48);
2954 stream_putl (s
, 0); /* RD = 0, per RFC */
2956 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2957 stream_putl (s
, 0); /* RD = 0, per RFC */
2959 stream_put (s
, &attr
->extra
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2976 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2977 struct prefix
*p
, struct prefix_rd
*prd
,
2978 mpls_label_t
*label
, int addpath_encode
,
2979 u_int32_t addpath_tx_id
, struct attr
*attr
)
2981 if (safi
== SAFI_MPLS_VPN
)
2984 stream_putl(s
, addpath_tx_id
);
2985 /* Label, RD, Prefix write. */
2986 stream_putc (s
, p
->prefixlen
+ 88);
2987 stream_put (s
, label
, BGP_LABEL_BYTES
);
2988 stream_put (s
, prd
->val
, 8);
2989 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2991 else if (safi
== SAFI_EVPN
)
2993 bgp_packet_mpattr_route_type_5(s
, p
, prd
, label
, attr
);
2995 else if (safi
== SAFI_LABELED_UNICAST
)
2997 /* Prefix write with label. */
2998 stream_put_labeled_prefix(s
, p
, label
);
3001 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
3005 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
3007 int size
= PSIZE (p
->prefixlen
);
3008 if (safi
== SAFI_MPLS_VPN
)
3014 * Encodes the tunnel encapsulation attribute,
3015 * and with ENABLE_BGP_VNC the VNC attribute which uses
3016 * almost the same TLV format
3019 bgp_packet_mpattr_tea(
3026 unsigned int attrlenfield
= 0;
3027 unsigned int attrhdrlen
= 0;
3028 struct bgp_attr_encap_subtlv
*subtlvs
;
3029 struct bgp_attr_encap_subtlv
*st
;
3030 const char *attrname
;
3032 if (!attr
|| !attr
->extra
||
3033 (attrtype
== BGP_ATTR_ENCAP
&&
3034 (!attr
->extra
->encap_tunneltype
||
3035 attr
->extra
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3039 case BGP_ATTR_ENCAP
:
3040 attrname
= "Tunnel Encap";
3041 subtlvs
= attr
->extra
->encap_subtlvs
;
3042 if (subtlvs
== NULL
) /* nothing to do */
3045 * The tunnel encap attr has an "outer" tlv.
3047 * L = total length of subtlvs,
3048 * V = concatenated subtlvs.
3050 attrlenfield
= 2 + 2; /* T + L */
3051 attrhdrlen
= 1 + 1; /* subTLV T + L */
3057 subtlvs
= attr
->extra
->vnc_subtlvs
;
3058 if (subtlvs
== NULL
) /* nothing to do */
3060 attrlenfield
= 0; /* no outer T + L */
3061 attrhdrlen
= 2 + 2; /* subTLV T + L */
3069 /* compute attr length */
3070 for (st
= subtlvs
; st
; st
= st
->next
) {
3071 attrlenfield
+= (attrhdrlen
+ st
->length
);
3074 if (attrlenfield
> 0xffff) {
3075 zlog_info ("%s attribute is too long (length=%d), can't send it",
3081 if (attrlenfield
> 0xff) {
3082 /* 2-octet length field */
3084 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3085 stream_putc (s
, attrtype
);
3086 stream_putw (s
, attrlenfield
& 0xffff);
3088 /* 1-octet length field */
3089 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
3090 stream_putc (s
, attrtype
);
3091 stream_putc (s
, attrlenfield
& 0xff);
3094 if (attrtype
== BGP_ATTR_ENCAP
) {
3095 /* write outer T+L */
3096 stream_putw(s
, attr
->extra
->encap_tunneltype
);
3097 stream_putw(s
, attrlenfield
- 4);
3100 /* write each sub-tlv */
3101 for (st
= subtlvs
; st
; st
= st
->next
) {
3102 if (attrtype
== BGP_ATTR_ENCAP
) {
3103 stream_putc (s
, st
->type
);
3104 stream_putc (s
, st
->length
);
3107 stream_putw (s
, st
->type
);
3108 stream_putw (s
, st
->length
);
3111 stream_put (s
, st
->value
, st
->length
);
3116 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
3118 /* Set MP attribute length. Don't count the (2) bytes used to encode
3120 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
3123 /* Make attribute packet. */
3125 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
3126 struct stream
*s
, struct attr
*attr
,
3127 struct bpacket_attr_vec_arr
*vecarr
,
3128 struct prefix
*p
, afi_t afi
, safi_t safi
,
3129 struct peer
*from
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3131 u_int32_t addpath_tx_id
)
3134 size_t aspath_sizep
;
3135 struct aspath
*aspath
;
3136 int send_as4_path
= 0;
3137 int send_as4_aggregator
= 0;
3138 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3143 /* Remember current pointer. */
3144 cp
= stream_get_endp (s
);
3146 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
3147 !peer_cap_enhe(peer
, afi
, safi
)))
3149 size_t mpattrlen_pos
= 0;
3151 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
, vecarr
, attr
);
3152 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3153 addpath_encode
, addpath_tx_id
, attr
);
3154 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3157 /* Origin attribute. */
3158 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3159 stream_putc (s
, BGP_ATTR_ORIGIN
);
3161 stream_putc (s
, attr
->origin
);
3163 /* AS path attribute. */
3165 /* If remote-peer is EBGP */
3166 if (peer
->sort
== BGP_PEER_EBGP
3167 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
3168 || attr
->aspath
->segments
== NULL
)
3169 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
3171 aspath
= aspath_dup (attr
->aspath
);
3173 /* Even though we may not be configured for confederations we may have
3174 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3175 aspath
= aspath_delete_confed_seq (aspath
);
3177 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
3179 /* Stuff our path CONFED_ID on the front */
3180 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
3184 if (peer
->change_local_as
) {
3185 /* If replace-as is specified, we only use the change_local_as when
3186 advertising routes. */
3187 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
3188 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3190 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
3192 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3196 else if (peer
->sort
== BGP_PEER_CONFED
)
3198 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
3199 aspath
= aspath_dup (attr
->aspath
);
3200 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
3203 aspath
= attr
->aspath
;
3205 /* If peer is not AS4 capable, then:
3206 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3207 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
3208 * types are in it (i.e. exclude them if they are there)
3209 * AND do this only if there is at least one asnum > 65535 in the path!
3210 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
3211 * all ASnums > 65535 to BGP_AS_TRANS
3214 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3215 stream_putc (s
, BGP_ATTR_AS_PATH
);
3216 aspath_sizep
= stream_get_endp (s
);
3218 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
3220 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3223 if (!use32bit
&& aspath_has_as4 (aspath
))
3224 send_as4_path
= 1; /* we'll do this later, at the correct place */
3226 /* Nexthop attribute. */
3227 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
, afi
, safi
))
3229 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
3231 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3232 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3233 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3235 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3237 else if (peer_cap_enhe(from
, afi
, safi
))
3240 * Likely this is the case when an IPv4 prefix was received with
3241 * Extended Next-hop capability and now being advertised to
3243 * Setting the mandatory (ipv4) next-hop attribute here to enable
3244 * implicit next-hop self with correct (ipv4 address family).
3246 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3247 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3248 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
3250 stream_put_ipv4 (s
, 0);
3254 /* MED attribute. */
3255 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
3258 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3259 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3261 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
3264 /* Local preference. */
3265 if (peer
->sort
== BGP_PEER_IBGP
||
3266 peer
->sort
== BGP_PEER_CONFED
)
3268 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3269 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3271 stream_putl (s
, attr
->local_pref
);
3274 /* Atomic aggregate. */
3275 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3277 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3278 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3283 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3285 assert (attr
->extra
);
3287 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3288 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3289 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3293 /* AS4 capable peer */
3295 stream_putl (s
, attr
->extra
->aggregator_as
);
3299 /* 2-byte AS peer */
3302 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3303 if ( attr
->extra
->aggregator_as
> 65535 )
3305 stream_putw (s
, BGP_AS_TRANS
);
3307 /* we have to send AS4_AGGREGATOR, too.
3308 * we'll do that later in order to send attributes in ascending
3311 send_as4_aggregator
= 1;
3314 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
3316 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3319 /* Community attribute. */
3320 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3321 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
3323 if (attr
->community
->size
* 4 > 255)
3325 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3326 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3327 stream_putw (s
, attr
->community
->size
* 4);
3331 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3332 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3333 stream_putc (s
, attr
->community
->size
* 4);
3335 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3339 * Large Community attribute.
3342 CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_LARGE_COMMUNITY
)
3343 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
)))
3345 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3347 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3348 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3349 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3353 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3354 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3355 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3357 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3360 /* Route Reflector. */
3361 if (peer
->sort
== BGP_PEER_IBGP
3363 && from
->sort
== BGP_PEER_IBGP
)
3365 /* Originator ID. */
3366 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3367 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
3370 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3371 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
3373 stream_put_in_addr (s
, &from
->remote_id
);
3376 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3377 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
3379 if (attr
->extra
&& attr
->extra
->cluster
)
3381 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
3382 /* If this peer configuration's parent BGP has cluster_id. */
3383 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3384 stream_put_in_addr (s
, &bgp
->cluster_id
);
3386 stream_put_in_addr (s
, &bgp
->router_id
);
3387 stream_put (s
, attr
->extra
->cluster
->list
,
3388 attr
->extra
->cluster
->length
);
3393 /* If this peer configuration's parent BGP has cluster_id. */
3394 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3395 stream_put_in_addr (s
, &bgp
->cluster_id
);
3397 stream_put_in_addr (s
, &bgp
->router_id
);
3401 /* Extended Communities attribute. */
3402 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3403 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
3405 struct attr_extra
*attre
= attr
->extra
;
3409 if (peer
->sort
== BGP_PEER_IBGP
3410 || peer
->sort
== BGP_PEER_CONFED
)
3412 if (attre
->ecommunity
->size
* 8 > 255)
3414 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3415 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3416 stream_putw (s
, attre
->ecommunity
->size
* 8);
3420 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3421 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3422 stream_putc (s
, attre
->ecommunity
->size
* 8);
3424 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
3430 int ecom_tr_size
= 0;
3433 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3435 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3438 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3446 if (ecom_tr_size
* 8 > 255)
3448 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3449 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3450 stream_putw (s
, ecom_tr_size
* 8);
3454 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3455 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3456 stream_putc (s
, ecom_tr_size
* 8);
3459 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3461 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3464 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3467 stream_put (s
, pnt
, 8);
3473 /* Label index attribute. */
3474 if (safi
== SAFI_LABELED_UNICAST
)
3476 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3478 u_int32_t label_index
;
3480 assert (attr
->extra
);
3481 label_index
= attr
->extra
->label_index
;
3483 if (label_index
!= BGP_INVALID_LABEL_INDEX
)
3485 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3486 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3487 stream_putc (s
, 10);
3488 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3489 stream_putw (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3490 stream_putc (s
, 0); // reserved
3491 stream_putw (s
, 0); // flags
3492 stream_putl (s
, label_index
);
3497 if ( send_as4_path
)
3499 /* If the peer is NOT As4 capable, AND */
3500 /* there are ASnums > 65535 in path THEN
3501 * give out AS4_PATH */
3503 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3505 * Hm, I wonder... confederation things *should* only be at
3506 * the beginning of an aspath, right? Then we should use
3507 * aspath_delete_confed_seq for this, because it is already
3509 * Folks, talk to me: what is reasonable here!?
3511 aspath
= aspath_delete_confed_seq (aspath
);
3513 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3514 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3515 aspath_sizep
= stream_get_endp (s
);
3517 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3520 if (aspath
!= attr
->aspath
)
3521 aspath_free (aspath
);
3523 if ( send_as4_aggregator
)
3525 assert (attr
->extra
);
3527 /* send AS4_AGGREGATOR, at this place */
3528 /* this section of code moved here in order to ensure the correct
3529 * *ascending* order of attributes
3531 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3532 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3534 stream_putl (s
, attr
->extra
->aggregator_as
);
3535 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3538 if (((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3539 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
)) ||
3540 (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3542 /* Tunnel Encap attribute */
3543 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3547 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3551 /* Unknown transit attribute. */
3552 if (attr
->extra
&& attr
->extra
->transit
)
3553 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3555 /* Return total size of attribute. */
3556 return stream_get_endp (s
) - cp
;
3560 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3562 unsigned long attrlen_pnt
;
3566 /* Set extended bit always to encode the attribute length as 2 bytes */
3567 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3568 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3570 attrlen_pnt
= stream_get_endp (s
);
3571 stream_putw (s
, 0); /* Length of this attribute. */
3573 /* Convert AFI, SAFI to values for packet. */
3574 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
3576 stream_putw (s
, pkt_afi
);
3577 stream_putc (s
, pkt_safi
);
3583 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3584 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3585 mpls_label_t
*label
, int addpath_encode
,
3586 u_int32_t addpath_tx_id
, struct attr
*attr
)
3588 u_char wlabel
[3] = {0x80, 0x00, 0x00};
3590 if (safi
== SAFI_LABELED_UNICAST
)
3591 label
= (mpls_label_t
*) wlabel
;
3593 return bgp_packet_mpattr_prefix (s
, afi
, safi
, p
, prd
,
3595 addpath_encode
, addpath_tx_id
, attr
);
3599 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3601 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3604 /* Initialization of attribute. */
3606 bgp_attr_init (void)
3619 bgp_attr_finish (void)
3623 community_finish ();
3624 ecommunity_finish ();
3625 lcommunity_finish ();
3631 /* Make attribute packet. */
3633 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3634 struct prefix
*prefix
)
3639 struct aspath
*aspath
;
3640 int addpath_encode
= 0;
3641 u_int32_t addpath_tx_id
= 0;
3643 /* Remember current pointer. */
3644 cp
= stream_get_endp (s
);
3646 /* Place holder of length. */
3649 /* Origin attribute. */
3650 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3651 stream_putc (s
, BGP_ATTR_ORIGIN
);
3653 stream_putc (s
, attr
->origin
);
3655 aspath
= attr
->aspath
;
3657 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3658 stream_putc (s
, BGP_ATTR_AS_PATH
);
3659 aspath_lenp
= stream_get_endp (s
);
3662 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3664 /* Nexthop attribute. */
3665 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3666 if(prefix
!= NULL
&& prefix
->family
!= AF_INET6
)
3668 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3669 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3671 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3674 /* MED attribute. */
3675 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3677 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3678 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3680 stream_putl (s
, attr
->med
);
3683 /* Local preference. */
3684 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3686 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3687 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3689 stream_putl (s
, attr
->local_pref
);
3692 /* Atomic aggregate. */
3693 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3695 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3696 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3701 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3703 assert (attr
->extra
);
3704 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3705 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3707 stream_putl (s
, attr
->extra
->aggregator_as
);
3708 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3711 /* Community attribute. */
3712 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3714 if (attr
->community
->size
* 4 > 255)
3716 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3717 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3718 stream_putw (s
, attr
->community
->size
* 4);
3722 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3723 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3724 stream_putc (s
, attr
->community
->size
* 4);
3726 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3729 /* Large Community attribute. */
3730 if (attr
->extra
&& attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
))
3732 if (attr
->extra
->lcommunity
->size
* 12 > 255)
3734 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3735 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3736 stream_putw (s
, attr
->extra
->lcommunity
->size
* 12);
3740 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3741 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3742 stream_putc (s
, attr
->extra
->lcommunity
->size
* 12);
3745 stream_put (s
, attr
->extra
->lcommunity
->val
, attr
->extra
->lcommunity
->size
* 12);
3748 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3749 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3750 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3751 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3754 struct attr_extra
*attre
= attr
->extra
;
3756 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3757 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3758 sizep
= stream_get_endp (s
);
3761 stream_putc (s
, 0); /* Marker: Attribute length. */
3762 stream_putw(s
, AFI_IP6
); /* AFI */
3763 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3766 stream_putc(s
, attre
->mp_nexthop_len
);
3767 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3768 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3769 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3775 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3777 /* Set MP attribute length. */
3778 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3782 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3784 assert (attr
->extra
);
3786 if (attr
->extra
->label_index
!= BGP_INVALID_LABEL_INDEX
)
3788 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3789 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3790 stream_putc (s
, 10);
3791 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3792 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3793 stream_putc (s
, 0); // reserved
3794 stream_putw (s
, 0); // flags
3795 stream_putl (s
, attr
->extra
->label_index
);
3799 /* Return total size of attribute. */
3800 len
= stream_get_endp (s
) - cp
- 2;
3801 stream_putw_at (s
, cp
, len
);