1 /* BGP attributes management routines.
2 Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 This file is part of GNU Zebra.
6 GNU Zebra is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 GNU Zebra is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_packet.h"
43 #include "bgpd/bgp_ecommunity.h"
44 #include "bgpd/bgp_updgrp.h"
45 #include "bgpd/bgp_encap_types.h"
47 # include "bgpd/rfapi/bgp_rfapi_cfg.h"
48 # include "bgp_encap_types.h"
49 # include "bgp_vnc_types.h"
52 /* Attribute strings for logging. */
53 static const struct message attr_str
[] =
55 { BGP_ATTR_ORIGIN
, "ORIGIN" },
56 { BGP_ATTR_AS_PATH
, "AS_PATH" },
57 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
58 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
59 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
60 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
61 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
62 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
63 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
64 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
65 { BGP_ATTR_DPA
, "DPA" },
66 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
67 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
68 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
69 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
70 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
71 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
72 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
73 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
74 { BGP_ATTR_ENCAP
, "ENCAP" },
76 { BGP_ATTR_VNC
, "VNC" },
79 static const int attr_str_max
= array_size(attr_str
);
81 static const struct message attr_flag_str
[] =
83 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
84 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
85 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
86 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
87 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
90 static struct hash
*cluster_hash
;
93 cluster_hash_alloc (void *p
)
95 const struct cluster_list
*val
= (const struct cluster_list
*) p
;
96 struct cluster_list
*cluster
;
98 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
99 cluster
->length
= val
->length
;
103 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
104 memcpy (cluster
->list
, val
->list
, val
->length
);
107 cluster
->list
= NULL
;
114 /* Cluster list related functions. */
115 static struct cluster_list
*
116 cluster_parse (struct in_addr
* pnt
, int length
)
118 struct cluster_list tmp
;
119 struct cluster_list
*cluster
;
124 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
130 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
134 for (i
= 0; i
< cluster
->length
/ 4; i
++)
135 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
141 cluster_hash_key_make (void *p
)
143 const struct cluster_list
*cluster
= p
;
145 return jhash(cluster
->list
, cluster
->length
, 0);
149 cluster_hash_cmp (const void *p1
, const void *p2
)
151 const struct cluster_list
* cluster1
= p1
;
152 const struct cluster_list
* cluster2
= p2
;
154 return (cluster1
->length
== cluster2
->length
&&
155 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
159 cluster_free (struct cluster_list
*cluster
)
162 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
163 XFREE (MTYPE_CLUSTER
, cluster
);
166 static struct cluster_list
*
167 cluster_dup (struct cluster_list
*cluster
)
169 struct cluster_list
*new;
171 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
172 new->length
= cluster
->length
;
176 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
177 memcpy (new->list
, cluster
->list
, cluster
->length
);
185 static struct cluster_list
*
186 cluster_intern (struct cluster_list
*cluster
)
188 struct cluster_list
*find
;
190 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
197 cluster_unintern (struct cluster_list
*cluster
)
202 if (cluster
->refcnt
== 0)
204 hash_release (cluster_hash
, cluster
);
205 cluster_free (cluster
);
212 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
216 cluster_finish (void)
218 hash_clean (cluster_hash
, (void (*)(void *))cluster_free
);
219 hash_free (cluster_hash
);
223 static struct hash
*encap_hash
= NULL
;
225 static struct hash
*vnc_hash
= NULL
;
228 struct bgp_attr_encap_subtlv
*
229 encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
231 struct bgp_attr_encap_subtlv
*new;
232 struct bgp_attr_encap_subtlv
*tail
;
233 struct bgp_attr_encap_subtlv
*p
;
235 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
236 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
238 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
241 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
244 memcpy(tail
, p
, size
);
252 encap_free(struct bgp_attr_encap_subtlv
*p
)
254 struct bgp_attr_encap_subtlv
*next
;
258 XFREE(MTYPE_ENCAP_TLV
, p
);
264 bgp_attr_flush_encap(struct attr
*attr
)
266 if (!attr
|| !attr
->extra
)
269 if (attr
->extra
->encap_subtlvs
) {
270 encap_free(attr
->extra
->encap_subtlvs
);
271 attr
->extra
->encap_subtlvs
= NULL
;
274 if (attr
->extra
->vnc_subtlvs
) {
275 encap_free(attr
->extra
->vnc_subtlvs
);
276 attr
->extra
->vnc_subtlvs
= NULL
;
282 * Compare encap sub-tlv chains
287 * This algorithm could be made faster if needed
290 encap_same(struct bgp_attr_encap_subtlv
*h1
, struct bgp_attr_encap_subtlv
*h2
)
292 struct bgp_attr_encap_subtlv
*p
;
293 struct bgp_attr_encap_subtlv
*q
;
297 if (h1
== NULL
|| h2
== NULL
)
300 for (p
= h1
; p
; p
= p
->next
) {
301 for (q
= h2
; q
; q
= q
->next
) {
302 if ((p
->type
== q
->type
) &&
303 (p
->length
== q
->length
) &&
304 !memcmp(p
->value
, q
->value
, p
->length
)) {
313 for (p
= h2
; p
; p
= p
->next
) {
314 for (q
= h1
; q
; q
= q
->next
) {
315 if ((p
->type
== q
->type
) &&
316 (p
->length
== q
->length
) &&
317 !memcmp(p
->value
, q
->value
, p
->length
)) {
330 encap_hash_alloc (void *p
)
332 /* Encap structure is already allocated. */
344 static struct bgp_attr_encap_subtlv
*
345 encap_intern (struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
347 struct bgp_attr_encap_subtlv
*find
;
348 struct hash
*hash
= encap_hash
;
350 if (type
== VNC_SUBTLV_TYPE
)
354 find
= hash_get (hash
, encap
, encap_hash_alloc
);
363 encap_unintern (struct bgp_attr_encap_subtlv
**encapp
, encap_subtlv_type type
)
365 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
369 if (encap
->refcnt
== 0)
371 struct hash
*hash
= encap_hash
;
373 if (type
== VNC_SUBTLV_TYPE
)
376 hash_release (hash
, encap
);
383 encap_hash_key_make (void *p
)
385 const struct bgp_attr_encap_subtlv
* encap
= p
;
387 return jhash(encap
->value
, encap
->length
, 0);
391 encap_hash_cmp (const void *p1
, const void *p2
)
393 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
394 (struct bgp_attr_encap_subtlv
*)p2
);
400 encap_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
402 vnc_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
409 hash_clean (encap_hash
, (void (*)(void *))encap_free
);
410 hash_free (encap_hash
);
413 hash_clean (vnc_hash
, (void (*)(void *))encap_free
);
414 hash_free (vnc_hash
);
419 /* Unknown transit attribute. */
420 static struct hash
*transit_hash
;
423 transit_free (struct transit
*transit
)
426 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
427 XFREE (MTYPE_TRANSIT
, transit
);
430 static struct transit
*
431 transit_dup (struct transit
*transit
)
435 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
436 new->length
= transit
->length
;
439 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
440 memcpy (new->val
, transit
->val
, transit
->length
);
449 transit_hash_alloc (void *p
)
451 /* Transit structure is already allocated. */
455 static struct transit
*
456 transit_intern (struct transit
*transit
)
458 struct transit
*find
;
460 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
462 transit_free (transit
);
469 transit_unintern (struct transit
*transit
)
474 if (transit
->refcnt
== 0)
476 hash_release (transit_hash
, transit
);
477 transit_free (transit
);
482 transit_hash_key_make (void *p
)
484 const struct transit
* transit
= p
;
486 return jhash(transit
->val
, transit
->length
, 0);
490 transit_hash_cmp (const void *p1
, const void *p2
)
492 const struct transit
* transit1
= p1
;
493 const struct transit
* transit2
= p2
;
495 return (transit1
->length
== transit2
->length
&&
496 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
502 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
506 transit_finish (void)
508 hash_clean (transit_hash
, (void (*)(void *))transit_free
);
509 hash_free (transit_hash
);
513 /* Attribute hash routines. */
514 static struct hash
*attrhash
;
516 static struct attr_extra
*
517 bgp_attr_extra_new (void)
519 return XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
523 bgp_attr_extra_free (struct attr
*attr
)
527 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
533 bgp_attr_extra_get (struct attr
*attr
)
536 attr
->extra
= bgp_attr_extra_new();
540 /* Shallow copy of an attribute
541 * Though, not so shallow that it doesn't copy the contents
542 * of the attr_extra pointed to by 'extra'
545 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
547 struct attr_extra
*extra
= new->extra
;
550 /* if caller provided attr_extra space, use it in any case.
552 * This is neccesary even if orig->extra equals NULL, because otherwise
553 * memory may be later allocated on the heap by bgp_attr_extra_get.
555 * That memory would eventually be leaked, because the caller must not
556 * call bgp_attr_extra_free if he provided attr_extra on the stack.
561 memset(new->extra
, 0, sizeof(struct attr_extra
));
563 *new->extra
= *orig
->extra
;
566 else if (orig
->extra
)
568 new->extra
= bgp_attr_extra_new();
569 *new->extra
= *orig
->extra
;
574 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
577 new->aspath
= aspath_dup(orig
->aspath
);
580 new->community
= community_dup(orig
->community
);
584 if (orig
->extra
->ecommunity
)
585 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
586 if (orig
->extra
->cluster
)
587 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
588 if (orig
->extra
->transit
)
589 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
590 if (orig
->extra
->encap_subtlvs
)
591 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
593 if (orig
->extra
->vnc_subtlvs
)
594 new->extra
->vnc_subtlvs
= encap_tlv_dup(orig
->extra
->vnc_subtlvs
);
600 bgp_attr_deep_free (struct attr
*attr
)
603 aspath_free(attr
->aspath
);
606 community_free(attr
->community
);
610 if (attr
->extra
->ecommunity
)
611 ecommunity_free(&attr
->extra
->ecommunity
);
612 if (attr
->extra
->cluster
)
613 cluster_free(attr
->extra
->cluster
);
614 if (attr
->extra
->transit
)
615 transit_free(attr
->extra
->transit
);
616 if (attr
->extra
->encap_subtlvs
)
617 encap_free(attr
->extra
->encap_subtlvs
);
619 if (attr
->extra
->vnc_subtlvs
)
620 encap_free(attr
->extra
->vnc_subtlvs
);
628 return attrhash
->count
;
632 attr_unknown_count (void)
634 return transit_hash
->count
;
638 attrhash_key_make (void *p
)
640 const struct attr
*attr
= (struct attr
*) p
;
641 const struct attr_extra
*extra
= attr
->extra
;
643 #define MIX(val) key = jhash_1word(val, key)
646 MIX(attr
->nexthop
.s_addr
);
648 MIX(attr
->local_pref
);
651 key
+= attr
->nexthop
.s_addr
;
653 key
+= attr
->local_pref
;
657 MIX(extra
->aggregator_as
);
658 MIX(extra
->aggregator_addr
.s_addr
);
660 MIX(extra
->mp_nexthop_global_in
.s_addr
);
661 MIX(extra
->originator_id
.s_addr
);
666 MIX(aspath_key_make (attr
->aspath
));
668 MIX(community_hash_make (attr
->community
));
672 if (extra
->ecommunity
)
673 MIX(ecommunity_hash_make (extra
->ecommunity
));
675 MIX(cluster_hash_key_make (extra
->cluster
));
677 MIX(transit_hash_key_make (extra
->transit
));
678 if (extra
->encap_subtlvs
)
679 MIX(encap_hash_key_make (extra
->encap_subtlvs
));
681 if (extra
->vnc_subtlvs
)
682 MIX(encap_hash_key_make (extra
->vnc_subtlvs
));
685 MIX(extra
->mp_nexthop_len
);
686 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
687 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
688 #endif /* HAVE_IPV6 */
695 attrhash_cmp (const void *p1
, const void *p2
)
697 const struct attr
* attr1
= p1
;
698 const struct attr
* attr2
= p2
;
700 if (attr1
->flag
== attr2
->flag
701 && attr1
->origin
== attr2
->origin
702 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
703 && attr1
->aspath
== attr2
->aspath
704 && attr1
->community
== attr2
->community
705 && attr1
->med
== attr2
->med
706 && attr1
->local_pref
== attr2
->local_pref
707 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
709 const struct attr_extra
*ae1
= attr1
->extra
;
710 const struct attr_extra
*ae2
= attr2
->extra
;
713 && ae1
->aggregator_as
== ae2
->aggregator_as
714 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
715 && ae1
->weight
== ae2
->weight
716 && ae1
->tag
== ae2
->tag
718 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
719 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
720 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
721 #endif /* HAVE_IPV6 */
722 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
723 && ae1
->ecommunity
== ae2
->ecommunity
724 && ae1
->cluster
== ae2
->cluster
725 && ae1
->transit
== ae2
->transit
726 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
727 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
729 && encap_same(ae1
->vnc_subtlvs
, ae2
->vnc_subtlvs
)
731 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
))
735 /* neither attribute has extra attributes, so they're same */
745 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
749 * special for hash_clean below
752 attr_vfree (void *attr
)
754 bgp_attr_extra_free ((struct attr
*)attr
);
755 XFREE (MTYPE_ATTR
, attr
);
759 attrhash_finish (void)
761 hash_clean(attrhash
, attr_vfree
);
762 hash_free (attrhash
);
767 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
769 struct attr
*attr
= backet
->data
;
771 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
772 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
776 attr_show_all (struct vty
*vty
)
778 hash_iterate (attrhash
,
779 (void (*)(struct hash_backet
*, void *))
780 attr_show_all_iterator
,
785 bgp_attr_hash_alloc (void *p
)
787 const struct attr
* val
= (const struct attr
*) p
;
790 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
794 attr
->extra
= bgp_attr_extra_new ();
795 *attr
->extra
= *val
->extra
;
796 if (val
->extra
->encap_subtlvs
) {
797 val
->extra
->encap_subtlvs
= NULL
;
800 if (val
->extra
->vnc_subtlvs
) {
801 val
->extra
->vnc_subtlvs
= NULL
;
809 /* Internet argument attribute. */
811 bgp_attr_intern (struct attr
*attr
)
815 /* Intern referenced strucutre. */
818 if (! attr
->aspath
->refcnt
)
819 attr
->aspath
= aspath_intern (attr
->aspath
);
821 attr
->aspath
->refcnt
++;
825 if (! attr
->community
->refcnt
)
826 attr
->community
= community_intern (attr
->community
);
828 attr
->community
->refcnt
++;
832 struct attr_extra
*attre
= attr
->extra
;
834 if (attre
->ecommunity
)
836 if (! attre
->ecommunity
->refcnt
)
837 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
839 attre
->ecommunity
->refcnt
++;
844 if (! attre
->cluster
->refcnt
)
845 attre
->cluster
= cluster_intern (attre
->cluster
);
847 attre
->cluster
->refcnt
++;
851 if (! attre
->transit
->refcnt
)
852 attre
->transit
= transit_intern (attre
->transit
);
854 attre
->transit
->refcnt
++;
856 if (attre
->encap_subtlvs
)
858 if (! attre
->encap_subtlvs
->refcnt
)
859 attre
->encap_subtlvs
= encap_intern (attre
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
861 attre
->encap_subtlvs
->refcnt
++;
864 if (attre
->vnc_subtlvs
)
866 if (! attre
->vnc_subtlvs
->refcnt
)
867 attre
->vnc_subtlvs
= encap_intern (attre
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
869 attre
->vnc_subtlvs
->refcnt
++;
874 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
881 * Increment the refcount on various structures that attr holds.
882 * Note on usage: call _only_ when the 'attr' object has already
883 * been 'intern'ed and exists in 'attrhash' table. The function
884 * serves to hold a reference to that (real) object.
885 * Note also that the caller can safely call bgp_attr_unintern()
886 * after calling bgp_attr_refcount(). That would release the
887 * reference and could result in a free() of the attr object.
890 bgp_attr_refcount (struct attr
*attr
)
892 /* Intern referenced strucutre. */
894 attr
->aspath
->refcnt
++;
897 attr
->community
->refcnt
++;
901 struct attr_extra
*attre
= attr
->extra
;
902 if (attre
->ecommunity
)
903 attre
->ecommunity
->refcnt
++;
906 attre
->cluster
->refcnt
++;
909 attre
->transit
->refcnt
++;
911 if (attre
->encap_subtlvs
)
912 attre
->encap_subtlvs
->refcnt
++;
915 if (attre
->vnc_subtlvs
)
916 attre
->vnc_subtlvs
->refcnt
++;
923 /* Make network statement's attribute. */
925 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
927 memset (attr
, 0, sizeof (struct attr
));
928 bgp_attr_extra_get (attr
);
930 attr
->origin
= origin
;
931 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
932 attr
->aspath
= aspath_empty ();
933 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
934 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
935 attr
->extra
->tag
= 0;
936 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
938 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
945 /* Make network statement's attribute. */
947 bgp_attr_default_intern (u_char origin
)
952 memset (&attr
, 0, sizeof (struct attr
));
953 bgp_attr_extra_get (&attr
);
955 bgp_attr_default_set(&attr
, origin
);
957 new = bgp_attr_intern (&attr
);
958 bgp_attr_extra_free (&attr
);
960 aspath_unintern (&new->aspath
);
964 /* Create the attributes for an aggregate */
966 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
967 struct aspath
*aspath
,
968 struct community
*community
, int as_set
,
969 u_char atomic_aggregate
)
973 struct attr_extra attre
;
975 memset (&attr
, 0, sizeof (struct attr
));
976 memset (&attre
, 0, sizeof (struct attr_extra
));
979 /* Origin attribute. */
980 attr
.origin
= origin
;
981 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
983 /* AS path attribute. */
985 attr
.aspath
= aspath_intern (aspath
);
987 attr
.aspath
= aspath_empty ();
988 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
990 /* Next hop attribute. */
991 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
995 attr
.community
= community
;
996 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
999 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1001 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1003 if (! as_set
|| atomic_aggregate
)
1004 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1005 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1006 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1007 attre
.aggregator_as
= bgp
->confed_id
;
1009 attre
.aggregator_as
= bgp
->as
;
1010 attre
.aggregator_addr
= bgp
->router_id
;
1012 new = bgp_attr_intern (&attr
);
1014 aspath_unintern (&new->aspath
);
1018 /* Unintern just the sub-components of the attr, but not the attr */
1020 bgp_attr_unintern_sub (struct attr
*attr
)
1022 /* aspath refcount shoud be decrement. */
1024 aspath_unintern (&attr
->aspath
);
1025 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
1027 if (attr
->community
)
1028 community_unintern (&attr
->community
);
1029 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
1033 if (attr
->extra
->ecommunity
)
1034 ecommunity_unintern (&attr
->extra
->ecommunity
);
1035 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
1037 if (attr
->extra
->cluster
)
1038 cluster_unintern (attr
->extra
->cluster
);
1039 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
1041 if (attr
->extra
->transit
)
1042 transit_unintern (attr
->extra
->transit
);
1044 if (attr
->extra
->encap_subtlvs
)
1045 encap_unintern (&attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1048 if (attr
->extra
->vnc_subtlvs
)
1049 encap_unintern (&attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1054 /* Free bgp attribute and aspath. */
1056 bgp_attr_unintern (struct attr
**pattr
)
1058 struct attr
*attr
= *pattr
;
1061 struct attr_extra tmp_extra
;
1063 /* Decrement attribute reference. */
1070 tmp
.extra
= &tmp_extra
;
1071 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
1074 /* If reference becomes zero then free attribute object. */
1075 if (attr
->refcnt
== 0)
1077 ret
= hash_release (attrhash
, attr
);
1078 assert (ret
!= NULL
);
1079 bgp_attr_extra_free (attr
);
1080 XFREE (MTYPE_ATTR
, attr
);
1084 bgp_attr_unintern_sub (&tmp
);
1088 bgp_attr_flush (struct attr
*attr
)
1090 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
1092 aspath_free (attr
->aspath
);
1093 attr
->aspath
= NULL
;
1095 if (attr
->community
&& ! attr
->community
->refcnt
)
1097 community_free (attr
->community
);
1098 attr
->community
= NULL
;
1102 struct attr_extra
*attre
= attr
->extra
;
1104 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
1105 ecommunity_free (&attre
->ecommunity
);
1106 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
1108 cluster_free (attre
->cluster
);
1109 attre
->cluster
= NULL
;
1111 if (attre
->transit
&& ! attre
->transit
->refcnt
)
1113 transit_free (attre
->transit
);
1114 attre
->transit
= NULL
;
1116 if (attre
->encap_subtlvs
&& ! attre
->encap_subtlvs
->refcnt
)
1118 encap_free(attre
->encap_subtlvs
);
1119 attre
->encap_subtlvs
= NULL
;
1122 if (attre
->vnc_subtlvs
&& ! attre
->vnc_subtlvs
->refcnt
)
1124 encap_free(attre
->vnc_subtlvs
);
1125 attre
->vnc_subtlvs
= NULL
;
1131 /* Implement draft-scudder-idr-optional-transitive behaviour and
1132 * avoid resetting sessions for malformed attributes which are
1133 * are partial/optional and hence where the error likely was not
1134 * introduced by the sending neighbour.
1136 static bgp_attr_parse_ret_t
1137 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
1140 struct peer
*const peer
= args
->peer
;
1141 const u_int8_t flags
= args
->flags
;
1142 /* startp and length must be special-cased, as whether or not to
1143 * send the attribute data with the NOTIFY depends on the error,
1144 * the caller therefore signals this with the seperate length argument
1146 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1148 /* Only relax error handling for eBGP peers */
1149 if (peer
->sort
!= BGP_PEER_EBGP
)
1151 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1152 notify_datap
, length
);
1153 return BGP_ATTR_PARSE_ERROR
;
1157 /* Adjust the stream getp to the end of the attribute, in case we can
1158 * still proceed but the caller hasn't read all the attribute.
1160 stream_set_getp (BGP_INPUT (peer
),
1161 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
1164 switch (args
->type
) {
1165 /* where an attribute is relatively inconsequential, e.g. it does not
1166 * affect route selection, and can be safely ignored, then any such
1167 * attributes which are malformed should just be ignored and the route
1168 * processed as normal.
1170 case BGP_ATTR_AS4_AGGREGATOR
:
1171 case BGP_ATTR_AGGREGATOR
:
1172 case BGP_ATTR_ATOMIC_AGGREGATE
:
1173 return BGP_ATTR_PARSE_PROCEED
;
1175 /* Core attributes, particularly ones which may influence route
1176 * selection, should always cause session resets
1178 case BGP_ATTR_ORIGIN
:
1179 case BGP_ATTR_AS_PATH
:
1180 case BGP_ATTR_NEXT_HOP
:
1181 case BGP_ATTR_MULTI_EXIT_DISC
:
1182 case BGP_ATTR_LOCAL_PREF
:
1183 case BGP_ATTR_COMMUNITIES
:
1184 case BGP_ATTR_ORIGINATOR_ID
:
1185 case BGP_ATTR_CLUSTER_LIST
:
1186 case BGP_ATTR_MP_REACH_NLRI
:
1187 case BGP_ATTR_MP_UNREACH_NLRI
:
1188 case BGP_ATTR_EXT_COMMUNITIES
:
1189 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1190 notify_datap
, length
);
1191 return BGP_ATTR_PARSE_ERROR
;
1194 /* Partial optional attributes that are malformed should not cause
1195 * the whole session to be reset. Instead treat it as a withdrawal
1196 * of the routes, if possible.
1198 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1199 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1200 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1201 return BGP_ATTR_PARSE_WITHDRAW
;
1203 /* default to reset */
1204 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1207 /* Find out what is wrong with the path attribute flag bits and log the error.
1208 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1209 Extended Length. Checking O/T/P bits at once implies, that the attribute
1210 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1211 non-transitive" attribute. */
1213 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1214 u_int8_t desired_flags
/* how RFC says it must be */
1218 u_char real_flags
= args
->flags
;
1219 const u_int8_t attr_code
= args
->type
;
1221 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1222 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1223 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1226 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1227 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1230 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1231 LOOKUP (attr_str
, attr_code
),
1232 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1233 attr_flag_str
[i
].str
);
1238 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1239 " (real flags 0x%x, desired 0x%x)",
1240 __func__
, LOOKUP (attr_str
, attr_code
),
1241 real_flags
, desired_flags
);
1245 /* Required flags for attributes. EXTLEN will be masked off when testing,
1246 * as will PARTIAL for optional+transitive attributes.
1248 const u_int8_t attr_flags_values
[] = {
1249 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1250 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1251 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1252 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1253 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1254 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1255 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1256 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1257 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1258 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1259 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1260 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1261 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1262 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1263 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1265 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1268 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1270 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1271 const u_int8_t flags
= args
->flags
;
1272 const u_int8_t attr_code
= args
->type
;
1274 /* there may be attributes we don't know about */
1275 if (attr_code
> attr_flags_values_max
)
1277 if (attr_flags_values
[attr_code
] == 0)
1280 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1283 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1284 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1286 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1287 LOOKUP (attr_str
, attr_code
), flags
);
1291 /* "For well-known attributes and for optional non-transitive attributes,
1292 * the Partial bit MUST be set to 0."
1294 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1296 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1298 zlog_err ("%s well-known attribute "
1299 "must NOT have the partial flag set (%x)",
1300 LOOKUP (attr_str
, attr_code
), flags
);
1303 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1304 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1306 zlog_err ("%s optional + transitive attribute "
1307 "must NOT have the partial flag set (%x)",
1308 LOOKUP (attr_str
, attr_code
), flags
);
1313 /* Optional transitive attributes may go through speakers that don't
1314 * reocgnise them and set the Partial bit.
1316 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1317 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1318 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1321 == attr_flags_values
[attr_code
])
1324 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1328 /* Get origin attribute of the update message. */
1329 static bgp_attr_parse_ret_t
1330 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1332 struct peer
*const peer
= args
->peer
;
1333 struct attr
*const attr
= args
->attr
;
1334 const bgp_size_t length
= args
->length
;
1336 /* If any recognized attribute has Attribute Length that conflicts
1337 with the expected length (based on the attribute type code), then
1338 the Error Subcode is set to Attribute Length Error. The Data
1339 field contains the erroneous attribute (type, length and
1343 zlog_err ("Origin attribute length is not one %d", length
);
1344 return bgp_attr_malformed (args
,
1345 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1349 /* Fetch origin attribute. */
1350 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1352 /* If the ORIGIN attribute has an undefined value, then the Error
1353 Subcode is set to Invalid Origin Attribute. The Data field
1354 contains the unrecognized attribute (type, length and value). */
1355 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1356 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1357 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1359 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1360 return bgp_attr_malformed (args
,
1361 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1365 /* Set oring attribute flag. */
1366 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1371 /* Parse AS path information. This function is wrapper of
1374 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1376 struct attr
*const attr
= args
->attr
;
1377 struct peer
*const peer
= args
->peer
;
1378 const bgp_size_t length
= args
->length
;
1381 * peer with AS4 => will get 4Byte ASnums
1382 * otherwise, will get 16 Bit
1384 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1385 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1387 /* In case of IBGP, length will be zero. */
1390 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1391 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1394 /* Set aspath attribute flag. */
1395 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1397 return BGP_ATTR_PARSE_PROCEED
;
1400 static bgp_attr_parse_ret_t
1401 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1403 /* These checks were part of bgp_attr_aspath, but with
1404 * as4 we should to check aspath things when
1405 * aspath synthesizing with as4_path has already taken place.
1406 * Otherwise we check ASPATH and use the synthesized thing, and that is
1408 * So do the checks later, i.e. here
1410 struct bgp
*bgp
= peer
->bgp
;
1411 struct aspath
*aspath
;
1413 /* Confederation sanity check. */
1414 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1415 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1417 zlog_err ("Malformed AS path from %s", peer
->host
);
1418 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1419 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1420 return BGP_ATTR_PARSE_ERROR
;
1423 /* First AS check for EBGP. */
1424 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1426 if (peer
->sort
== BGP_PEER_EBGP
1427 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1429 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1430 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1431 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1432 return BGP_ATTR_PARSE_ERROR
;
1436 /* local-as prepend */
1437 if (peer
->change_local_as
&&
1438 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1440 aspath
= aspath_dup (attr
->aspath
);
1441 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1442 aspath_unintern (&attr
->aspath
);
1443 attr
->aspath
= aspath_intern (aspath
);
1446 return BGP_ATTR_PARSE_PROCEED
;
1449 /* Parse AS4 path information. This function is another wrapper of
1452 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1454 struct peer
*const peer
= args
->peer
;
1455 struct attr
*const attr
= args
->attr
;
1456 const bgp_size_t length
= args
->length
;
1458 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1460 /* In case of IBGP, length will be zero. */
1463 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1464 return bgp_attr_malformed (args
,
1465 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1469 /* Set aspath attribute flag. */
1471 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1473 return BGP_ATTR_PARSE_PROCEED
;
1476 /* Nexthop attribute. */
1477 static bgp_attr_parse_ret_t
1478 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1480 struct peer
*const peer
= args
->peer
;
1481 struct attr
*const attr
= args
->attr
;
1482 const bgp_size_t length
= args
->length
;
1484 in_addr_t nexthop_h
, nexthop_n
;
1486 /* Check nexthop attribute length. */
1489 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1491 return bgp_attr_malformed (args
,
1492 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1496 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1497 attribute must result in a NOTIFICATION message (this is implemented below).
1498 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1499 logged locally (this is implemented somewhere else). The UPDATE message
1500 gets ignored in any of these cases. */
1501 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1502 nexthop_h
= ntohl (nexthop_n
);
1503 if ((IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1504 && !BGP_DEBUG (allow_martians
, ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1506 char buf
[INET_ADDRSTRLEN
];
1507 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1508 zlog_err ("Martian nexthop %s", buf
);
1509 return bgp_attr_malformed (args
,
1510 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1514 attr
->nexthop
.s_addr
= nexthop_n
;
1515 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1517 return BGP_ATTR_PARSE_PROCEED
;
1520 /* MED atrribute. */
1521 static bgp_attr_parse_ret_t
1522 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1524 struct peer
*const peer
= args
->peer
;
1525 struct attr
*const attr
= args
->attr
;
1526 const bgp_size_t length
= args
->length
;
1531 zlog_err ("MED attribute length isn't four [%d]", length
);
1533 return bgp_attr_malformed (args
,
1534 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1538 attr
->med
= stream_getl (peer
->ibuf
);
1540 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1542 return BGP_ATTR_PARSE_PROCEED
;
1545 /* Local preference attribute. */
1546 static bgp_attr_parse_ret_t
1547 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1549 struct peer
*const peer
= args
->peer
;
1550 struct attr
*const attr
= args
->attr
;
1551 const bgp_size_t length
= args
->length
;
1556 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1557 return bgp_attr_malformed (args
,
1558 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1562 /* If it is contained in an UPDATE message that is received from an
1563 external peer, then this attribute MUST be ignored by the
1564 receiving speaker. */
1565 if (peer
->sort
== BGP_PEER_EBGP
)
1567 stream_forward_getp (peer
->ibuf
, length
);
1568 return BGP_ATTR_PARSE_PROCEED
;
1571 attr
->local_pref
= stream_getl (peer
->ibuf
);
1573 /* Set atomic aggregate flag. */
1574 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1576 return BGP_ATTR_PARSE_PROCEED
;
1579 /* Atomic aggregate. */
1581 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1583 struct attr
*const attr
= args
->attr
;
1584 const bgp_size_t length
= args
->length
;
1589 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1590 return bgp_attr_malformed (args
,
1591 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1595 /* Set atomic aggregate flag. */
1596 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1598 return BGP_ATTR_PARSE_PROCEED
;
1601 /* Aggregator attribute */
1603 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1605 struct peer
*const peer
= args
->peer
;
1606 struct attr
*const attr
= args
->attr
;
1607 const bgp_size_t length
= args
->length
;
1610 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1612 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1613 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1616 if (length
!= wantedlen
)
1618 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1619 return bgp_attr_malformed (args
,
1620 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1624 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1625 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1627 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1628 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1630 /* Set atomic aggregate flag. */
1631 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1633 return BGP_ATTR_PARSE_PROCEED
;
1636 /* New Aggregator attribute */
1637 static bgp_attr_parse_ret_t
1638 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1639 as_t
*as4_aggregator_as
,
1640 struct in_addr
*as4_aggregator_addr
)
1642 struct peer
*const peer
= args
->peer
;
1643 struct attr
*const attr
= args
->attr
;
1644 const bgp_size_t length
= args
->length
;
1648 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1649 return bgp_attr_malformed (args
,
1650 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1654 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1655 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1657 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1659 return BGP_ATTR_PARSE_PROCEED
;
1662 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1664 static bgp_attr_parse_ret_t
1665 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1666 struct attr
*const attr
,
1667 struct aspath
*as4_path
, as_t as4_aggregator
,
1668 struct in_addr
*as4_aggregator_addr
)
1670 int ignore_as4_path
= 0;
1671 struct aspath
*newpath
;
1672 struct attr_extra
*attre
= attr
->extra
;
1676 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1677 * checked that all well-known, mandatory attributes were present.
1679 * Can only be a problem with peer itself - hard error
1681 return BGP_ATTR_PARSE_ERROR
;
1684 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1686 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1688 * It is worth a warning though, because the peer really
1689 * should not send them
1691 if (BGP_DEBUG(as4
, AS4
))
1693 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1694 zlog_debug ("[AS4] %s %s AS4_PATH",
1695 peer
->host
, "AS4 capable peer, yet it sent");
1697 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1698 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1699 peer
->host
, "AS4 capable peer, yet it sent");
1702 return BGP_ATTR_PARSE_PROCEED
;
1705 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1706 * because that may override AS4_PATH
1708 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1710 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1715 * if the as_number in aggregator is not AS_TRANS,
1716 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1717 * and the Aggregator shall be taken as
1718 * info on the aggregating node, and the AS_PATH
1719 * shall be taken as the AS_PATH
1721 * the Aggregator shall be ignored and the
1722 * AS4_AGGREGATOR shall be taken as the
1723 * Aggregating node and the AS_PATH is to be
1724 * constructed "as in all other cases"
1726 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1729 if ( BGP_DEBUG(as4
, AS4
))
1730 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1731 " send AGGREGATOR != AS_TRANS and"
1732 " AS4_AGGREGATOR, so ignore"
1733 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1734 ignore_as4_path
= 1;
1738 /* "New_aggregator shall be taken as aggregator" */
1739 attre
->aggregator_as
= as4_aggregator
;
1740 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1745 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1746 * That is bogus - but reading the conditions
1747 * we have to handle AS4_AGGREGATOR as if it were
1748 * AGGREGATOR in that case
1750 if ( BGP_DEBUG(as4
, AS4
))
1751 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1752 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1753 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1754 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1755 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1756 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1760 /* need to reconcile NEW_AS_PATH and AS_PATH */
1761 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1763 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1764 aspath_unintern (&attr
->aspath
);
1765 attr
->aspath
= aspath_intern (newpath
);
1767 return BGP_ATTR_PARSE_PROCEED
;
1770 /* Community attribute. */
1771 static bgp_attr_parse_ret_t
1772 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1774 struct peer
*const peer
= args
->peer
;
1775 struct attr
*const attr
= args
->attr
;
1776 const bgp_size_t length
= args
->length
;
1780 attr
->community
= NULL
;
1781 return BGP_ATTR_PARSE_PROCEED
;
1785 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1787 /* XXX: fix community_parse to use stream API and remove this */
1788 stream_forward_getp (peer
->ibuf
, length
);
1790 if (!attr
->community
)
1791 return bgp_attr_malformed (args
,
1792 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1795 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1797 return BGP_ATTR_PARSE_PROCEED
;
1800 /* Originator ID attribute. */
1801 static bgp_attr_parse_ret_t
1802 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1804 struct peer
*const peer
= args
->peer
;
1805 struct attr
*const attr
= args
->attr
;
1806 const bgp_size_t length
= args
->length
;
1811 zlog_err ("Bad originator ID length %d", length
);
1813 return bgp_attr_malformed (args
,
1814 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1818 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1819 = stream_get_ipv4 (peer
->ibuf
);
1821 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1823 return BGP_ATTR_PARSE_PROCEED
;
1826 /* Cluster list attribute. */
1827 static bgp_attr_parse_ret_t
1828 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1830 struct peer
*const peer
= args
->peer
;
1831 struct attr
*const attr
= args
->attr
;
1832 const bgp_size_t length
= args
->length
;
1837 zlog_err ("Bad cluster list length %d", length
);
1839 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1843 (bgp_attr_extra_get (attr
))->cluster
1844 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1846 /* XXX: Fix cluster_parse to use stream API and then remove this */
1847 stream_forward_getp (peer
->ibuf
, length
);
1849 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1851 return BGP_ATTR_PARSE_PROCEED
;
1854 /* Multiprotocol reachability information parse. */
1856 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1857 struct bgp_nlri
*mp_update
)
1861 bgp_size_t nlri_len
;
1864 struct peer
*const peer
= args
->peer
;
1865 struct attr
*const attr
= args
->attr
;
1866 const bgp_size_t length
= args
->length
;
1867 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1869 /* Set end of packet. */
1870 s
= BGP_INPUT(peer
);
1871 start
= stream_get_getp(s
);
1873 /* safe to read statically sized header? */
1874 #define BGP_MP_REACH_MIN_SIZE 5
1875 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1876 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1878 zlog_info ("%s: %s sent invalid length, %lu",
1879 __func__
, peer
->host
, (unsigned long)length
);
1880 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1883 /* Load AFI, SAFI. */
1884 afi
= stream_getw (s
);
1885 safi
= stream_getc (s
);
1887 /* Get nexthop length. */
1888 attre
->mp_nexthop_len
= stream_getc (s
);
1890 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1892 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1893 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1894 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1897 /* Nexthop length check. */
1898 switch (attre
->mp_nexthop_len
)
1900 case BGP_ATTR_NHLEN_IPV4
:
1901 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1902 /* Probably needed for RFC 2283 */
1903 if (attr
->nexthop
.s_addr
== 0)
1904 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1906 case BGP_ATTR_NHLEN_VPNV4
:
1907 stream_getl (s
); /* RD high */
1908 stream_getl (s
); /* RD low */
1909 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1912 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1913 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1914 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1916 stream_getl (s
); /* RD high */
1917 stream_getl (s
); /* RD low */
1919 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1921 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1922 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1923 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1925 stream_getl (s
); /* RD high */
1926 stream_getl (s
); /* RD low */
1928 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1929 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1931 stream_getl (s
); /* RD high */
1932 stream_getl (s
); /* RD low */
1934 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1935 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1937 char buf1
[INET6_ADDRSTRLEN
];
1938 char buf2
[INET6_ADDRSTRLEN
];
1940 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1941 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1943 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1944 buf1
, INET6_ADDRSTRLEN
),
1945 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1946 buf2
, INET6_ADDRSTRLEN
));
1948 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1951 #endif /* HAVE_IPV6 */
1953 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1954 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1955 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1960 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1961 __func__
, peer
->host
);
1962 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1967 if ((val
= stream_getc (s
)))
1968 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1972 /* must have nrli_len, what is left of the attribute */
1973 nlri_len
= LEN_LEFT
;
1974 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
1976 zlog_info ("%s: (%s) Failed to read NLRI",
1977 __func__
, peer
->host
);
1978 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1981 mp_update
->afi
= afi
;
1982 mp_update
->safi
= safi
;
1983 mp_update
->nlri
= stream_pnt (s
);
1984 mp_update
->length
= nlri_len
;
1986 stream_forward_getp (s
, nlri_len
);
1988 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
1990 return BGP_ATTR_PARSE_PROCEED
;
1994 /* Multiprotocol unreachable parse */
1996 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
1997 struct bgp_nlri
*mp_withdraw
)
2002 u_int16_t withdraw_len
;
2003 struct peer
*const peer
= args
->peer
;
2004 struct attr
*const attr
= args
->attr
;
2005 const bgp_size_t length
= args
->length
;
2009 #define BGP_MP_UNREACH_MIN_SIZE 3
2010 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2011 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2013 afi
= stream_getw (s
);
2014 safi
= stream_getc (s
);
2016 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2018 mp_withdraw
->afi
= afi
;
2019 mp_withdraw
->safi
= safi
;
2020 mp_withdraw
->nlri
= stream_pnt (s
);
2021 mp_withdraw
->length
= withdraw_len
;
2023 stream_forward_getp (s
, withdraw_len
);
2025 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
2027 return BGP_ATTR_PARSE_PROCEED
;
2030 /* Extended Community attribute. */
2031 static bgp_attr_parse_ret_t
2032 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
2034 struct peer
*const peer
= args
->peer
;
2035 struct attr
*const attr
= args
->attr
;
2036 const bgp_size_t length
= args
->length
;
2041 attr
->extra
->ecommunity
= NULL
;
2042 /* Empty extcomm doesn't seem to be invalid per se */
2043 return BGP_ATTR_PARSE_PROCEED
;
2046 (bgp_attr_extra_get (attr
))->ecommunity
=
2047 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2048 /* XXX: fix ecommunity_parse to use stream API */
2049 stream_forward_getp (peer
->ibuf
, length
);
2051 if (!attr
->extra
->ecommunity
)
2052 return bgp_attr_malformed (args
,
2053 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2056 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
2058 return BGP_ATTR_PARSE_PROCEED
;
2061 /* Parse Tunnel Encap attribute in an UPDATE */
2065 struct peer
*peer
, /* IN */
2066 bgp_size_t length
, /* IN: attr's length field */
2067 struct attr
*attr
, /* IN: caller already allocated */
2068 u_char flag
, /* IN: attr's flags field */
2072 struct attr_extra
*attre
= NULL
;
2073 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2074 uint16_t tunneltype
= 0;
2076 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2078 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2079 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
2081 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
2082 bgp_notify_send_with_data (peer
,
2083 BGP_NOTIFY_UPDATE_ERR
,
2084 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2089 if (BGP_ATTR_ENCAP
== type
) {
2090 /* read outer TLV type and length */
2091 uint16_t tlv_length
;
2094 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2095 bgp_notify_send_with_data(peer
,
2096 BGP_NOTIFY_UPDATE_ERR
,
2097 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2101 tunneltype
= stream_getw (BGP_INPUT (peer
));
2102 tlv_length
= stream_getw (BGP_INPUT (peer
));
2105 if (tlv_length
!= length
) {
2106 zlog_info ("%s: tlv_length(%d) != length(%d)",
2107 __func__
, tlv_length
, length
);
2111 while (length
>= 4) {
2112 uint16_t subtype
= 0;
2113 uint16_t sublength
= 0;
2114 struct bgp_attr_encap_subtlv
*tlv
;
2116 if (BGP_ATTR_ENCAP
== type
) {
2117 subtype
= stream_getc (BGP_INPUT (peer
));
2118 sublength
= stream_getc (BGP_INPUT (peer
));
2122 subtype
= stream_getw (BGP_INPUT (peer
));
2123 sublength
= stream_getw (BGP_INPUT (peer
));
2128 if (sublength
> length
) {
2129 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2131 bgp_notify_send_with_data (peer
,
2132 BGP_NOTIFY_UPDATE_ERR
,
2133 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2138 /* alloc and copy sub-tlv */
2139 /* TBD make sure these are freed when attributes are released */
2140 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
2141 tlv
->type
= subtype
;
2142 tlv
->length
= sublength
;
2143 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2144 length
-= sublength
;
2146 /* attach tlv to encap chain */
2148 attre
= bgp_attr_extra_get(attr
);
2149 if (BGP_ATTR_ENCAP
== type
) {
2150 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
2151 stlv_last
= stlv_last
->next
);
2153 stlv_last
->next
= tlv
;
2155 attre
->encap_subtlvs
= tlv
;
2159 for (stlv_last
= attre
->vnc_subtlvs
; stlv_last
&& stlv_last
->next
;
2160 stlv_last
= stlv_last
->next
);
2162 stlv_last
->next
= tlv
;
2164 attre
->vnc_subtlvs
= tlv
;
2169 stlv_last
->next
= tlv
;
2174 if (BGP_ATTR_ENCAP
== type
) {
2176 attre
= bgp_attr_extra_get(attr
);
2177 attre
->encap_tunneltype
= tunneltype
;
2181 /* spurious leftover data */
2182 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2183 bgp_notify_send_with_data (peer
,
2184 BGP_NOTIFY_UPDATE_ERR
,
2185 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2193 /* BGP unknown attribute treatment. */
2194 static bgp_attr_parse_ret_t
2195 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2197 bgp_size_t total
= args
->total
;
2198 struct transit
*transit
;
2199 struct attr_extra
*attre
;
2200 struct peer
*const peer
= args
->peer
;
2201 struct attr
*const attr
= args
->attr
;
2202 u_char
*const startp
= args
->startp
;
2203 const u_char type
= args
->type
;
2204 const u_char flag
= args
->flags
;
2205 const bgp_size_t length
= args
->length
;
2207 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2208 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2209 peer
->host
, type
, length
);
2211 /* Forward read pointer of input stream. */
2212 stream_forward_getp (peer
->ibuf
, length
);
2214 /* If any of the mandatory well-known attributes are not recognized,
2215 then the Error Subcode is set to Unrecognized Well-known
2216 Attribute. The Data field contains the unrecognized attribute
2217 (type, length and value). */
2218 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2220 return bgp_attr_malformed (args
,
2221 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2225 /* Unrecognized non-transitive optional attributes must be quietly
2226 ignored and not passed along to other BGP peers. */
2227 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2228 return BGP_ATTR_PARSE_PROCEED
;
2230 /* If a path with recognized transitive optional attribute is
2231 accepted and passed along to other BGP peers and the Partial bit
2232 in the Attribute Flags octet is set to 1 by some previous AS, it
2233 is not set back to 0 by the current AS. */
2234 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2236 /* Store transitive attribute to the end of attr->transit. */
2237 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2238 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2240 transit
= attre
->transit
;
2243 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2244 transit
->length
+ total
);
2246 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2248 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2249 transit
->length
+= total
;
2251 return BGP_ATTR_PARSE_PROCEED
;
2254 /* Well-known attribute check. */
2256 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2260 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2262 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2263 return BGP_ATTR_PARSE_PROCEED
;
2265 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2266 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2267 are present, it should. Check for any other attribute being present
2270 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2271 return BGP_ATTR_PARSE_PROCEED
;
2273 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2274 type
= BGP_ATTR_ORIGIN
;
2276 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2277 type
= BGP_ATTR_AS_PATH
;
2279 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2280 * NLRI is empty. We can't easily check NLRI empty here though.
2282 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2283 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2284 type
= BGP_ATTR_NEXT_HOP
;
2286 if (peer
->sort
== BGP_PEER_IBGP
2287 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2288 type
= BGP_ATTR_LOCAL_PREF
;
2292 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2293 LOOKUP (attr_str
, type
));
2294 bgp_notify_send_with_data (peer
,
2295 BGP_NOTIFY_UPDATE_ERR
,
2296 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2298 return BGP_ATTR_PARSE_ERROR
;
2300 return BGP_ATTR_PARSE_PROCEED
;
2303 /* Read attribute of update packet. This function is called from
2304 bgp_update_receive() in bgp_packet.c. */
2305 bgp_attr_parse_ret_t
2306 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2307 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2313 u_char
*startp
, *endp
;
2315 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2316 /* we need the as4_path only until we have synthesized the as_path with it */
2317 /* same goes for as4_aggregator */
2318 struct aspath
*as4_path
= NULL
;
2319 as_t as4_aggregator
= 0;
2320 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2322 /* Initialize bitmap. */
2323 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2325 /* End pointer of BGP attribute. */
2326 endp
= BGP_INPUT_PNT (peer
) + size
;
2328 /* Get attributes to the end of attribute length. */
2329 while (BGP_INPUT_PNT (peer
) < endp
)
2331 /* Check remaining length check.*/
2332 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2334 /* XXX warning: long int format, int arg (arg 5) */
2335 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2337 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2339 bgp_notify_send (peer
,
2340 BGP_NOTIFY_UPDATE_ERR
,
2341 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2342 return BGP_ATTR_PARSE_ERROR
;
2345 /* Fetch attribute flag and type. */
2346 startp
= BGP_INPUT_PNT (peer
);
2347 /* "The lower-order four bits of the Attribute Flags octet are
2348 unused. They MUST be zero when sent and MUST be ignored when
2350 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2351 type
= stream_getc (BGP_INPUT (peer
));
2353 /* Check whether Extended-Length applies and is in bounds */
2354 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2355 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2357 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2359 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2361 bgp_notify_send (peer
,
2362 BGP_NOTIFY_UPDATE_ERR
,
2363 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2364 return BGP_ATTR_PARSE_ERROR
;
2367 /* Check extended attribue length bit. */
2368 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2369 length
= stream_getw (BGP_INPUT (peer
));
2371 length
= stream_getc (BGP_INPUT (peer
));
2373 /* If any attribute appears more than once in the UPDATE
2374 message, then the Error Subcode is set to Malformed Attribute
2377 if (CHECK_BITMAP (seen
, type
))
2379 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2382 bgp_notify_send (peer
,
2383 BGP_NOTIFY_UPDATE_ERR
,
2384 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2385 return BGP_ATTR_PARSE_ERROR
;
2388 /* Set type to bitmap to check duplicate attribute. `type' is
2389 unsigned char so it never overflow bitmap range. */
2391 SET_BITMAP (seen
, type
);
2393 /* Overflow check. */
2394 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2396 if (attr_endp
> endp
)
2398 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
);
2399 bgp_notify_send_with_data (peer
,
2400 BGP_NOTIFY_UPDATE_ERR
,
2401 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2402 startp
, attr_endp
- startp
);
2403 return BGP_ATTR_PARSE_ERROR
;
2406 struct bgp_attr_parser_args attr_args
= {
2413 .total
= attr_endp
- startp
,
2417 /* If any recognized attribute has Attribute Flags that conflict
2418 with the Attribute Type Code, then the Error Subcode is set to
2419 Attribute Flags Error. The Data field contains the erroneous
2420 attribute (type, length and value). */
2421 if (bgp_attr_flag_invalid (&attr_args
))
2423 bgp_attr_parse_ret_t ret
;
2424 ret
= bgp_attr_malformed (&attr_args
,
2425 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2427 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2432 /* OK check attribute and store it's value. */
2435 case BGP_ATTR_ORIGIN
:
2436 ret
= bgp_attr_origin (&attr_args
);
2438 case BGP_ATTR_AS_PATH
:
2439 ret
= bgp_attr_aspath (&attr_args
);
2441 case BGP_ATTR_AS4_PATH
:
2442 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2444 case BGP_ATTR_NEXT_HOP
:
2445 ret
= bgp_attr_nexthop (&attr_args
);
2447 case BGP_ATTR_MULTI_EXIT_DISC
:
2448 ret
= bgp_attr_med (&attr_args
);
2450 case BGP_ATTR_LOCAL_PREF
:
2451 ret
= bgp_attr_local_pref (&attr_args
);
2453 case BGP_ATTR_ATOMIC_AGGREGATE
:
2454 ret
= bgp_attr_atomic (&attr_args
);
2456 case BGP_ATTR_AGGREGATOR
:
2457 ret
= bgp_attr_aggregator (&attr_args
);
2459 case BGP_ATTR_AS4_AGGREGATOR
:
2460 ret
= bgp_attr_as4_aggregator (&attr_args
,
2462 &as4_aggregator_addr
);
2464 case BGP_ATTR_COMMUNITIES
:
2465 ret
= bgp_attr_community (&attr_args
);
2467 case BGP_ATTR_ORIGINATOR_ID
:
2468 ret
= bgp_attr_originator_id (&attr_args
);
2470 case BGP_ATTR_CLUSTER_LIST
:
2471 ret
= bgp_attr_cluster_list (&attr_args
);
2473 case BGP_ATTR_MP_REACH_NLRI
:
2474 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2476 case BGP_ATTR_MP_UNREACH_NLRI
:
2477 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2479 case BGP_ATTR_EXT_COMMUNITIES
:
2480 ret
= bgp_attr_ext_communities (&attr_args
);
2485 case BGP_ATTR_ENCAP
:
2486 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2489 ret
= bgp_attr_unknown (&attr_args
);
2493 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2495 bgp_notify_send (peer
,
2496 BGP_NOTIFY_UPDATE_ERR
,
2497 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2498 ret
= BGP_ATTR_PARSE_ERROR
;
2501 /* If hard error occured immediately return to the caller. */
2502 if (ret
== BGP_ATTR_PARSE_ERROR
)
2504 zlog_warn ("%s: Attribute %s, parse error",
2506 LOOKUP (attr_str
, type
));
2508 aspath_unintern (&as4_path
);
2511 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2514 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2516 LOOKUP (attr_str
, type
));
2518 aspath_unintern (&as4_path
);
2522 /* Check the fetched length. */
2523 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2525 zlog_warn ("%s: BGP attribute %s, fetch error",
2526 peer
->host
, LOOKUP (attr_str
, type
));
2527 bgp_notify_send (peer
,
2528 BGP_NOTIFY_UPDATE_ERR
,
2529 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2531 aspath_unintern (&as4_path
);
2532 return BGP_ATTR_PARSE_ERROR
;
2536 /* Check final read pointer is same as end pointer. */
2537 if (BGP_INPUT_PNT (peer
) != endp
)
2539 zlog_warn ("%s: BGP attribute %s, length mismatch",
2540 peer
->host
, LOOKUP (attr_str
, type
));
2541 bgp_notify_send (peer
,
2542 BGP_NOTIFY_UPDATE_ERR
,
2543 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2545 aspath_unintern (&as4_path
);
2546 return BGP_ATTR_PARSE_ERROR
;
2549 /* Check all mandatory well-known attributes are present */
2551 bgp_attr_parse_ret_t ret
;
2552 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2555 aspath_unintern (&as4_path
);
2561 * At this place we can see whether we got AS4_PATH and/or
2562 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2563 * We can not do this before we've read all attributes because
2564 * the as4 handling does not say whether AS4_PATH has to be sent
2565 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2566 * in relationship to AGGREGATOR.
2567 * So, to be defensive, we are not relying on any order and read
2568 * all attributes first, including these 32bit ones, and now,
2569 * afterwards, we look what and if something is to be done for as4.
2571 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2574 /* actually... this doesn't ever return failure currently, but
2575 * better safe than sorry */
2576 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2577 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2578 as4_aggregator
, &as4_aggregator_addr
))
2580 bgp_notify_send (peer
,
2581 BGP_NOTIFY_UPDATE_ERR
,
2582 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2584 aspath_unintern (&as4_path
);
2585 return BGP_ATTR_PARSE_ERROR
;
2588 /* At this stage, we have done all fiddling with as4, and the
2589 * resulting info is in attr->aggregator resp. attr->aspath
2590 * so we can chuck as4_aggregator and as4_path alltogether in
2591 * order to save memory
2595 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2596 /* The flag that we got this is still there, but that does not
2601 * The "rest" of the code does nothing with as4_aggregator.
2602 * there is no memory attached specifically which is not part
2604 * so ignoring just means do nothing.
2607 * Finally do the checks on the aspath we did not do yet
2608 * because we waited for a potentially synthesized aspath.
2610 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2612 ret
= bgp_attr_aspath_check (peer
, attr
);
2613 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2618 /* Finally intern unknown attribute. */
2619 if (attr
->extra
->transit
)
2620 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2621 if (attr
->extra
->encap_subtlvs
)
2622 attr
->extra
->encap_subtlvs
= encap_intern (attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2624 if (attr
->extra
->vnc_subtlvs
)
2625 attr
->extra
->vnc_subtlvs
= encap_intern (attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2629 return BGP_ATTR_PARSE_PROCEED
;
2633 bgp_packet_mpattr_start (struct stream
*s
, afi_t afi
, safi_t safi
, afi_t nh_afi
,
2634 struct bpacket_attr_vec_arr
*vecarr
,
2639 /* Set extended bit always to encode the attribute length as 2 bytes */
2640 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2641 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2642 sizep
= stream_get_endp (s
);
2643 stream_putw (s
, 0); /* Marker: Attribute length. */
2645 stream_putw (s
, afi
);
2646 stream_putc (s
, (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
);
2648 if (nh_afi
== AFI_MAX
)
2649 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->extra
->mp_nexthop_len
);
2657 case SAFI_MULTICAST
:
2658 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2660 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2663 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2664 stream_putc (s
, 12);
2665 stream_putl (s
, 0); /* RD = 0, per RFC */
2667 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2671 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2682 case SAFI_MULTICAST
:
2684 struct attr_extra
*attre
= attr
->extra
;
2686 assert (attr
->extra
);
2687 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2688 stream_putc (s
, attre
->mp_nexthop_len
);
2689 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2690 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2691 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2696 struct attr_extra
*attre
= attr
->extra
;
2698 assert (attr
->extra
);
2699 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2700 stream_putc (s
, 24);
2701 stream_putl (s
, 0); /* RD = 0, per RFC */
2703 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2704 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2705 stream_putc (s
, 48);
2706 stream_putl (s
, 0); /* RD = 0, per RFC */
2708 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2709 stream_putl (s
, 0); /* RD = 0, per RFC */
2711 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2716 assert (attr
->extra
);
2717 stream_putc (s
, IPV6_MAX_BYTELEN
);
2718 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2724 #endif /*HAVE_IPV6*/
2735 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2736 struct prefix
*p
, struct prefix_rd
*prd
,
2737 u_char
*tag
, int addpath_encode
,
2738 u_int32_t addpath_tx_id
)
2740 if (safi
== SAFI_MPLS_VPN
)
2743 stream_putl(s
, addpath_tx_id
);
2744 /* Tag, RD, Prefix write. */
2745 stream_putc (s
, p
->prefixlen
+ 88);
2746 stream_put (s
, tag
, 3);
2747 stream_put (s
, prd
->val
, 8);
2748 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2751 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
2755 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
2757 int size
= PSIZE (p
->prefixlen
);
2758 if (safi
== SAFI_MPLS_VPN
)
2764 * Encodes the tunnel encapsulation attribute,
2765 * and with ENABLE_BGP_VNC the VNC attribute which uses
2766 * almost the same TLV format
2769 bgp_packet_mpattr_tea(
2776 unsigned int attrlenfield
= 0;
2777 unsigned int attrhdrlen
= 0;
2778 struct bgp_attr_encap_subtlv
*subtlvs
;
2779 struct bgp_attr_encap_subtlv
*st
;
2780 const char *attrname
;
2782 if (!attr
|| !attr
->extra
||
2783 (attrtype
== BGP_ATTR_ENCAP
&&
2784 (!attr
->extra
->encap_tunneltype
||
2785 attr
->extra
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
2789 case BGP_ATTR_ENCAP
:
2790 attrname
= "Tunnel Encap";
2791 subtlvs
= attr
->extra
->encap_subtlvs
;
2794 * The tunnel encap attr has an "outer" tlv.
2796 * L = total length of subtlvs,
2797 * V = concatenated subtlvs.
2799 attrlenfield
= 2 + 2; /* T + L */
2800 attrhdrlen
= 1 + 1; /* subTLV T + L */
2806 subtlvs
= attr
->extra
->vnc_subtlvs
;
2807 attrlenfield
= 0; /* no outer T + L */
2808 attrhdrlen
= 2 + 2; /* subTLV T + L */
2816 /* compute attr length */
2817 for (st
= subtlvs
; st
; st
= st
->next
) {
2818 attrlenfield
+= (attrhdrlen
+ st
->length
);
2821 if (attrlenfield
> 0xffff) {
2822 zlog_info ("%s attribute is too long (length=%d), can't send it",
2828 if (attrlenfield
> 0xff) {
2829 /* 2-octet length field */
2831 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2832 stream_putc (s
, attrtype
);
2833 stream_putw (s
, attrlenfield
& 0xffff);
2835 /* 1-octet length field */
2836 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
2837 stream_putc (s
, attrtype
);
2838 stream_putc (s
, attrlenfield
& 0xff);
2841 if (attrtype
== BGP_ATTR_ENCAP
) {
2842 /* write outer T+L */
2843 stream_putw(s
, attr
->extra
->encap_tunneltype
);
2844 stream_putw(s
, attrlenfield
- 4);
2847 /* write each sub-tlv */
2848 for (st
= subtlvs
; st
; st
= st
->next
) {
2849 if (attrtype
== BGP_ATTR_ENCAP
) {
2850 stream_putc (s
, st
->type
);
2851 stream_putc (s
, st
->length
);
2854 stream_putw (s
, st
->type
);
2855 stream_putw (s
, st
->length
);
2858 stream_put (s
, st
->value
, st
->length
);
2863 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
2865 /* Set MP attribute length. Don't count the (2) bytes used to encode
2867 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
2870 /* Make attribute packet. */
2872 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
2873 struct stream
*s
, struct attr
*attr
,
2874 struct bpacket_attr_vec_arr
*vecarr
,
2875 struct prefix
*p
, afi_t afi
, safi_t safi
,
2876 struct peer
*from
, struct prefix_rd
*prd
, u_char
*tag
,
2878 u_int32_t addpath_tx_id
)
2881 size_t aspath_sizep
;
2882 struct aspath
*aspath
;
2883 int send_as4_path
= 0;
2884 int send_as4_aggregator
= 0;
2885 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2890 /* Remember current pointer. */
2891 cp
= stream_get_endp (s
);
2893 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
2894 !peer_cap_enhe(peer
)))
2896 size_t mpattrlen_pos
= 0;
2898 mpattrlen_pos
= bgp_packet_mpattr_start(s
, afi
, safi
,
2899 (peer_cap_enhe(peer
) ? AFI_IP6
:
2900 AFI_MAX
), /* get from NH */
2902 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
2903 addpath_encode
, addpath_tx_id
);
2904 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2907 /* Origin attribute. */
2908 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2909 stream_putc (s
, BGP_ATTR_ORIGIN
);
2911 stream_putc (s
, attr
->origin
);
2913 /* AS path attribute. */
2915 /* If remote-peer is EBGP */
2916 if (peer
->sort
== BGP_PEER_EBGP
2917 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
2918 || attr
->aspath
->segments
== NULL
)
2919 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
2921 aspath
= aspath_dup (attr
->aspath
);
2923 /* Even though we may not be configured for confederations we may have
2924 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2925 aspath
= aspath_delete_confed_seq (aspath
);
2927 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
2929 /* Stuff our path CONFED_ID on the front */
2930 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
2934 if (peer
->change_local_as
) {
2935 /* If replace-as is specified, we only use the change_local_as when
2936 advertising routes. */
2937 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
2938 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2940 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
2942 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2946 else if (peer
->sort
== BGP_PEER_CONFED
)
2948 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2949 aspath
= aspath_dup (attr
->aspath
);
2950 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
2953 aspath
= attr
->aspath
;
2955 /* If peer is not AS4 capable, then:
2956 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2957 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2958 * types are in it (i.e. exclude them if they are there)
2959 * AND do this only if there is at least one asnum > 65535 in the path!
2960 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2961 * all ASnums > 65535 to BGP_AS_TRANS
2964 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2965 stream_putc (s
, BGP_ATTR_AS_PATH
);
2966 aspath_sizep
= stream_get_endp (s
);
2968 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
2970 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2973 if (!use32bit
&& aspath_has_as4 (aspath
))
2974 send_as4_path
= 1; /* we'll do this later, at the correct place */
2976 /* Nexthop attribute. */
2977 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
))
2979 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2981 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2982 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2983 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2985 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2987 else if (safi
== SAFI_UNICAST
&& peer_cap_enhe(from
))
2990 * Likely this is the case when an IPv4 prefix was received with
2991 * Extended Next-hop capability and now being advertised to
2993 * Setting the mandatory (ipv4) next-hop attribute here to enable
2994 * implicit next-hop self with correct (ipv4 address family).
2996 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2997 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2998 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
3000 stream_put_ipv4 (s
, 0);
3004 /* MED attribute. */
3005 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
3008 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3009 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3011 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
3014 /* Local preference. */
3015 if (peer
->sort
== BGP_PEER_IBGP
||
3016 peer
->sort
== BGP_PEER_CONFED
)
3018 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3019 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3021 stream_putl (s
, attr
->local_pref
);
3024 /* Atomic aggregate. */
3025 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3027 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3028 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3033 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3035 assert (attr
->extra
);
3037 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3038 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3039 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3043 /* AS4 capable peer */
3045 stream_putl (s
, attr
->extra
->aggregator_as
);
3049 /* 2-byte AS peer */
3052 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3053 if ( attr
->extra
->aggregator_as
> 65535 )
3055 stream_putw (s
, BGP_AS_TRANS
);
3057 /* we have to send AS4_AGGREGATOR, too.
3058 * we'll do that later in order to send attributes in ascending
3061 send_as4_aggregator
= 1;
3064 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
3066 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3069 /* Community attribute. */
3070 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3071 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
3073 if (attr
->community
->size
* 4 > 255)
3075 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3076 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3077 stream_putw (s
, attr
->community
->size
* 4);
3081 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3082 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3083 stream_putc (s
, attr
->community
->size
* 4);
3085 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3088 /* Route Reflector. */
3089 if (peer
->sort
== BGP_PEER_IBGP
3091 && from
->sort
== BGP_PEER_IBGP
)
3093 /* Originator ID. */
3094 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3095 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
3098 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3099 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
3101 stream_put_in_addr (s
, &from
->remote_id
);
3104 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3105 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
3107 if (attr
->extra
&& attr
->extra
->cluster
)
3109 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
3110 /* If this peer configuration's parent BGP has cluster_id. */
3111 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3112 stream_put_in_addr (s
, &bgp
->cluster_id
);
3114 stream_put_in_addr (s
, &bgp
->router_id
);
3115 stream_put (s
, attr
->extra
->cluster
->list
,
3116 attr
->extra
->cluster
->length
);
3121 /* If this peer configuration's parent BGP has cluster_id. */
3122 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3123 stream_put_in_addr (s
, &bgp
->cluster_id
);
3125 stream_put_in_addr (s
, &bgp
->router_id
);
3129 /* Extended Communities attribute. */
3130 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3131 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
3133 struct attr_extra
*attre
= attr
->extra
;
3137 if (peer
->sort
== BGP_PEER_IBGP
3138 || peer
->sort
== BGP_PEER_CONFED
)
3140 if (attre
->ecommunity
->size
* 8 > 255)
3142 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3143 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3144 stream_putw (s
, attre
->ecommunity
->size
* 8);
3148 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3149 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3150 stream_putc (s
, attre
->ecommunity
->size
* 8);
3152 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
3158 int ecom_tr_size
= 0;
3161 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3163 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3166 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3174 if (ecom_tr_size
* 8 > 255)
3176 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3177 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3178 stream_putw (s
, ecom_tr_size
* 8);
3182 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3183 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3184 stream_putc (s
, ecom_tr_size
* 8);
3187 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3189 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3192 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3195 stream_put (s
, pnt
, 8);
3201 if ( send_as4_path
)
3203 /* If the peer is NOT As4 capable, AND */
3204 /* there are ASnums > 65535 in path THEN
3205 * give out AS4_PATH */
3207 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3209 * Hm, I wonder... confederation things *should* only be at
3210 * the beginning of an aspath, right? Then we should use
3211 * aspath_delete_confed_seq for this, because it is already
3213 * Folks, talk to me: what is reasonable here!?
3215 aspath
= aspath_delete_confed_seq (aspath
);
3217 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3218 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3219 aspath_sizep
= stream_get_endp (s
);
3221 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3224 if (aspath
!= attr
->aspath
)
3225 aspath_free (aspath
);
3227 if ( send_as4_aggregator
)
3229 assert (attr
->extra
);
3231 /* send AS4_AGGREGATOR, at this place */
3232 /* this section of code moved here in order to ensure the correct
3233 * *ascending* order of attributes
3235 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3236 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3238 stream_putl (s
, attr
->extra
->aggregator_as
);
3239 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3242 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3243 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3245 /* Tunnel Encap attribute */
3246 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3250 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3254 /* Unknown transit attribute. */
3255 if (attr
->extra
&& attr
->extra
->transit
)
3256 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3258 /* Return total size of attribute. */
3259 return stream_get_endp (s
) - cp
;
3263 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3265 unsigned long attrlen_pnt
;
3267 /* Set extended bit always to encode the attribute length as 2 bytes */
3268 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3269 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3271 attrlen_pnt
= stream_get_endp (s
);
3272 stream_putw (s
, 0); /* Length of this attribute. */
3274 stream_putw (s
, afi
);
3275 stream_putc (s
, (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
);
3280 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3281 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3282 u_char
*tag
, int addpath_encode
,
3283 u_int32_t addpath_tx_id
)
3285 if (safi
== SAFI_MPLS_VPN
)
3289 stream_putl(s
, addpath_tx_id
);
3291 stream_putc (s
, p
->prefixlen
+ 88);
3292 stream_put (s
, tag
, 3);
3293 stream_put (s
, prd
->val
, 8);
3294 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3297 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
3301 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3303 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3306 /* Initialization of attribute. */
3308 bgp_attr_init (void)
3320 bgp_attr_finish (void)
3324 community_finish ();
3325 ecommunity_finish ();
3331 /* Make attribute packet. */
3333 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3334 struct prefix
*prefix
)
3339 struct aspath
*aspath
;
3340 int addpath_encode
= 0;
3341 u_int32_t addpath_tx_id
= 0;
3343 /* Remember current pointer. */
3344 cp
= stream_get_endp (s
);
3346 /* Place holder of length. */
3349 /* Origin attribute. */
3350 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3351 stream_putc (s
, BGP_ATTR_ORIGIN
);
3353 stream_putc (s
, attr
->origin
);
3355 aspath
= attr
->aspath
;
3357 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3358 stream_putc (s
, BGP_ATTR_AS_PATH
);
3359 aspath_lenp
= stream_get_endp (s
);
3362 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3364 /* Nexthop attribute. */
3365 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3368 && prefix
->family
!= AF_INET6
3369 #endif /* HAVE_IPV6 */
3372 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3373 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3375 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3378 /* MED attribute. */
3379 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3381 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3382 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3384 stream_putl (s
, attr
->med
);
3387 /* Local preference. */
3388 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3390 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3391 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3393 stream_putl (s
, attr
->local_pref
);
3396 /* Atomic aggregate. */
3397 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3399 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3400 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3405 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3407 assert (attr
->extra
);
3408 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3409 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3411 stream_putl (s
, attr
->extra
->aggregator_as
);
3412 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3415 /* Community attribute. */
3416 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3418 if (attr
->community
->size
* 4 > 255)
3420 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3421 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3422 stream_putw (s
, attr
->community
->size
* 4);
3426 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3427 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3428 stream_putc (s
, attr
->community
->size
* 4);
3430 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3434 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3435 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3436 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3437 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3440 struct attr_extra
*attre
= attr
->extra
;
3442 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3443 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3444 sizep
= stream_get_endp (s
);
3447 stream_putc (s
, 0); /* Marker: Attribute length. */
3448 stream_putw(s
, AFI_IP6
); /* AFI */
3449 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3452 stream_putc(s
, attre
->mp_nexthop_len
);
3453 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3454 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3455 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3461 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3463 /* Set MP attribute length. */
3464 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3466 #endif /* HAVE_IPV6 */
3468 /* Return total size of attribute. */
3469 len
= stream_get_endp (s
) - cp
- 2;
3470 stream_putw_at (s
, cp
, len
);