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
)
276 if (attr
->encap_subtlvs
) {
277 encap_free(attr
->encap_subtlvs
);
278 attr
->encap_subtlvs
= NULL
;
281 if (attr
->vnc_subtlvs
) {
282 encap_free(attr
->vnc_subtlvs
);
283 attr
->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
*a1
, const struct attr
*a2
)
435 return !memcmp(&(a1
->evpn_overlay
), &(a2
->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 /* Shallow copy of an attribute
536 * Though, not so shallow that it doesn't copy the contents
537 * of the attr_extra pointed to by 'extra'
540 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
546 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
549 new->aspath
= aspath_dup(orig
->aspath
);
552 new->community
= community_dup(orig
->community
);
554 if (orig
->ecommunity
)
555 new->ecommunity
= ecommunity_dup(orig
->ecommunity
);
557 new->cluster
= cluster_dup(orig
->cluster
);
559 new->transit
= transit_dup(orig
->transit
);
560 if (orig
->encap_subtlvs
)
561 new->encap_subtlvs
= encap_tlv_dup(orig
->encap_subtlvs
);
563 if (orig
->vnc_subtlvs
)
564 new->vnc_subtlvs
= encap_tlv_dup(orig
->vnc_subtlvs
);
569 bgp_attr_deep_free (struct attr
*attr
)
572 aspath_free(attr
->aspath
);
575 community_free(attr
->community
);
577 if (attr
->ecommunity
)
578 ecommunity_free(&attr
->ecommunity
);
580 cluster_free(attr
->cluster
);
582 transit_free(attr
->transit
);
583 if (attr
->encap_subtlvs
)
584 encap_free(attr
->encap_subtlvs
);
586 if (attr
->vnc_subtlvs
)
587 encap_free(attr
->vnc_subtlvs
);
594 return attrhash
->count
;
598 attr_unknown_count (void)
600 return transit_hash
->count
;
604 attrhash_key_make (void *p
)
606 const struct attr
*attr
= (struct attr
*) p
;
608 #define MIX(val) key = jhash_1word(val, key)
611 MIX(attr
->nexthop
.s_addr
);
613 MIX(attr
->local_pref
);
616 key
+= attr
->nexthop
.s_addr
;
618 key
+= attr
->local_pref
;
620 MIX(attr
->aggregator_as
);
621 MIX(attr
->aggregator_addr
.s_addr
);
623 MIX(attr
->mp_nexthop_global_in
.s_addr
);
624 MIX(attr
->originator_id
.s_addr
);
627 MIX(attr
->label_index
);
630 MIX(aspath_key_make (attr
->aspath
));
632 MIX(community_hash_make (attr
->community
));
634 if (attr
->lcommunity
)
635 MIX(lcommunity_hash_make (attr
->lcommunity
));
636 if (attr
->ecommunity
)
637 MIX(ecommunity_hash_make (attr
->ecommunity
));
639 MIX(cluster_hash_key_make (attr
->cluster
));
641 MIX(transit_hash_key_make (attr
->transit
));
642 if (attr
->encap_subtlvs
)
643 MIX(encap_hash_key_make (attr
->encap_subtlvs
));
645 if (attr
->vnc_subtlvs
)
646 MIX(encap_hash_key_make (attr
->vnc_subtlvs
));
648 MIX(attr
->mp_nexthop_len
);
649 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
650 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
656 attrhash_cmp (const void *p1
, const void *p2
)
658 const struct attr
* attr1
= p1
;
659 const struct attr
* attr2
= p2
;
661 if (attr1
->flag
== attr2
->flag
662 && attr1
->origin
== attr2
->origin
663 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
664 && attr1
->aspath
== attr2
->aspath
665 && attr1
->community
== attr2
->community
666 && attr1
->med
== attr2
->med
667 && attr1
->local_pref
== attr2
->local_pref
668 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
670 if (attr1
->aggregator_as
== attr2
->aggregator_as
671 && attr1
->aggregator_addr
.s_addr
== attr2
->aggregator_addr
.s_addr
672 && attr1
->weight
== attr2
->weight
673 && attr1
->tag
== attr2
->tag
674 && attr1
->label_index
== attr2
->label_index
675 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
676 && IPV6_ADDR_SAME (&attr1
->mp_nexthop_global
, &attr2
->mp_nexthop_global
)
677 && IPV6_ADDR_SAME (&attr1
->mp_nexthop_local
, &attr2
->mp_nexthop_local
)
678 && IPV4_ADDR_SAME (&attr1
->mp_nexthop_global_in
, &attr2
->mp_nexthop_global_in
)
679 && attr1
->ecommunity
== attr2
->ecommunity
680 && attr1
->lcommunity
== attr2
->lcommunity
681 && attr1
->cluster
== attr2
->cluster
682 && attr1
->transit
== attr2
->transit
683 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
684 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
686 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
688 && IPV4_ADDR_SAME (&attr1
->originator_id
, &attr2
->originator_id
)
689 && overlay_index_same(attr1
, attr2
))
699 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
703 * special for hash_clean below
706 attr_vfree (void *attr
)
708 XFREE (MTYPE_ATTR
, attr
);
712 attrhash_finish (void)
714 hash_clean(attrhash
, attr_vfree
);
715 hash_free (attrhash
);
720 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
722 struct attr
*attr
= backet
->data
;
724 vty_outln (vty
, "attr[%ld] nexthop %s", attr
->refcnt
,
725 inet_ntoa(attr
->nexthop
));
729 attr_show_all (struct vty
*vty
)
731 hash_iterate (attrhash
,
732 (void (*)(struct hash_backet
*, void *))
733 attr_show_all_iterator
,
738 bgp_attr_hash_alloc (void *p
)
740 struct attr
* val
= (struct attr
*) p
;
743 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
745 if (val
->encap_subtlvs
) {
746 val
->encap_subtlvs
= NULL
;
749 if (val
->vnc_subtlvs
) {
750 val
->vnc_subtlvs
= NULL
;
757 /* Internet argument attribute. */
759 bgp_attr_intern (struct attr
*attr
)
763 /* Intern referenced strucutre. */
766 if (! attr
->aspath
->refcnt
)
767 attr
->aspath
= aspath_intern (attr
->aspath
);
769 attr
->aspath
->refcnt
++;
773 if (! attr
->community
->refcnt
)
774 attr
->community
= community_intern (attr
->community
);
776 attr
->community
->refcnt
++;
779 if (attr
->ecommunity
)
781 if (! attr
->ecommunity
->refcnt
)
782 attr
->ecommunity
= ecommunity_intern (attr
->ecommunity
);
784 attr
->ecommunity
->refcnt
++;
786 if (attr
->lcommunity
)
788 if (! attr
->lcommunity
->refcnt
)
789 attr
->lcommunity
= lcommunity_intern (attr
->lcommunity
);
791 attr
->lcommunity
->refcnt
++;
795 if (! attr
->cluster
->refcnt
)
796 attr
->cluster
= cluster_intern (attr
->cluster
);
798 attr
->cluster
->refcnt
++;
802 if (! attr
->transit
->refcnt
)
803 attr
->transit
= transit_intern (attr
->transit
);
805 attr
->transit
->refcnt
++;
807 if (attr
->encap_subtlvs
)
809 if (! attr
->encap_subtlvs
->refcnt
)
810 attr
->encap_subtlvs
= encap_intern (attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
812 attr
->encap_subtlvs
->refcnt
++;
815 if (attr
->vnc_subtlvs
)
817 if (! attr
->vnc_subtlvs
->refcnt
)
818 attr
->vnc_subtlvs
= encap_intern (attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
820 attr
->vnc_subtlvs
->refcnt
++;
824 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
831 * Increment the refcount on various structures that attr holds.
832 * Note on usage: call _only_ when the 'attr' object has already
833 * been 'intern'ed and exists in 'attrhash' table. The function
834 * serves to hold a reference to that (real) object.
835 * Note also that the caller can safely call bgp_attr_unintern()
836 * after calling bgp_attr_refcount(). That would release the
837 * reference and could result in a free() of the attr object.
840 bgp_attr_refcount (struct attr
*attr
)
842 /* Intern referenced strucutre. */
844 attr
->aspath
->refcnt
++;
847 attr
->community
->refcnt
++;
849 if (attr
->ecommunity
)
850 attr
->ecommunity
->refcnt
++;
853 attr
->cluster
->refcnt
++;
856 attr
->transit
->refcnt
++;
858 if (attr
->encap_subtlvs
)
859 attr
->encap_subtlvs
->refcnt
++;
862 if (attr
->vnc_subtlvs
)
863 attr
->vnc_subtlvs
->refcnt
++;
870 /* Make network statement's attribute. */
872 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
874 memset (attr
, 0, sizeof (struct attr
));
876 attr
->origin
= origin
;
877 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
878 attr
->aspath
= aspath_empty ();
879 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
880 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
882 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
883 attr
->label
= MPLS_INVALID_LABEL
;
884 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
885 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
890 /* Create the attributes for an aggregate */
892 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
893 struct aspath
*aspath
,
894 struct community
*community
, int as_set
,
895 u_char atomic_aggregate
)
900 memset (&attr
, 0, sizeof (struct attr
));
902 /* Origin attribute. */
903 attr
.origin
= origin
;
904 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
906 /* AS path attribute. */
908 attr
.aspath
= aspath_intern (aspath
);
910 attr
.aspath
= aspath_empty ();
911 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
913 /* Next hop attribute. */
914 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
918 attr
.community
= community
;
919 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
922 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
923 attr
.label
= MPLS_INVALID_LABEL
;
924 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
925 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
926 if (! as_set
|| atomic_aggregate
)
927 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
928 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
929 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
930 attr
.aggregator_as
= bgp
->confed_id
;
932 attr
.aggregator_as
= bgp
->as
;
933 attr
.aggregator_addr
= bgp
->router_id
;
934 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
935 attr
.label
= MPLS_INVALID_LABEL
;
937 new = bgp_attr_intern (&attr
);
939 aspath_unintern (&new->aspath
);
943 /* Unintern just the sub-components of the attr, but not the attr */
945 bgp_attr_unintern_sub (struct attr
*attr
)
947 /* aspath refcount shoud be decrement. */
949 aspath_unintern (&attr
->aspath
);
950 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
953 community_unintern (&attr
->community
);
954 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
956 if (attr
->ecommunity
)
957 ecommunity_unintern (&attr
->ecommunity
);
958 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
960 if (attr
->lcommunity
)
961 lcommunity_unintern (&attr
->lcommunity
);
962 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
));
965 cluster_unintern (attr
->cluster
);
966 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
969 transit_unintern (attr
->transit
);
971 if (attr
->encap_subtlvs
)
972 encap_unintern (&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
975 if (attr
->vnc_subtlvs
)
976 encap_unintern (&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
980 /* Free bgp attribute and aspath. */
982 bgp_attr_unintern (struct attr
**pattr
)
984 struct attr
*attr
= *pattr
;
988 /* Decrement attribute reference. */
993 /* If reference becomes zero then free attribute object. */
994 if (attr
->refcnt
== 0)
996 ret
= hash_release (attrhash
, attr
);
997 assert (ret
!= NULL
);
998 XFREE (MTYPE_ATTR
, attr
);
1002 bgp_attr_unintern_sub (&tmp
);
1006 bgp_attr_flush (struct attr
*attr
)
1008 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
1010 aspath_free (attr
->aspath
);
1011 attr
->aspath
= NULL
;
1013 if (attr
->community
&& ! attr
->community
->refcnt
)
1015 community_free (attr
->community
);
1016 attr
->community
= NULL
;
1019 if (attr
->ecommunity
&& ! attr
->ecommunity
->refcnt
)
1020 ecommunity_free (&attr
->ecommunity
);
1021 if (attr
->lcommunity
&& ! attr
->lcommunity
->refcnt
)
1022 lcommunity_free (&attr
->lcommunity
);
1023 if (attr
->cluster
&& ! attr
->cluster
->refcnt
)
1025 cluster_free (attr
->cluster
);
1026 attr
->cluster
= NULL
;
1028 if (attr
->transit
&& ! attr
->transit
->refcnt
)
1030 transit_free (attr
->transit
);
1031 attr
->transit
= NULL
;
1033 if (attr
->encap_subtlvs
&& ! attr
->encap_subtlvs
->refcnt
)
1035 encap_free(attr
->encap_subtlvs
);
1036 attr
->encap_subtlvs
= NULL
;
1039 if (attr
->vnc_subtlvs
&& ! attr
->vnc_subtlvs
->refcnt
)
1041 encap_free(attr
->vnc_subtlvs
);
1042 attr
->vnc_subtlvs
= NULL
;
1047 /* Implement draft-scudder-idr-optional-transitive behaviour and
1048 * avoid resetting sessions for malformed attributes which are
1049 * are partial/optional and hence where the error likely was not
1050 * introduced by the sending neighbour.
1052 static bgp_attr_parse_ret_t
1053 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
1056 struct peer
*const peer
= args
->peer
;
1057 const u_int8_t flags
= args
->flags
;
1058 /* startp and length must be special-cased, as whether or not to
1059 * send the attribute data with the NOTIFY depends on the error,
1060 * the caller therefore signals this with the seperate length argument
1062 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1064 /* Only relax error handling for eBGP peers */
1065 if (peer
->sort
!= BGP_PEER_EBGP
)
1067 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1068 notify_datap
, length
);
1069 return BGP_ATTR_PARSE_ERROR
;
1073 /* Adjust the stream getp to the end of the attribute, in case we can
1074 * still proceed but the caller hasn't read all the attribute.
1076 stream_set_getp (BGP_INPUT (peer
),
1077 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
1080 switch (args
->type
) {
1081 /* where an attribute is relatively inconsequential, e.g. it does not
1082 * affect route selection, and can be safely ignored, then any such
1083 * attributes which are malformed should just be ignored and the route
1084 * processed as normal.
1086 case BGP_ATTR_AS4_AGGREGATOR
:
1087 case BGP_ATTR_AGGREGATOR
:
1088 case BGP_ATTR_ATOMIC_AGGREGATE
:
1089 return BGP_ATTR_PARSE_PROCEED
;
1091 /* Core attributes, particularly ones which may influence route
1092 * selection, should always cause session resets
1094 case BGP_ATTR_ORIGIN
:
1095 case BGP_ATTR_AS_PATH
:
1096 case BGP_ATTR_NEXT_HOP
:
1097 case BGP_ATTR_MULTI_EXIT_DISC
:
1098 case BGP_ATTR_LOCAL_PREF
:
1099 case BGP_ATTR_COMMUNITIES
:
1100 case BGP_ATTR_ORIGINATOR_ID
:
1101 case BGP_ATTR_CLUSTER_LIST
:
1102 case BGP_ATTR_MP_REACH_NLRI
:
1103 case BGP_ATTR_MP_UNREACH_NLRI
:
1104 case BGP_ATTR_EXT_COMMUNITIES
:
1105 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1106 notify_datap
, length
);
1107 return BGP_ATTR_PARSE_ERROR
;
1110 /* Partial optional attributes that are malformed should not cause
1111 * the whole session to be reset. Instead treat it as a withdrawal
1112 * of the routes, if possible.
1114 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1115 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1116 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1117 return BGP_ATTR_PARSE_WITHDRAW
;
1119 /* default to reset */
1120 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1123 /* Find out what is wrong with the path attribute flag bits and log the error.
1124 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1125 Extended Length. Checking O/T/P bits at once implies, that the attribute
1126 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1127 non-transitive" attribute. */
1129 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1130 u_int8_t desired_flags
/* how RFC says it must be */
1134 u_char real_flags
= args
->flags
;
1135 const u_int8_t attr_code
= args
->type
;
1137 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1138 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1139 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1142 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1143 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1146 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1147 lookup_msg(attr_str
, attr_code
, NULL
),
1148 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1149 attr_flag_str
[i
].str
);
1154 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1155 " (real flags 0x%x, desired 0x%x)",
1156 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1157 real_flags
, desired_flags
);
1161 /* Required flags for attributes. EXTLEN will be masked off when testing,
1162 * as will PARTIAL for optional+transitive attributes.
1164 const u_int8_t attr_flags_values
[] = {
1165 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1166 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1167 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1168 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1169 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1170 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1171 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1172 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1173 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1174 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1175 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1176 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1177 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1178 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1179 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1180 [BGP_ATTR_LARGE_COMMUNITIES
]= BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1181 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1183 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1186 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1188 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1189 const u_int8_t flags
= args
->flags
;
1190 const u_int8_t attr_code
= args
->type
;
1192 /* there may be attributes we don't know about */
1193 if (attr_code
> attr_flags_values_max
)
1195 if (attr_flags_values
[attr_code
] == 0)
1198 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1201 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1202 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1204 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1205 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1209 /* "For well-known attributes and for optional non-transitive attributes,
1210 * the Partial bit MUST be set to 0."
1212 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1214 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1216 zlog_err ("%s well-known attribute "
1217 "must NOT have the partial flag set (%x)",
1218 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1221 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1222 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1224 zlog_err ("%s optional + transitive attribute "
1225 "must NOT have the partial flag set (%x)",
1226 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1231 /* Optional transitive attributes may go through speakers that don't
1232 * reocgnise them and set the Partial bit.
1234 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1235 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1236 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1239 == attr_flags_values
[attr_code
])
1242 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1246 /* Get origin attribute of the update message. */
1247 static bgp_attr_parse_ret_t
1248 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1250 struct peer
*const peer
= args
->peer
;
1251 struct attr
*const attr
= args
->attr
;
1252 const bgp_size_t length
= args
->length
;
1254 /* If any recognized attribute has Attribute Length that conflicts
1255 with the expected length (based on the attribute type code), then
1256 the Error Subcode is set to Attribute Length Error. The Data
1257 field contains the erroneous attribute (type, length and
1261 zlog_err ("Origin attribute length is not one %d", length
);
1262 return bgp_attr_malformed (args
,
1263 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1267 /* Fetch origin attribute. */
1268 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1270 /* If the ORIGIN attribute has an undefined value, then the Error
1271 Subcode is set to Invalid Origin Attribute. The Data field
1272 contains the unrecognized attribute (type, length and value). */
1273 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1274 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1275 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1277 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1278 return bgp_attr_malformed (args
,
1279 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1283 /* Set oring attribute flag. */
1284 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1289 /* Parse AS path information. This function is wrapper of
1292 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1294 struct attr
*const attr
= args
->attr
;
1295 struct peer
*const peer
= args
->peer
;
1296 const bgp_size_t length
= args
->length
;
1299 * peer with AS4 => will get 4Byte ASnums
1300 * otherwise, will get 16 Bit
1302 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1303 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1305 /* In case of IBGP, length will be zero. */
1308 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1309 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1312 /* Set aspath attribute flag. */
1313 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1315 return BGP_ATTR_PARSE_PROCEED
;
1318 static bgp_attr_parse_ret_t
1319 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1321 /* These checks were part of bgp_attr_aspath, but with
1322 * as4 we should to check aspath things when
1323 * aspath synthesizing with as4_path has already taken place.
1324 * Otherwise we check ASPATH and use the synthesized thing, and that is
1326 * So do the checks later, i.e. here
1328 struct bgp
*bgp
= peer
->bgp
;
1329 struct aspath
*aspath
;
1331 /* Confederation sanity check. */
1332 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1333 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1335 zlog_err ("Malformed AS path from %s", peer
->host
);
1336 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1337 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1338 return BGP_ATTR_PARSE_ERROR
;
1341 /* First AS check for EBGP. */
1342 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1344 if (peer
->sort
== BGP_PEER_EBGP
1345 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1347 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1348 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1349 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1350 return BGP_ATTR_PARSE_ERROR
;
1354 /* local-as prepend */
1355 if (peer
->change_local_as
&&
1356 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1358 aspath
= aspath_dup (attr
->aspath
);
1359 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1360 aspath_unintern (&attr
->aspath
);
1361 attr
->aspath
= aspath_intern (aspath
);
1364 return BGP_ATTR_PARSE_PROCEED
;
1367 /* Parse AS4 path information. This function is another wrapper of
1370 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1372 struct peer
*const peer
= args
->peer
;
1373 struct attr
*const attr
= args
->attr
;
1374 const bgp_size_t length
= args
->length
;
1376 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1378 /* In case of IBGP, length will be zero. */
1381 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1382 return bgp_attr_malformed (args
,
1383 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1387 /* Set aspath attribute flag. */
1388 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1390 return BGP_ATTR_PARSE_PROCEED
;
1393 /* Nexthop attribute. */
1394 static bgp_attr_parse_ret_t
1395 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1397 struct peer
*const peer
= args
->peer
;
1398 struct attr
*const attr
= args
->attr
;
1399 const bgp_size_t length
= args
->length
;
1401 in_addr_t nexthop_h
, nexthop_n
;
1403 /* Check nexthop attribute length. */
1406 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1408 return bgp_attr_malformed (args
,
1409 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1413 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1414 attribute must result in a NOTIFICATION message (this is implemented below).
1415 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1416 logged locally (this is implemented somewhere else). The UPDATE message
1417 gets ignored in any of these cases. */
1418 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1419 nexthop_h
= ntohl (nexthop_n
);
1420 if ((IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1421 && !BGP_DEBUG (allow_martians
, ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1423 char buf
[INET_ADDRSTRLEN
];
1424 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1425 zlog_err ("Martian nexthop %s", buf
);
1426 return bgp_attr_malformed (args
,
1427 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1431 attr
->nexthop
.s_addr
= nexthop_n
;
1432 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1434 return BGP_ATTR_PARSE_PROCEED
;
1437 /* MED atrribute. */
1438 static bgp_attr_parse_ret_t
1439 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1441 struct peer
*const peer
= args
->peer
;
1442 struct attr
*const attr
= args
->attr
;
1443 const bgp_size_t length
= args
->length
;
1448 zlog_err ("MED attribute length isn't four [%d]", length
);
1450 return bgp_attr_malformed (args
,
1451 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1455 attr
->med
= stream_getl (peer
->ibuf
);
1457 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1459 return BGP_ATTR_PARSE_PROCEED
;
1462 /* Local preference attribute. */
1463 static bgp_attr_parse_ret_t
1464 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1466 struct peer
*const peer
= args
->peer
;
1467 struct attr
*const attr
= args
->attr
;
1468 const bgp_size_t length
= args
->length
;
1473 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1474 return bgp_attr_malformed (args
,
1475 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1479 /* If it is contained in an UPDATE message that is received from an
1480 external peer, then this attribute MUST be ignored by the
1481 receiving speaker. */
1482 if (peer
->sort
== BGP_PEER_EBGP
)
1484 stream_forward_getp (peer
->ibuf
, length
);
1485 return BGP_ATTR_PARSE_PROCEED
;
1488 attr
->local_pref
= stream_getl (peer
->ibuf
);
1490 /* Set atomic aggregate flag. */
1491 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1493 return BGP_ATTR_PARSE_PROCEED
;
1496 /* Atomic aggregate. */
1498 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1500 struct attr
*const attr
= args
->attr
;
1501 const bgp_size_t length
= args
->length
;
1506 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1507 return bgp_attr_malformed (args
,
1508 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1512 /* Set atomic aggregate flag. */
1513 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1515 return BGP_ATTR_PARSE_PROCEED
;
1518 /* Aggregator attribute */
1520 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1522 struct peer
*const peer
= args
->peer
;
1523 struct attr
*const attr
= args
->attr
;
1524 const bgp_size_t length
= args
->length
;
1528 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1529 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1532 if (length
!= wantedlen
)
1534 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1535 return bgp_attr_malformed (args
,
1536 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1540 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1541 attr
->aggregator_as
= stream_getl (peer
->ibuf
);
1543 attr
->aggregator_as
= stream_getw (peer
->ibuf
);
1544 attr
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1546 /* Set atomic aggregate flag. */
1547 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1549 return BGP_ATTR_PARSE_PROCEED
;
1552 /* New Aggregator attribute */
1553 static bgp_attr_parse_ret_t
1554 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1555 as_t
*as4_aggregator_as
,
1556 struct in_addr
*as4_aggregator_addr
)
1558 struct peer
*const peer
= args
->peer
;
1559 struct attr
*const attr
= args
->attr
;
1560 const bgp_size_t length
= args
->length
;
1564 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1565 return bgp_attr_malformed (args
,
1566 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1570 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1571 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1573 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1575 return BGP_ATTR_PARSE_PROCEED
;
1578 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1580 static bgp_attr_parse_ret_t
1581 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1582 struct attr
*const attr
,
1583 struct aspath
*as4_path
, as_t as4_aggregator
,
1584 struct in_addr
*as4_aggregator_addr
)
1586 int ignore_as4_path
= 0;
1587 struct aspath
*newpath
;
1591 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1592 * checked that all well-known, mandatory attributes were present.
1594 * Can only be a problem with peer itself - hard error
1596 return BGP_ATTR_PARSE_ERROR
;
1599 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1601 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1603 * It is worth a warning though, because the peer really
1604 * should not send them
1606 if (BGP_DEBUG(as4
, AS4
))
1608 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1609 zlog_debug ("[AS4] %s %s AS4_PATH",
1610 peer
->host
, "AS4 capable peer, yet it sent");
1612 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1613 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1614 peer
->host
, "AS4 capable peer, yet it sent");
1617 return BGP_ATTR_PARSE_PROCEED
;
1620 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1621 * because that may override AS4_PATH
1623 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1625 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1628 * if the as_number in aggregator is not AS_TRANS,
1629 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1630 * and the Aggregator shall be taken as
1631 * info on the aggregating node, and the AS_PATH
1632 * shall be taken as the AS_PATH
1634 * the Aggregator shall be ignored and the
1635 * AS4_AGGREGATOR shall be taken as the
1636 * Aggregating node and the AS_PATH is to be
1637 * constructed "as in all other cases"
1639 if (attr
->aggregator_as
!= BGP_AS_TRANS
)
1642 if ( BGP_DEBUG(as4
, AS4
))
1643 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1644 " send AGGREGATOR != AS_TRANS and"
1645 " AS4_AGGREGATOR, so ignore"
1646 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1647 ignore_as4_path
= 1;
1651 /* "New_aggregator shall be taken as aggregator" */
1652 attr
->aggregator_as
= as4_aggregator
;
1653 attr
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1658 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1659 * That is bogus - but reading the conditions
1660 * we have to handle AS4_AGGREGATOR as if it were
1661 * AGGREGATOR in that case
1663 if ( BGP_DEBUG(as4
, AS4
))
1664 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1665 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1666 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1667 attr
->aggregator_as
= as4_aggregator
;
1668 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1669 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1673 /* need to reconcile NEW_AS_PATH and AS_PATH */
1674 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1676 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1677 aspath_unintern (&attr
->aspath
);
1678 attr
->aspath
= aspath_intern (newpath
);
1680 return BGP_ATTR_PARSE_PROCEED
;
1683 /* Community attribute. */
1684 static bgp_attr_parse_ret_t
1685 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1687 struct peer
*const peer
= args
->peer
;
1688 struct attr
*const attr
= args
->attr
;
1689 const bgp_size_t length
= args
->length
;
1693 attr
->community
= NULL
;
1694 return BGP_ATTR_PARSE_PROCEED
;
1698 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1700 /* XXX: fix community_parse to use stream API and remove this */
1701 stream_forward_getp (peer
->ibuf
, length
);
1703 if (!attr
->community
)
1704 return bgp_attr_malformed (args
,
1705 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1708 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1710 return BGP_ATTR_PARSE_PROCEED
;
1713 /* Originator ID attribute. */
1714 static bgp_attr_parse_ret_t
1715 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1717 struct peer
*const peer
= args
->peer
;
1718 struct attr
*const attr
= args
->attr
;
1719 const bgp_size_t length
= args
->length
;
1724 zlog_err ("Bad originator ID length %d", length
);
1726 return bgp_attr_malformed (args
,
1727 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1731 attr
->originator_id
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1733 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1735 return BGP_ATTR_PARSE_PROCEED
;
1738 /* Cluster list attribute. */
1739 static bgp_attr_parse_ret_t
1740 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1742 struct peer
*const peer
= args
->peer
;
1743 struct attr
*const attr
= args
->attr
;
1744 const bgp_size_t length
= args
->length
;
1749 zlog_err ("Bad cluster list length %d", length
);
1751 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1755 attr
->cluster
= cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1757 /* XXX: Fix cluster_parse to use stream API and then remove this */
1758 stream_forward_getp (peer
->ibuf
, length
);
1760 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1762 return BGP_ATTR_PARSE_PROCEED
;
1765 /* Multiprotocol reachability information parse. */
1767 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1768 struct bgp_nlri
*mp_update
)
1772 safi_t pkt_safi
, safi
;
1773 bgp_size_t nlri_len
;
1776 struct peer
*const peer
= args
->peer
;
1777 struct attr
*const attr
= args
->attr
;
1778 const bgp_size_t length
= args
->length
;
1780 /* Set end of packet. */
1781 s
= BGP_INPUT(peer
);
1782 start
= stream_get_getp(s
);
1784 /* safe to read statically sized header? */
1785 #define BGP_MP_REACH_MIN_SIZE 5
1786 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1787 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1789 zlog_info ("%s: %s sent invalid length, %lu",
1790 __func__
, peer
->host
, (unsigned long)length
);
1791 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1794 /* Load AFI, SAFI. */
1795 pkt_afi
= stream_getw (s
);
1796 pkt_safi
= stream_getc (s
);
1798 /* Convert AFI, SAFI to internal values, check. */
1799 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
1801 /* Log if AFI or SAFI is unrecognized. This is not an error unless
1802 * the attribute is otherwise malformed.
1804 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1805 zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1806 peer
->host
, pkt_afi
, pkt_safi
);
1807 return BGP_ATTR_PARSE_ERROR
;
1810 /* Get nexthop length. */
1811 attr
->mp_nexthop_len
= stream_getc (s
);
1813 if (LEN_LEFT
< attr
->mp_nexthop_len
)
1815 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1816 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1817 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1820 /* Nexthop length check. */
1821 switch (attr
->mp_nexthop_len
)
1823 case BGP_ATTR_NHLEN_IPV4
:
1824 stream_get (&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1825 /* Probably needed for RFC 2283 */
1826 if (attr
->nexthop
.s_addr
== 0)
1827 memcpy(&attr
->nexthop
.s_addr
, &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1829 case BGP_ATTR_NHLEN_VPNV4
:
1830 stream_getl (s
); /* RD high */
1831 stream_getl (s
); /* RD low */
1832 stream_get (&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1834 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1835 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1836 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1838 stream_getl (s
); /* RD high */
1839 stream_getl (s
); /* RD low */
1841 stream_get (&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1843 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1844 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1845 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1847 stream_getl (s
); /* RD high */
1848 stream_getl (s
); /* RD low */
1850 stream_get (&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1851 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1853 stream_getl (s
); /* RD high */
1854 stream_getl (s
); /* RD low */
1856 stream_get (&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1857 if (! IN6_IS_ADDR_LINKLOCAL (&attr
->mp_nexthop_local
))
1859 char buf1
[INET6_ADDRSTRLEN
];
1860 char buf2
[INET6_ADDRSTRLEN
];
1862 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1863 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1865 inet_ntop (AF_INET6
, &attr
->mp_nexthop_global
,
1866 buf1
, INET6_ADDRSTRLEN
),
1867 inet_ntop (AF_INET6
, &attr
->mp_nexthop_local
,
1868 buf2
, INET6_ADDRSTRLEN
));
1870 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1874 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1875 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1876 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1881 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1882 __func__
, peer
->host
);
1883 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1888 if ((val
= stream_getc (s
)))
1889 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1893 /* must have nrli_len, what is left of the attribute */
1894 nlri_len
= LEN_LEFT
;
1895 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
1897 zlog_info ("%s: (%s) Failed to read NLRI",
1898 __func__
, peer
->host
);
1899 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1902 mp_update
->afi
= afi
;
1903 mp_update
->safi
= safi
;
1904 mp_update
->nlri
= stream_pnt (s
);
1905 mp_update
->length
= nlri_len
;
1907 stream_forward_getp (s
, nlri_len
);
1909 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
1911 return BGP_ATTR_PARSE_PROCEED
;
1915 /* Multiprotocol unreachable parse */
1917 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
1918 struct bgp_nlri
*mp_withdraw
)
1923 safi_t pkt_safi
, safi
;
1924 u_int16_t withdraw_len
;
1925 struct peer
*const peer
= args
->peer
;
1926 struct attr
*const attr
= args
->attr
;
1927 const bgp_size_t length
= args
->length
;
1931 #define BGP_MP_UNREACH_MIN_SIZE 3
1932 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1933 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1935 pkt_afi
= stream_getw (s
);
1936 pkt_safi
= stream_getc (s
);
1938 /* Convert AFI, SAFI to internal values, check. */
1939 if (bgp_map_afi_safi_iana2int (pkt_afi
, pkt_safi
, &afi
, &safi
))
1941 /* Log if AFI or SAFI is unrecognized. This is not an error unless
1942 * the attribute is otherwise malformed.
1944 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1945 zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
1946 peer
->host
, pkt_afi
, pkt_safi
);
1947 return BGP_ATTR_PARSE_ERROR
;
1950 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1952 mp_withdraw
->afi
= afi
;
1953 mp_withdraw
->safi
= safi
;
1954 mp_withdraw
->nlri
= stream_pnt (s
);
1955 mp_withdraw
->length
= withdraw_len
;
1957 stream_forward_getp (s
, withdraw_len
);
1959 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
1961 return BGP_ATTR_PARSE_PROCEED
;
1964 /* Large Community attribute. */
1965 static bgp_attr_parse_ret_t
1966 bgp_attr_large_community (struct bgp_attr_parser_args
*args
)
1968 struct peer
*const peer
= args
->peer
;
1969 struct attr
*const attr
= args
->attr
;
1970 const bgp_size_t length
= args
->length
;
1973 * Large community follows new attribute format.
1977 attr
->lcommunity
= NULL
;
1978 /* Empty extcomm doesn't seem to be invalid per se */
1979 return BGP_ATTR_PARSE_PROCEED
;
1982 attr
->lcommunity
= lcommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
1983 /* XXX: fix ecommunity_parse to use stream API */
1984 stream_forward_getp (peer
->ibuf
, length
);
1986 if (!attr
->lcommunity
)
1987 return bgp_attr_malformed (args
,
1988 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1991 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
);
1993 return BGP_ATTR_PARSE_PROCEED
;
1996 /* Extended Community attribute. */
1997 static bgp_attr_parse_ret_t
1998 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
2000 struct peer
*const peer
= args
->peer
;
2001 struct attr
*const attr
= args
->attr
;
2002 const bgp_size_t length
= args
->length
;
2007 attr
->ecommunity
= NULL
;
2008 /* Empty extcomm doesn't seem to be invalid per se */
2009 return BGP_ATTR_PARSE_PROCEED
;
2012 attr
->ecommunity
= ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2013 /* XXX: fix ecommunity_parse to use stream API */
2014 stream_forward_getp (peer
->ibuf
, length
);
2016 if (!attr
->ecommunity
)
2017 return bgp_attr_malformed (args
,
2018 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2021 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
2023 /* Extract MAC mobility sequence number, if any. */
2024 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum (attr
, &sticky
);
2025 attr
->sticky
= sticky
;
2027 return BGP_ATTR_PARSE_PROCEED
;
2030 /* Parse Tunnel Encap attribute in an UPDATE */
2034 struct peer
*peer
, /* IN */
2035 bgp_size_t length
, /* IN: attr's length field */
2036 struct attr
*attr
, /* IN: caller already allocated */
2037 u_char flag
, /* IN: attr's flags field */
2041 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2042 uint16_t tunneltype
= 0;
2044 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2046 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2047 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
2049 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
2050 bgp_notify_send_with_data (peer
,
2051 BGP_NOTIFY_UPDATE_ERR
,
2052 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2057 if (BGP_ATTR_ENCAP
== type
) {
2058 /* read outer TLV type and length */
2059 uint16_t tlv_length
;
2062 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2063 bgp_notify_send_with_data(peer
,
2064 BGP_NOTIFY_UPDATE_ERR
,
2065 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2069 tunneltype
= stream_getw (BGP_INPUT (peer
));
2070 tlv_length
= stream_getw (BGP_INPUT (peer
));
2073 if (tlv_length
!= length
) {
2074 zlog_info ("%s: tlv_length(%d) != length(%d)",
2075 __func__
, tlv_length
, length
);
2079 while (length
>= 4) {
2080 uint16_t subtype
= 0;
2081 uint16_t sublength
= 0;
2082 struct bgp_attr_encap_subtlv
*tlv
;
2084 if (BGP_ATTR_ENCAP
== type
) {
2085 subtype
= stream_getc (BGP_INPUT (peer
));
2086 sublength
= stream_getc (BGP_INPUT (peer
));
2090 subtype
= stream_getw (BGP_INPUT (peer
));
2091 sublength
= stream_getw (BGP_INPUT (peer
));
2096 if (sublength
> length
) {
2097 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2099 bgp_notify_send_with_data (peer
,
2100 BGP_NOTIFY_UPDATE_ERR
,
2101 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2106 /* alloc and copy sub-tlv */
2107 /* TBD make sure these are freed when attributes are released */
2108 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
2109 tlv
->type
= subtype
;
2110 tlv
->length
= sublength
;
2111 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2112 length
-= sublength
;
2114 /* attach tlv to encap chain */
2115 if (BGP_ATTR_ENCAP
== type
) {
2116 for (stlv_last
= attr
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
2117 stlv_last
= stlv_last
->next
);
2119 stlv_last
->next
= tlv
;
2121 attr
->encap_subtlvs
= tlv
;
2125 for (stlv_last
= attr
->vnc_subtlvs
; stlv_last
&& stlv_last
->next
;
2126 stlv_last
= stlv_last
->next
);
2128 stlv_last
->next
= tlv
;
2130 attr
->vnc_subtlvs
= tlv
;
2134 stlv_last
->next
= tlv
;
2137 if (BGP_ATTR_ENCAP
== type
) {
2138 attr
->encap_tunneltype
= tunneltype
;
2142 /* spurious leftover data */
2143 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2144 bgp_notify_send_with_data (peer
,
2145 BGP_NOTIFY_UPDATE_ERR
,
2146 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2154 /* Prefix SID attribute
2155 * draft-ietf-idr-bgp-prefix-sid-05
2157 static bgp_attr_parse_ret_t
2158 bgp_attr_prefix_sid (struct bgp_attr_parser_args
*args
, struct bgp_nlri
*mp_update
)
2160 struct peer
*const peer
= args
->peer
;
2161 struct attr
*const attr
= args
->attr
;
2164 u_int32_t label_index
;
2165 struct in6_addr ipv6_sid
;
2166 u_int32_t srgb_base
;
2167 u_int32_t srgb_range
;
2170 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
);
2172 type
= stream_getc (peer
->ibuf
);
2173 length
= stream_getw (peer
->ibuf
);
2175 if (type
== BGP_PREFIX_SID_LABEL_INDEX
)
2177 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
)
2179 zlog_err ("Prefix SID label index length is %d instead of %d", length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2180 return bgp_attr_malformed (args
,
2181 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2185 /* Ignore flags and reserved */
2186 stream_getc (peer
->ibuf
);
2187 stream_getw (peer
->ibuf
);
2189 /* Fetch the label index and see if it is valid. */
2190 label_index
= stream_getl (peer
->ibuf
);
2191 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2192 return bgp_attr_malformed (args
,
2193 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2196 /* Store label index; subsequently, we'll check on address-family */
2197 attr
->label_index
= label_index
;
2200 * Ignore the Label index attribute unless received for labeled-unicast
2203 if (!mp_update
->length
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2204 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2207 /* Placeholder code for the IPv6 SID type */
2208 else if (type
== BGP_PREFIX_SID_IPV6
)
2210 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
)
2212 zlog_err ("Prefix SID IPv6 length is %d instead of %d", length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2213 return bgp_attr_malformed (args
,
2214 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2218 /* Ignore reserved */
2219 stream_getc (peer
->ibuf
);
2220 stream_getw (peer
->ibuf
);
2222 stream_get (&ipv6_sid
, peer
->ibuf
, 16);
2225 /* Placeholder code for the Originator SRGB type */
2226 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
)
2229 stream_getw (peer
->ibuf
);
2233 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)
2235 zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2236 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2237 return bgp_attr_malformed (args
,
2238 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2242 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2244 for (int i
= 0; i
< srgb_count
; i
++)
2246 stream_get (&srgb_base
, peer
->ibuf
, 3);
2247 stream_get (&srgb_range
, peer
->ibuf
, 3);
2251 return BGP_ATTR_PARSE_PROCEED
;
2254 /* BGP unknown attribute treatment. */
2255 static bgp_attr_parse_ret_t
2256 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2258 bgp_size_t total
= args
->total
;
2259 struct transit
*transit
;
2260 struct peer
*const peer
= args
->peer
;
2261 struct attr
*const attr
= args
->attr
;
2262 u_char
*const startp
= args
->startp
;
2263 const u_char type
= args
->type
;
2264 const u_char flag
= args
->flags
;
2265 const bgp_size_t length
= args
->length
;
2267 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2268 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2269 peer
->host
, type
, length
);
2271 /* Forward read pointer of input stream. */
2272 stream_forward_getp (peer
->ibuf
, length
);
2274 /* If any of the mandatory well-known attributes are not recognized,
2275 then the Error Subcode is set to Unrecognized Well-known
2276 Attribute. The Data field contains the unrecognized attribute
2277 (type, length and value). */
2278 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2280 return bgp_attr_malformed (args
,
2281 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2285 /* Unrecognized non-transitive optional attributes must be quietly
2286 ignored and not passed along to other BGP peers. */
2287 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2288 return BGP_ATTR_PARSE_PROCEED
;
2290 /* If a path with recognized transitive optional attribute is
2291 accepted and passed along to other BGP peers and the Partial bit
2292 in the Attribute Flags octet is set to 1 by some previous AS, it
2293 is not set back to 0 by the current AS. */
2294 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2296 /* Store transitive attribute to the end of attr->transit. */
2298 attr
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2300 transit
= attr
->transit
;
2303 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2304 transit
->length
+ total
);
2306 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2308 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2309 transit
->length
+= total
;
2311 return BGP_ATTR_PARSE_PROCEED
;
2314 /* Well-known attribute check. */
2316 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2320 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2322 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2323 return BGP_ATTR_PARSE_PROCEED
;
2325 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2326 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2327 are present, it should. Check for any other attribute being present
2330 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2331 return BGP_ATTR_PARSE_PROCEED
;
2333 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2334 type
= BGP_ATTR_ORIGIN
;
2336 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2337 type
= BGP_ATTR_AS_PATH
;
2339 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2340 * NLRI is empty. We can't easily check NLRI empty here though.
2342 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2343 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2344 type
= BGP_ATTR_NEXT_HOP
;
2346 if (peer
->sort
== BGP_PEER_IBGP
2347 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2348 type
= BGP_ATTR_LOCAL_PREF
;
2352 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2353 lookup_msg(attr_str
, type
, NULL
));
2354 bgp_notify_send_with_data (peer
,
2355 BGP_NOTIFY_UPDATE_ERR
,
2356 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2358 return BGP_ATTR_PARSE_ERROR
;
2360 return BGP_ATTR_PARSE_PROCEED
;
2363 /* Read attribute of update packet. This function is called from
2364 bgp_update_receive() in bgp_packet.c. */
2365 bgp_attr_parse_ret_t
2366 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2367 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2373 u_char
*startp
, *endp
;
2375 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2376 /* we need the as4_path only until we have synthesized the as_path with it */
2377 /* same goes for as4_aggregator */
2378 struct aspath
*as4_path
= NULL
;
2379 as_t as4_aggregator
= 0;
2380 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2382 /* Initialize bitmap. */
2383 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2385 /* End pointer of BGP attribute. */
2386 endp
= BGP_INPUT_PNT (peer
) + size
;
2388 /* Get attributes to the end of attribute length. */
2389 while (BGP_INPUT_PNT (peer
) < endp
)
2391 /* Check remaining length check.*/
2392 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2394 /* XXX warning: long int format, int arg (arg 5) */
2395 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2397 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2399 bgp_notify_send (peer
,
2400 BGP_NOTIFY_UPDATE_ERR
,
2401 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2402 return BGP_ATTR_PARSE_ERROR
;
2405 /* Fetch attribute flag and type. */
2406 startp
= BGP_INPUT_PNT (peer
);
2407 /* "The lower-order four bits of the Attribute Flags octet are
2408 unused. They MUST be zero when sent and MUST be ignored when
2410 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2411 type
= stream_getc (BGP_INPUT (peer
));
2413 /* Check whether Extended-Length applies and is in bounds */
2414 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2415 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2417 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2419 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2421 bgp_notify_send (peer
,
2422 BGP_NOTIFY_UPDATE_ERR
,
2423 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2424 return BGP_ATTR_PARSE_ERROR
;
2427 /* Check extended attribue length bit. */
2428 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2429 length
= stream_getw (BGP_INPUT (peer
));
2431 length
= stream_getc (BGP_INPUT (peer
));
2433 /* If any attribute appears more than once in the UPDATE
2434 message, then the Error Subcode is set to Malformed Attribute
2437 if (CHECK_BITMAP (seen
, type
))
2439 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2442 bgp_notify_send (peer
,
2443 BGP_NOTIFY_UPDATE_ERR
,
2444 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2445 return BGP_ATTR_PARSE_ERROR
;
2448 /* Set type to bitmap to check duplicate attribute. `type' is
2449 unsigned char so it never overflow bitmap range. */
2451 SET_BITMAP (seen
, type
);
2453 /* Overflow check. */
2454 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2456 if (attr_endp
> endp
)
2458 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
);
2459 bgp_notify_send_with_data (peer
,
2460 BGP_NOTIFY_UPDATE_ERR
,
2461 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2462 startp
, attr_endp
- startp
);
2463 return BGP_ATTR_PARSE_ERROR
;
2466 struct bgp_attr_parser_args attr_args
= {
2473 .total
= attr_endp
- startp
,
2477 /* If any recognized attribute has Attribute Flags that conflict
2478 with the Attribute Type Code, then the Error Subcode is set to
2479 Attribute Flags Error. The Data field contains the erroneous
2480 attribute (type, length and value). */
2481 if (bgp_attr_flag_invalid (&attr_args
))
2483 bgp_attr_parse_ret_t ret
;
2484 ret
= bgp_attr_malformed (&attr_args
,
2485 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2487 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2492 /* OK check attribute and store it's value. */
2495 case BGP_ATTR_ORIGIN
:
2496 ret
= bgp_attr_origin (&attr_args
);
2498 case BGP_ATTR_AS_PATH
:
2499 ret
= bgp_attr_aspath (&attr_args
);
2501 case BGP_ATTR_AS4_PATH
:
2502 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2504 case BGP_ATTR_NEXT_HOP
:
2505 ret
= bgp_attr_nexthop (&attr_args
);
2507 case BGP_ATTR_MULTI_EXIT_DISC
:
2508 ret
= bgp_attr_med (&attr_args
);
2510 case BGP_ATTR_LOCAL_PREF
:
2511 ret
= bgp_attr_local_pref (&attr_args
);
2513 case BGP_ATTR_ATOMIC_AGGREGATE
:
2514 ret
= bgp_attr_atomic (&attr_args
);
2516 case BGP_ATTR_AGGREGATOR
:
2517 ret
= bgp_attr_aggregator (&attr_args
);
2519 case BGP_ATTR_AS4_AGGREGATOR
:
2520 ret
= bgp_attr_as4_aggregator (&attr_args
,
2522 &as4_aggregator_addr
);
2524 case BGP_ATTR_COMMUNITIES
:
2525 ret
= bgp_attr_community (&attr_args
);
2527 case BGP_ATTR_LARGE_COMMUNITIES
:
2528 ret
= bgp_attr_large_community (&attr_args
);
2530 case BGP_ATTR_ORIGINATOR_ID
:
2531 ret
= bgp_attr_originator_id (&attr_args
);
2533 case BGP_ATTR_CLUSTER_LIST
:
2534 ret
= bgp_attr_cluster_list (&attr_args
);
2536 case BGP_ATTR_MP_REACH_NLRI
:
2537 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2539 case BGP_ATTR_MP_UNREACH_NLRI
:
2540 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2542 case BGP_ATTR_EXT_COMMUNITIES
:
2543 ret
= bgp_attr_ext_communities (&attr_args
);
2548 case BGP_ATTR_ENCAP
:
2549 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2551 case BGP_ATTR_PREFIX_SID
:
2552 ret
= bgp_attr_prefix_sid (&attr_args
, mp_update
);
2555 ret
= bgp_attr_unknown (&attr_args
);
2559 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2561 bgp_notify_send (peer
,
2562 BGP_NOTIFY_UPDATE_ERR
,
2563 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2564 ret
= BGP_ATTR_PARSE_ERROR
;
2567 /* If hard error occured immediately return to the caller. */
2568 if (ret
== BGP_ATTR_PARSE_ERROR
)
2570 zlog_warn ("%s: Attribute %s, parse error",
2572 lookup_msg(attr_str
, type
, NULL
));
2574 aspath_unintern (&as4_path
);
2577 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2580 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2582 lookup_msg(attr_str
, type
, NULL
));
2584 aspath_unintern (&as4_path
);
2588 /* Check the fetched length. */
2589 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2591 zlog_warn ("%s: BGP attribute %s, fetch error",
2592 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2593 bgp_notify_send (peer
,
2594 BGP_NOTIFY_UPDATE_ERR
,
2595 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2597 aspath_unintern (&as4_path
);
2598 return BGP_ATTR_PARSE_ERROR
;
2602 /* Check final read pointer is same as end pointer. */
2603 if (BGP_INPUT_PNT (peer
) != endp
)
2605 zlog_warn ("%s: BGP attribute %s, length mismatch",
2606 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2607 bgp_notify_send (peer
,
2608 BGP_NOTIFY_UPDATE_ERR
,
2609 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2611 aspath_unintern (&as4_path
);
2612 return BGP_ATTR_PARSE_ERROR
;
2615 /* Check all mandatory well-known attributes are present */
2617 bgp_attr_parse_ret_t ret
;
2618 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2621 aspath_unintern (&as4_path
);
2627 * At this place we can see whether we got AS4_PATH and/or
2628 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2629 * We can not do this before we've read all attributes because
2630 * the as4 handling does not say whether AS4_PATH has to be sent
2631 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2632 * in relationship to AGGREGATOR.
2633 * So, to be defensive, we are not relying on any order and read
2634 * all attributes first, including these 32bit ones, and now,
2635 * afterwards, we look what and if something is to be done for as4.
2637 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2640 /* actually... this doesn't ever return failure currently, but
2641 * better safe than sorry */
2642 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2643 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2644 as4_aggregator
, &as4_aggregator_addr
))
2646 bgp_notify_send (peer
,
2647 BGP_NOTIFY_UPDATE_ERR
,
2648 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2650 aspath_unintern (&as4_path
);
2651 return BGP_ATTR_PARSE_ERROR
;
2654 /* At this stage, we have done all fiddling with as4, and the
2655 * resulting info is in attr->aggregator resp. attr->aspath
2656 * so we can chuck as4_aggregator and as4_path alltogether in
2657 * order to save memory
2661 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2662 /* The flag that we got this is still there, but that does not
2667 * The "rest" of the code does nothing with as4_aggregator.
2668 * there is no memory attached specifically which is not part
2670 * so ignoring just means do nothing.
2673 * Finally do the checks on the aspath we did not do yet
2674 * because we waited for a potentially synthesized aspath.
2676 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2678 ret
= bgp_attr_aspath_check (peer
, attr
);
2679 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2682 /* Finally intern unknown attribute. */
2684 attr
->transit
= transit_intern (attr
->transit
);
2685 if (attr
->encap_subtlvs
)
2686 attr
->encap_subtlvs
= encap_intern (attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2688 if (attr
->vnc_subtlvs
)
2689 attr
->vnc_subtlvs
= encap_intern (attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2692 return BGP_ATTR_PARSE_PROCEED
;
2696 bgp_packet_mpattr_start (struct stream
*s
, struct peer
*peer
,
2697 afi_t afi
, safi_t safi
,
2698 struct bpacket_attr_vec_arr
*vecarr
,
2706 /* Set extended bit always to encode the attribute length as 2 bytes */
2707 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2708 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2709 sizep
= stream_get_endp (s
);
2710 stream_putw (s
, 0); /* Marker: Attribute length. */
2713 /* Convert AFI, SAFI to values for packet. */
2714 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
2716 stream_putw (s
, pkt_afi
); /* AFI */
2717 stream_putc (s
, pkt_safi
); /* SAFI */
2720 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
2722 nh_afi
= peer_cap_enhe (peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
2724 else if (safi
== SAFI_LABELED_UNICAST
)
2727 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
2730 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2737 case SAFI_MULTICAST
:
2738 case SAFI_LABELED_UNICAST
:
2740 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2743 stream_putc (s
, 12);
2744 stream_putl (s
, 0); /* RD = 0, per RFC */
2746 stream_put (s
, &attr
->mp_nexthop_global_in
, 4);
2751 stream_put (s
, &attr
->mp_nexthop_global_in
, 4);
2761 case SAFI_MULTICAST
:
2762 case SAFI_LABELED_UNICAST
:
2765 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2766 stream_putc (s
, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2767 stream_put (s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2768 stream_put (s
, &attr
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2770 stream_putc (s
, IPV6_MAX_BYTELEN
);
2771 stream_put (s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2777 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2778 stream_putc (s
, 24);
2779 stream_putl (s
, 0); /* RD = 0, per RFC */
2781 stream_put (s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2782 } else if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2783 stream_putc (s
, 48);
2784 stream_putl (s
, 0); /* RD = 0, per RFC */
2786 stream_put (s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2787 stream_putl (s
, 0); /* RD = 0, per RFC */
2789 stream_put (s
, &attr
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2794 stream_putc (s
, IPV6_MAX_BYTELEN
);
2795 stream_put (s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2802 zlog_err ("Bad nexthop when sening to %s, AFI %u SAFI %u nhlen %d",
2803 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
2813 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2814 struct prefix
*p
, struct prefix_rd
*prd
,
2815 mpls_label_t
*label
, int addpath_encode
,
2816 u_int32_t addpath_tx_id
, struct attr
*attr
)
2818 if (safi
== SAFI_MPLS_VPN
)
2821 stream_putl(s
, addpath_tx_id
);
2822 /* Label, RD, Prefix write. */
2823 stream_putc (s
, p
->prefixlen
+ 88);
2824 stream_put (s
, label
, BGP_LABEL_BYTES
);
2825 stream_put (s
, prd
->val
, 8);
2826 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2828 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2830 /* EVPN prefix - contents depend on type */
2831 bgp_evpn_encode_prefix (s
, p
, prd
, label
, attr
,
2832 addpath_encode
, addpath_tx_id
);
2834 else if (safi
== SAFI_LABELED_UNICAST
)
2836 /* Prefix write with label. */
2837 stream_put_labeled_prefix(s
, p
, label
);
2840 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
2844 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
2846 int size
= PSIZE (p
->prefixlen
);
2847 if (safi
== SAFI_MPLS_VPN
)
2849 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2850 size
+= 232; // TODO: Maximum possible for type-2, type-3 and type-5
2855 * Encodes the tunnel encapsulation attribute,
2856 * and with ENABLE_BGP_VNC the VNC attribute which uses
2857 * almost the same TLV format
2860 bgp_packet_mpattr_tea(
2867 unsigned int attrlenfield
= 0;
2868 unsigned int attrhdrlen
= 0;
2869 struct bgp_attr_encap_subtlv
*subtlvs
;
2870 struct bgp_attr_encap_subtlv
*st
;
2871 const char *attrname
;
2874 (attrtype
== BGP_ATTR_ENCAP
&&
2875 (!attr
->encap_tunneltype
||
2876 attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
2880 case BGP_ATTR_ENCAP
:
2881 attrname
= "Tunnel Encap";
2882 subtlvs
= attr
->encap_subtlvs
;
2883 if (subtlvs
== NULL
) /* nothing to do */
2886 * The tunnel encap attr has an "outer" tlv.
2888 * L = total length of subtlvs,
2889 * V = concatenated subtlvs.
2891 attrlenfield
= 2 + 2; /* T + L */
2892 attrhdrlen
= 1 + 1; /* subTLV T + L */
2898 subtlvs
= attr
->vnc_subtlvs
;
2899 if (subtlvs
== NULL
) /* nothing to do */
2901 attrlenfield
= 0; /* no outer T + L */
2902 attrhdrlen
= 2 + 2; /* subTLV T + L */
2910 /* compute attr length */
2911 for (st
= subtlvs
; st
; st
= st
->next
) {
2912 attrlenfield
+= (attrhdrlen
+ st
->length
);
2915 if (attrlenfield
> 0xffff) {
2916 zlog_info ("%s attribute is too long (length=%d), can't send it",
2922 if (attrlenfield
> 0xff) {
2923 /* 2-octet length field */
2925 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2926 stream_putc (s
, attrtype
);
2927 stream_putw (s
, attrlenfield
& 0xffff);
2929 /* 1-octet length field */
2930 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
2931 stream_putc (s
, attrtype
);
2932 stream_putc (s
, attrlenfield
& 0xff);
2935 if (attrtype
== BGP_ATTR_ENCAP
) {
2936 /* write outer T+L */
2937 stream_putw(s
, attr
->encap_tunneltype
);
2938 stream_putw(s
, attrlenfield
- 4);
2941 /* write each sub-tlv */
2942 for (st
= subtlvs
; st
; st
= st
->next
) {
2943 if (attrtype
== BGP_ATTR_ENCAP
) {
2944 stream_putc (s
, st
->type
);
2945 stream_putc (s
, st
->length
);
2948 stream_putw (s
, st
->type
);
2949 stream_putw (s
, st
->length
);
2952 stream_put (s
, st
->value
, st
->length
);
2957 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
2959 /* Set MP attribute length. Don't count the (2) bytes used to encode
2961 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
2964 /* Make attribute packet. */
2966 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
2967 struct stream
*s
, struct attr
*attr
,
2968 struct bpacket_attr_vec_arr
*vecarr
,
2969 struct prefix
*p
, afi_t afi
, safi_t safi
,
2970 struct peer
*from
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2972 u_int32_t addpath_tx_id
)
2975 size_t aspath_sizep
;
2976 struct aspath
*aspath
;
2977 int send_as4_path
= 0;
2978 int send_as4_aggregator
= 0;
2979 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2984 /* Remember current pointer. */
2985 cp
= stream_get_endp (s
);
2987 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
2988 !peer_cap_enhe(peer
, afi
, safi
)))
2990 size_t mpattrlen_pos
= 0;
2992 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
, vecarr
, attr
);
2993 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
2994 addpath_encode
, addpath_tx_id
, attr
);
2995 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2998 /* Origin attribute. */
2999 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3000 stream_putc (s
, BGP_ATTR_ORIGIN
);
3002 stream_putc (s
, attr
->origin
);
3004 /* AS path attribute. */
3006 /* If remote-peer is EBGP */
3007 if (peer
->sort
== BGP_PEER_EBGP
3008 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
3009 || attr
->aspath
->segments
== NULL
)
3010 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
3012 aspath
= aspath_dup (attr
->aspath
);
3014 /* Even though we may not be configured for confederations we may have
3015 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3016 aspath
= aspath_delete_confed_seq (aspath
);
3018 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
3020 /* Stuff our path CONFED_ID on the front */
3021 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
3025 if (peer
->change_local_as
) {
3026 /* If replace-as is specified, we only use the change_local_as when
3027 advertising routes. */
3028 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
3029 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3031 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
3033 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
3037 else if (peer
->sort
== BGP_PEER_CONFED
)
3039 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
3040 aspath
= aspath_dup (attr
->aspath
);
3041 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
3044 aspath
= attr
->aspath
;
3046 /* If peer is not AS4 capable, then:
3047 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3048 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
3049 * types are in it (i.e. exclude them if they are there)
3050 * AND do this only if there is at least one asnum > 65535 in the path!
3051 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
3052 * all ASnums > 65535 to BGP_AS_TRANS
3055 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3056 stream_putc (s
, BGP_ATTR_AS_PATH
);
3057 aspath_sizep
= stream_get_endp (s
);
3059 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
3061 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3064 if (!use32bit
&& aspath_has_as4 (aspath
))
3065 send_as4_path
= 1; /* we'll do this later, at the correct place */
3067 /* Nexthop attribute. */
3068 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
, afi
, safi
))
3070 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
3072 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3073 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3074 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3076 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3078 else if (peer_cap_enhe(from
, afi
, safi
))
3081 * Likely this is the case when an IPv4 prefix was received with
3082 * Extended Next-hop capability and now being advertised to
3084 * Setting the mandatory (ipv4) next-hop attribute here to enable
3085 * implicit next-hop self with correct (ipv4 address family).
3087 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3088 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3089 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
3091 stream_put_ipv4 (s
, 0);
3095 /* MED attribute. */
3096 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
3099 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3100 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3102 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
3105 /* Local preference. */
3106 if (peer
->sort
== BGP_PEER_IBGP
||
3107 peer
->sort
== BGP_PEER_CONFED
)
3109 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3110 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3112 stream_putl (s
, attr
->local_pref
);
3115 /* Atomic aggregate. */
3116 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3118 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3119 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3124 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3126 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3127 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3128 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3132 /* AS4 capable peer */
3134 stream_putl (s
, attr
->aggregator_as
);
3138 /* 2-byte AS peer */
3141 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3142 if ( attr
->aggregator_as
> 65535 )
3144 stream_putw (s
, BGP_AS_TRANS
);
3146 /* we have to send AS4_AGGREGATOR, too.
3147 * we'll do that later in order to send attributes in ascending
3150 send_as4_aggregator
= 1;
3153 stream_putw (s
, (u_int16_t
) attr
->aggregator_as
);
3155 stream_put_ipv4 (s
, attr
->aggregator_addr
.s_addr
);
3158 /* Community attribute. */
3159 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3160 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
3162 if (attr
->community
->size
* 4 > 255)
3164 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3165 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3166 stream_putw (s
, attr
->community
->size
* 4);
3170 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3171 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3172 stream_putc (s
, attr
->community
->size
* 4);
3174 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3178 * Large Community attribute.
3180 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_LARGE_COMMUNITY
)
3181 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
)))
3183 if (attr
->lcommunity
->size
* 12 > 255)
3185 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3186 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3187 stream_putw (s
, attr
->lcommunity
->size
* 12);
3191 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3192 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3193 stream_putc (s
, attr
->lcommunity
->size
* 12);
3195 stream_put (s
, attr
->lcommunity
->val
, attr
->lcommunity
->size
* 12);
3198 /* Route Reflector. */
3199 if (peer
->sort
== BGP_PEER_IBGP
3201 && from
->sort
== BGP_PEER_IBGP
)
3203 /* Originator ID. */
3204 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3205 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
3208 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3209 stream_put_in_addr (s
, &attr
->originator_id
);
3211 stream_put_in_addr (s
, &from
->remote_id
);
3214 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3215 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
3219 stream_putc (s
, attr
->cluster
->length
+ 4);
3220 /* If this peer configuration's parent BGP has cluster_id. */
3221 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3222 stream_put_in_addr (s
, &bgp
->cluster_id
);
3224 stream_put_in_addr (s
, &bgp
->router_id
);
3225 stream_put (s
, attr
->cluster
->list
,
3226 attr
->cluster
->length
);
3231 /* If this peer configuration's parent BGP has cluster_id. */
3232 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3233 stream_put_in_addr (s
, &bgp
->cluster_id
);
3235 stream_put_in_addr (s
, &bgp
->router_id
);
3239 /* Extended Communities attribute. */
3240 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3241 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
3243 if (peer
->sort
== BGP_PEER_IBGP
3244 || peer
->sort
== BGP_PEER_CONFED
)
3246 if (attr
->ecommunity
->size
* 8 > 255)
3248 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3249 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3250 stream_putw (s
, attr
->ecommunity
->size
* 8);
3254 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3255 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3256 stream_putc (s
, attr
->ecommunity
->size
* 8);
3258 stream_put (s
, attr
->ecommunity
->val
, attr
->ecommunity
->size
* 8);
3264 int ecom_tr_size
= 0;
3267 for (i
= 0; i
< attr
->ecommunity
->size
; i
++)
3269 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3272 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3280 if (ecom_tr_size
* 8 > 255)
3282 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3283 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3284 stream_putw (s
, ecom_tr_size
* 8);
3288 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3289 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3290 stream_putc (s
, ecom_tr_size
* 8);
3293 for (i
= 0; i
< attr
->ecommunity
->size
; i
++)
3295 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3298 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3301 stream_put (s
, pnt
, 8);
3307 /* Label index attribute. */
3308 if (safi
== SAFI_LABELED_UNICAST
)
3310 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3312 u_int32_t label_index
;
3314 label_index
= attr
->label_index
;
3316 if (label_index
!= BGP_INVALID_LABEL_INDEX
)
3318 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3319 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3320 stream_putc (s
, 10);
3321 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3322 stream_putw (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3323 stream_putc (s
, 0); // reserved
3324 stream_putw (s
, 0); // flags
3325 stream_putl (s
, label_index
);
3330 if ( send_as4_path
)
3332 /* If the peer is NOT As4 capable, AND */
3333 /* there are ASnums > 65535 in path THEN
3334 * give out AS4_PATH */
3336 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3338 * Hm, I wonder... confederation things *should* only be at
3339 * the beginning of an aspath, right? Then we should use
3340 * aspath_delete_confed_seq for this, because it is already
3342 * Folks, talk to me: what is reasonable here!?
3344 aspath
= aspath_delete_confed_seq (aspath
);
3346 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3347 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3348 aspath_sizep
= stream_get_endp (s
);
3350 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3353 if (aspath
!= attr
->aspath
)
3354 aspath_free (aspath
);
3356 if ( send_as4_aggregator
)
3358 /* send AS4_AGGREGATOR, at this place */
3359 /* this section of code moved here in order to ensure the correct
3360 * *ascending* order of attributes
3362 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3363 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3365 stream_putl (s
, attr
->aggregator_as
);
3366 stream_put_ipv4 (s
, attr
->aggregator_addr
.s_addr
);
3369 if (((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3370 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
)) ||
3371 (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3373 /* Tunnel Encap attribute */
3374 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3378 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3382 /* Unknown transit attribute. */
3384 stream_put (s
, attr
->transit
->val
, attr
->transit
->length
);
3386 /* Return total size of attribute. */
3387 return stream_get_endp (s
) - cp
;
3391 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3393 unsigned long attrlen_pnt
;
3397 /* Set extended bit always to encode the attribute length as 2 bytes */
3398 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3399 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3401 attrlen_pnt
= stream_get_endp (s
);
3402 stream_putw (s
, 0); /* Length of this attribute. */
3404 /* Convert AFI, SAFI to values for packet. */
3405 bgp_map_afi_safi_int2iana (afi
, safi
, &pkt_afi
, &pkt_safi
);
3407 stream_putw (s
, pkt_afi
);
3408 stream_putc (s
, pkt_safi
);
3414 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3415 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3416 mpls_label_t
*label
, int addpath_encode
,
3417 u_int32_t addpath_tx_id
, struct attr
*attr
)
3419 u_char wlabel
[3] = {0x80, 0x00, 0x00};
3421 if (safi
== SAFI_LABELED_UNICAST
)
3422 label
= (mpls_label_t
*) wlabel
;
3424 return bgp_packet_mpattr_prefix (s
, afi
, safi
, p
, prd
,
3426 addpath_encode
, addpath_tx_id
, attr
);
3430 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3432 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3435 /* Initialization of attribute. */
3437 bgp_attr_init (void)
3450 bgp_attr_finish (void)
3454 community_finish ();
3455 ecommunity_finish ();
3456 lcommunity_finish ();
3462 /* Make attribute packet. */
3464 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3465 struct prefix
*prefix
)
3470 struct aspath
*aspath
;
3471 int addpath_encode
= 0;
3472 u_int32_t addpath_tx_id
= 0;
3474 /* Remember current pointer. */
3475 cp
= stream_get_endp (s
);
3477 /* Place holder of length. */
3480 /* Origin attribute. */
3481 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3482 stream_putc (s
, BGP_ATTR_ORIGIN
);
3484 stream_putc (s
, attr
->origin
);
3486 aspath
= attr
->aspath
;
3488 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3489 stream_putc (s
, BGP_ATTR_AS_PATH
);
3490 aspath_lenp
= stream_get_endp (s
);
3493 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3495 /* Nexthop attribute. */
3496 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3497 if(prefix
!= NULL
&& prefix
->family
!= AF_INET6
)
3499 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3500 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3502 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3505 /* MED attribute. */
3506 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3508 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3509 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3511 stream_putl (s
, attr
->med
);
3514 /* Local preference. */
3515 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3517 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3518 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3520 stream_putl (s
, attr
->local_pref
);
3523 /* Atomic aggregate. */
3524 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3526 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3527 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3532 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3534 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3535 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3537 stream_putl (s
, attr
->aggregator_as
);
3538 stream_put_ipv4 (s
, attr
->aggregator_addr
.s_addr
);
3541 /* Community attribute. */
3542 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3544 if (attr
->community
->size
* 4 > 255)
3546 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3547 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3548 stream_putw (s
, attr
->community
->size
* 4);
3552 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3553 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3554 stream_putc (s
, attr
->community
->size
* 4);
3556 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3559 /* Large Community attribute. */
3560 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES
))
3562 if (attr
->lcommunity
->size
* 12 > 255)
3564 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3565 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3566 stream_putw (s
, attr
->lcommunity
->size
* 12);
3570 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3571 stream_putc (s
, BGP_ATTR_LARGE_COMMUNITIES
);
3572 stream_putc (s
, attr
->lcommunity
->size
* 12);
3575 stream_put (s
, attr
->lcommunity
->val
, attr
->lcommunity
->size
* 12);
3578 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3579 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&&
3580 (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3581 attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3585 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3586 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3587 sizep
= stream_get_endp (s
);
3590 stream_putc (s
, 0); /* Marker: Attribute length. */
3591 stream_putw(s
, AFI_IP6
); /* AFI */
3592 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3595 stream_putc(s
, attr
->mp_nexthop_len
);
3596 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3597 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3598 stream_put(s
, &attr
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3604 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3606 /* Set MP attribute length. */
3607 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3611 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID
))
3613 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
)
3615 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3616 stream_putc (s
, BGP_ATTR_PREFIX_SID
);
3617 stream_putc (s
, 10);
3618 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX
);
3619 stream_putc (s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3620 stream_putc (s
, 0); // reserved
3621 stream_putw (s
, 0); // flags
3622 stream_putl (s
, attr
->label_index
);
3626 /* Return total size of attribute. */
3627 len
= stream_get_endp (s
) - cp
- 2;
3628 stream_putw_at (s
, cp
, len
);