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 /* Attribute strings for logging. */
48 static const struct message attr_str
[] =
50 { BGP_ATTR_ORIGIN
, "ORIGIN" },
51 { BGP_ATTR_AS_PATH
, "AS_PATH" },
52 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
53 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
54 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
55 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
56 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
57 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
58 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
59 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
60 { BGP_ATTR_DPA
, "DPA" },
61 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
62 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
63 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
64 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
65 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
66 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
67 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
68 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
69 { BGP_ATTR_ENCAP
, "ENCAP" },
71 static const int attr_str_max
= array_size(attr_str
);
73 static const struct message attr_flag_str
[] =
75 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
76 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
77 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
78 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
79 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
82 static struct hash
*cluster_hash
;
85 cluster_hash_alloc (void *p
)
87 const struct cluster_list
*val
= (const struct cluster_list
*) p
;
88 struct cluster_list
*cluster
;
90 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
91 cluster
->length
= val
->length
;
95 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
96 memcpy (cluster
->list
, val
->list
, val
->length
);
106 /* Cluster list related functions. */
107 static struct cluster_list
*
108 cluster_parse (struct in_addr
* pnt
, int length
)
110 struct cluster_list tmp
;
111 struct cluster_list
*cluster
;
116 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
122 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
126 for (i
= 0; i
< cluster
->length
/ 4; i
++)
127 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
133 cluster_hash_key_make (void *p
)
135 const struct cluster_list
*cluster
= p
;
137 return jhash(cluster
->list
, cluster
->length
, 0);
141 cluster_hash_cmp (const void *p1
, const void *p2
)
143 const struct cluster_list
* cluster1
= p1
;
144 const struct cluster_list
* cluster2
= p2
;
146 return (cluster1
->length
== cluster2
->length
&&
147 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
151 cluster_free (struct cluster_list
*cluster
)
154 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
155 XFREE (MTYPE_CLUSTER
, cluster
);
158 static struct cluster_list
*
159 cluster_dup (struct cluster_list
*cluster
)
161 struct cluster_list
*new;
163 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
164 new->length
= cluster
->length
;
168 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
169 memcpy (new->list
, cluster
->list
, cluster
->length
);
177 static struct cluster_list
*
178 cluster_intern (struct cluster_list
*cluster
)
180 struct cluster_list
*find
;
182 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
189 cluster_unintern (struct cluster_list
*cluster
)
194 if (cluster
->refcnt
== 0)
196 hash_release (cluster_hash
, cluster
);
197 cluster_free (cluster
);
204 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
208 cluster_finish (void)
210 hash_free (cluster_hash
);
214 struct bgp_attr_encap_subtlv
*
215 encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
217 struct bgp_attr_encap_subtlv
*new;
218 struct bgp_attr_encap_subtlv
*tail
;
219 struct bgp_attr_encap_subtlv
*p
;
221 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
222 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
224 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
227 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
230 memcpy(tail
, p
, size
);
238 encap_free(struct bgp_attr_encap_subtlv
*p
)
240 struct bgp_attr_encap_subtlv
*next
;
244 XFREE(MTYPE_ENCAP_TLV
, p
);
250 bgp_attr_flush_encap(struct attr
*attr
)
252 if (!attr
|| !attr
->extra
)
255 if (attr
->extra
->encap_subtlvs
) {
256 encap_free(attr
->extra
->encap_subtlvs
);
257 attr
->extra
->encap_subtlvs
= NULL
;
262 * Compare encap sub-tlv chains
267 * This algorithm could be made faster if needed
270 encap_same(struct bgp_attr_encap_subtlv
*h1
, struct bgp_attr_encap_subtlv
*h2
)
272 struct bgp_attr_encap_subtlv
*p
;
273 struct bgp_attr_encap_subtlv
*q
;
284 for (p
= h1
; p
; p
= p
->next
) {
285 for (q
= h2
; q
; q
= q
->next
) {
286 if ((p
->type
== q
->type
) &&
287 (p
->length
== q
->length
) &&
288 !memcmp(p
->value
, q
->value
, p
->length
)) {
297 for (p
= h2
; p
; p
= p
->next
) {
298 for (q
= h1
; q
; q
= q
->next
) {
299 if ((p
->type
== q
->type
) &&
300 (p
->length
== q
->length
) &&
301 !memcmp(p
->value
, q
->value
, p
->length
)) {
313 /* Unknown transit attribute. */
314 static struct hash
*transit_hash
;
317 transit_free (struct transit
*transit
)
320 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
321 XFREE (MTYPE_TRANSIT
, transit
);
324 static struct transit
*
325 transit_dup (struct transit
*transit
)
329 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
330 new->length
= transit
->length
;
333 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
334 memcpy (new->val
, transit
->val
, transit
->length
);
343 transit_hash_alloc (void *p
)
345 /* Transit structure is already allocated. */
349 static struct transit
*
350 transit_intern (struct transit
*transit
)
352 struct transit
*find
;
354 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
356 transit_free (transit
);
363 transit_unintern (struct transit
*transit
)
368 if (transit
->refcnt
== 0)
370 hash_release (transit_hash
, transit
);
371 transit_free (transit
);
376 transit_hash_key_make (void *p
)
378 const struct transit
* transit
= p
;
380 return jhash(transit
->val
, transit
->length
, 0);
384 transit_hash_cmp (const void *p1
, const void *p2
)
386 const struct transit
* transit1
= p1
;
387 const struct transit
* transit2
= p2
;
389 return (transit1
->length
== transit2
->length
&&
390 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
396 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
400 transit_finish (void)
402 hash_free (transit_hash
);
406 /* Attribute hash routines. */
407 static struct hash
*attrhash
;
409 static struct attr_extra
*
410 bgp_attr_extra_new (void)
412 return XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
416 bgp_attr_extra_free (struct attr
*attr
)
420 if (attr
->extra
->encap_subtlvs
) {
421 encap_free(attr
->extra
->encap_subtlvs
);
422 attr
->extra
->encap_subtlvs
= NULL
;
424 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
430 bgp_attr_extra_get (struct attr
*attr
)
433 attr
->extra
= bgp_attr_extra_new();
437 /* Shallow copy of an attribute
438 * Though, not so shallow that it doesn't copy the contents
439 * of the attr_extra pointed to by 'extra'
442 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
444 struct attr_extra
*extra
= new->extra
;
447 /* if caller provided attr_extra space, use it in any case.
449 * This is neccesary even if orig->extra equals NULL, because otherwise
450 * memory may be later allocated on the heap by bgp_attr_extra_get.
452 * That memory would eventually be leaked, because the caller must not
453 * call bgp_attr_extra_free if he provided attr_extra on the stack.
458 memset(new->extra
, 0, sizeof(struct attr_extra
));
460 *new->extra
= *orig
->extra
;
461 if (orig
->extra
->encap_subtlvs
) {
462 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
466 else if (orig
->extra
)
468 new->extra
= bgp_attr_extra_new();
469 *new->extra
= *orig
->extra
;
470 if (orig
->extra
->encap_subtlvs
) {
471 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
477 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
480 new->aspath
= aspath_dup(orig
->aspath
);
483 new->community
= community_dup(orig
->community
);
487 if (orig
->extra
->ecommunity
)
488 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
489 if (orig
->extra
->cluster
)
490 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
491 if (orig
->extra
->transit
)
492 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
497 bgp_attr_deep_free (struct attr
*attr
)
500 aspath_free(attr
->aspath
);
503 community_free(attr
->community
);
507 if (attr
->extra
->ecommunity
)
508 ecommunity_free(&attr
->extra
->ecommunity
);
509 if (attr
->extra
->cluster
)
510 cluster_free(attr
->extra
->cluster
);
511 if (attr
->extra
->transit
)
512 transit_free(attr
->extra
->transit
);
519 return attrhash
->count
;
523 attr_unknown_count (void)
525 return transit_hash
->count
;
529 attrhash_key_make (void *p
)
531 const struct attr
*attr
= (struct attr
*) p
;
532 const struct attr_extra
*extra
= attr
->extra
;
534 #define MIX(val) key = jhash_1word(val, key)
537 MIX(attr
->nexthop
.s_addr
);
539 MIX(attr
->local_pref
);
542 key
+= attr
->nexthop
.s_addr
;
544 key
+= attr
->local_pref
;
548 MIX(extra
->aggregator_as
);
549 MIX(extra
->aggregator_addr
.s_addr
);
551 MIX(extra
->mp_nexthop_global_in
.s_addr
);
552 MIX(extra
->originator_id
.s_addr
);
557 MIX(aspath_key_make (attr
->aspath
));
559 MIX(community_hash_make (attr
->community
));
563 if (extra
->ecommunity
)
564 MIX(ecommunity_hash_make (extra
->ecommunity
));
566 MIX(cluster_hash_key_make (extra
->cluster
));
568 MIX(transit_hash_key_make (extra
->transit
));
571 MIX(extra
->mp_nexthop_len
);
572 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
573 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
574 #endif /* HAVE_IPV6 */
581 attrhash_cmp (const void *p1
, const void *p2
)
583 const struct attr
* attr1
= p1
;
584 const struct attr
* attr2
= p2
;
586 if (attr1
->flag
== attr2
->flag
587 && attr1
->origin
== attr2
->origin
588 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
589 && attr1
->aspath
== attr2
->aspath
590 && attr1
->community
== attr2
->community
591 && attr1
->med
== attr2
->med
592 && attr1
->local_pref
== attr2
->local_pref
593 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
595 const struct attr_extra
*ae1
= attr1
->extra
;
596 const struct attr_extra
*ae2
= attr2
->extra
;
599 && ae1
->aggregator_as
== ae2
->aggregator_as
600 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
601 && ae1
->weight
== ae2
->weight
602 && ae1
->tag
== ae2
->tag
604 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
605 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
606 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
607 #endif /* HAVE_IPV6 */
608 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
609 && ae1
->ecommunity
== ae2
->ecommunity
610 && ae1
->cluster
== ae2
->cluster
611 && ae1
->transit
== ae2
->transit
612 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
613 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
614 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
))
618 /* neither attribute has extra attributes, so they're same */
628 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
632 attrhash_finish (void)
634 hash_free (attrhash
);
639 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
641 struct attr
*attr
= backet
->data
;
643 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
644 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
648 attr_show_all (struct vty
*vty
)
650 hash_iterate (attrhash
,
651 (void (*)(struct hash_backet
*, void *))
652 attr_show_all_iterator
,
657 bgp_attr_hash_alloc (void *p
)
659 const struct attr
* val
= (const struct attr
*) p
;
662 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
666 attr
->extra
= bgp_attr_extra_new ();
667 *attr
->extra
= *val
->extra
;
669 if (attr
->extra
->encap_subtlvs
) {
670 attr
->extra
->encap_subtlvs
= encap_tlv_dup(attr
->extra
->encap_subtlvs
);
677 /* Internet argument attribute. */
679 bgp_attr_intern (struct attr
*attr
)
683 /* Intern referenced strucutre. */
686 if (! attr
->aspath
->refcnt
)
687 attr
->aspath
= aspath_intern (attr
->aspath
);
689 attr
->aspath
->refcnt
++;
693 if (! attr
->community
->refcnt
)
694 attr
->community
= community_intern (attr
->community
);
696 attr
->community
->refcnt
++;
700 struct attr_extra
*attre
= attr
->extra
;
702 if (attre
->ecommunity
)
704 if (! attre
->ecommunity
->refcnt
)
705 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
707 attre
->ecommunity
->refcnt
++;
712 if (! attre
->cluster
->refcnt
)
713 attre
->cluster
= cluster_intern (attre
->cluster
);
715 attre
->cluster
->refcnt
++;
719 if (! attre
->transit
->refcnt
)
720 attre
->transit
= transit_intern (attre
->transit
);
722 attre
->transit
->refcnt
++;
726 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
733 * Increment the refcount on various structures that attr holds.
734 * Note on usage: call _only_ when the 'attr' object has already
735 * been 'intern'ed and exists in 'attrhash' table. The function
736 * serves to hold a reference to that (real) object.
737 * Note also that the caller can safely call bgp_attr_unintern()
738 * after calling bgp_attr_refcount(). That would release the
739 * reference and could result in a free() of the attr object.
742 bgp_attr_refcount (struct attr
*attr
)
744 /* Intern referenced strucutre. */
746 attr
->aspath
->refcnt
++;
749 attr
->community
->refcnt
++;
753 struct attr_extra
*attre
= attr
->extra
;
754 if (attre
->ecommunity
)
755 attre
->ecommunity
->refcnt
++;
758 attre
->cluster
->refcnt
++;
761 attre
->transit
->refcnt
++;
767 /* Make network statement's attribute. */
769 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
771 memset (attr
, 0, sizeof (struct attr
));
772 bgp_attr_extra_get (attr
);
774 attr
->origin
= origin
;
775 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
776 attr
->aspath
= aspath_empty ();
777 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
778 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
779 attr
->extra
->tag
= 0;
780 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
782 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
789 /* Make network statement's attribute. */
791 bgp_attr_default_intern (u_char origin
)
796 memset (&attr
, 0, sizeof (struct attr
));
797 bgp_attr_extra_get (&attr
);
799 bgp_attr_default_set(&attr
, origin
);
801 new = bgp_attr_intern (&attr
);
802 bgp_attr_extra_free (&attr
);
804 aspath_unintern (&new->aspath
);
808 /* Create the attributes for an aggregate */
810 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
811 struct aspath
*aspath
,
812 struct community
*community
, int as_set
,
813 u_char atomic_aggregate
)
817 struct attr_extra attre
;
819 memset (&attr
, 0, sizeof (struct attr
));
820 memset (&attre
, 0, sizeof (struct attr_extra
));
823 /* Origin attribute. */
824 attr
.origin
= origin
;
825 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
827 /* AS path attribute. */
829 attr
.aspath
= aspath_intern (aspath
);
831 attr
.aspath
= aspath_empty ();
832 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
834 /* Next hop attribute. */
835 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
839 attr
.community
= community
;
840 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
843 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
845 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
847 if (! as_set
|| atomic_aggregate
)
848 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
849 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
850 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
851 attre
.aggregator_as
= bgp
->confed_id
;
853 attre
.aggregator_as
= bgp
->as
;
854 attre
.aggregator_addr
= bgp
->router_id
;
856 new = bgp_attr_intern (&attr
);
858 aspath_unintern (&new->aspath
);
862 /* Unintern just the sub-components of the attr, but not the attr */
864 bgp_attr_unintern_sub (struct attr
*attr
)
866 /* aspath refcount shoud be decrement. */
868 aspath_unintern (&attr
->aspath
);
869 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
872 community_unintern (&attr
->community
);
873 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
877 if (attr
->extra
->ecommunity
)
878 ecommunity_unintern (&attr
->extra
->ecommunity
);
879 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
881 if (attr
->extra
->cluster
)
882 cluster_unintern (attr
->extra
->cluster
);
883 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
885 if (attr
->extra
->transit
)
886 transit_unintern (attr
->extra
->transit
);
890 /* Free bgp attribute and aspath. */
892 bgp_attr_unintern (struct attr
**pattr
)
894 struct attr
*attr
= *pattr
;
897 struct attr_extra tmp_extra
;
899 /* Decrement attribute reference. */
906 tmp
.extra
= &tmp_extra
;
907 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
910 /* If reference becomes zero then free attribute object. */
911 if (attr
->refcnt
== 0)
913 ret
= hash_release (attrhash
, attr
);
914 assert (ret
!= NULL
);
915 bgp_attr_extra_free (attr
);
916 XFREE (MTYPE_ATTR
, attr
);
920 bgp_attr_unintern_sub (&tmp
);
924 bgp_attr_flush (struct attr
*attr
)
926 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
927 aspath_free (attr
->aspath
);
928 if (attr
->community
&& ! attr
->community
->refcnt
)
929 community_free (attr
->community
);
932 struct attr_extra
*attre
= attr
->extra
;
934 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
935 ecommunity_free (&attre
->ecommunity
);
936 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
937 cluster_free (attre
->cluster
);
938 if (attre
->transit
&& ! attre
->transit
->refcnt
)
939 transit_free (attre
->transit
);
940 encap_free(attre
->encap_subtlvs
);
941 attre
->encap_subtlvs
= NULL
;
945 /* Implement draft-scudder-idr-optional-transitive behaviour and
946 * avoid resetting sessions for malformed attributes which are
947 * are partial/optional and hence where the error likely was not
948 * introduced by the sending neighbour.
950 static bgp_attr_parse_ret_t
951 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
954 struct peer
*const peer
= args
->peer
;
955 const u_int8_t flags
= args
->flags
;
956 /* startp and length must be special-cased, as whether or not to
957 * send the attribute data with the NOTIFY depends on the error,
958 * the caller therefore signals this with the seperate length argument
960 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
962 /* Only relax error handling for eBGP peers */
963 if (peer
->sort
!= BGP_PEER_EBGP
)
965 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
966 notify_datap
, length
);
967 return BGP_ATTR_PARSE_ERROR
;
971 /* Adjust the stream getp to the end of the attribute, in case we can
972 * still proceed but the caller hasn't read all the attribute.
974 stream_set_getp (BGP_INPUT (peer
),
975 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
978 switch (args
->type
) {
979 /* where an attribute is relatively inconsequential, e.g. it does not
980 * affect route selection, and can be safely ignored, then any such
981 * attributes which are malformed should just be ignored and the route
982 * processed as normal.
984 case BGP_ATTR_AS4_AGGREGATOR
:
985 case BGP_ATTR_AGGREGATOR
:
986 case BGP_ATTR_ATOMIC_AGGREGATE
:
987 return BGP_ATTR_PARSE_PROCEED
;
989 /* Core attributes, particularly ones which may influence route
990 * selection, should always cause session resets
992 case BGP_ATTR_ORIGIN
:
993 case BGP_ATTR_AS_PATH
:
994 case BGP_ATTR_NEXT_HOP
:
995 case BGP_ATTR_MULTI_EXIT_DISC
:
996 case BGP_ATTR_LOCAL_PREF
:
997 case BGP_ATTR_COMMUNITIES
:
998 case BGP_ATTR_ORIGINATOR_ID
:
999 case BGP_ATTR_CLUSTER_LIST
:
1000 case BGP_ATTR_MP_REACH_NLRI
:
1001 case BGP_ATTR_MP_UNREACH_NLRI
:
1002 case BGP_ATTR_EXT_COMMUNITIES
:
1003 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1004 notify_datap
, length
);
1005 return BGP_ATTR_PARSE_ERROR
;
1008 /* Partial optional attributes that are malformed should not cause
1009 * the whole session to be reset. Instead treat it as a withdrawal
1010 * of the routes, if possible.
1012 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1013 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1014 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1015 return BGP_ATTR_PARSE_WITHDRAW
;
1017 /* default to reset */
1018 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1021 /* Find out what is wrong with the path attribute flag bits and log the error.
1022 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1023 Extended Length. Checking O/T/P bits at once implies, that the attribute
1024 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1025 non-transitive" attribute. */
1027 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1028 u_int8_t desired_flags
/* how RFC says it must be */
1032 u_char real_flags
= args
->flags
;
1033 const u_int8_t attr_code
= args
->type
;
1035 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1036 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1037 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1040 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1041 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1044 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1045 LOOKUP (attr_str
, attr_code
),
1046 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1047 attr_flag_str
[i
].str
);
1052 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1053 " (real flags 0x%x, desired 0x%x)",
1054 __func__
, LOOKUP (attr_str
, attr_code
),
1055 real_flags
, desired_flags
);
1059 /* Required flags for attributes. EXTLEN will be masked off when testing,
1060 * as will PARTIAL for optional+transitive attributes.
1062 const u_int8_t attr_flags_values
[] = {
1063 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1064 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1065 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1066 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1067 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1068 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1069 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1070 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1071 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1072 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1073 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1074 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1075 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1076 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1077 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1079 static const size_t attr_flags_values_max
=
1080 sizeof (attr_flags_values
) / sizeof (attr_flags_values
[0]);
1083 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1085 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1086 const u_int8_t flags
= args
->flags
;
1087 const u_int8_t attr_code
= args
->type
;
1089 /* there may be attributes we don't know about */
1090 if (attr_code
> attr_flags_values_max
)
1092 if (attr_flags_values
[attr_code
] == 0)
1095 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1098 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1099 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1101 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1102 LOOKUP (attr_str
, attr_code
), flags
);
1106 /* "For well-known attributes and for optional non-transitive attributes,
1107 * the Partial bit MUST be set to 0."
1109 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1111 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1113 zlog_err ("%s well-known attribute "
1114 "must NOT have the partial flag set (%x)",
1115 LOOKUP (attr_str
, attr_code
), flags
);
1118 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1119 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1121 zlog_err ("%s optional + transitive attribute "
1122 "must NOT have the partial flag set (%x)",
1123 LOOKUP (attr_str
, attr_code
), flags
);
1128 /* Optional transitive attributes may go through speakers that don't
1129 * reocgnise them and set the Partial bit.
1131 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1132 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1133 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1136 == attr_flags_values
[attr_code
])
1139 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1143 /* Get origin attribute of the update message. */
1144 static bgp_attr_parse_ret_t
1145 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1147 struct peer
*const peer
= args
->peer
;
1148 struct attr
*const attr
= args
->attr
;
1149 const bgp_size_t length
= args
->length
;
1151 /* If any recognized attribute has Attribute Length that conflicts
1152 with the expected length (based on the attribute type code), then
1153 the Error Subcode is set to Attribute Length Error. The Data
1154 field contains the erroneous attribute (type, length and
1158 zlog_err ("Origin attribute length is not one %d", length
);
1159 return bgp_attr_malformed (args
,
1160 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1164 /* Fetch origin attribute. */
1165 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1167 /* If the ORIGIN attribute has an undefined value, then the Error
1168 Subcode is set to Invalid Origin Attribute. The Data field
1169 contains the unrecognized attribute (type, length and value). */
1170 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1171 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1172 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1174 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1175 return bgp_attr_malformed (args
,
1176 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1180 /* Set oring attribute flag. */
1181 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1186 /* Parse AS path information. This function is wrapper of
1189 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1191 struct attr
*const attr
= args
->attr
;
1192 struct peer
*const peer
= args
->peer
;
1193 const bgp_size_t length
= args
->length
;
1196 * peer with AS4 => will get 4Byte ASnums
1197 * otherwise, will get 16 Bit
1199 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1200 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1202 /* In case of IBGP, length will be zero. */
1205 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1206 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1209 /* Set aspath attribute flag. */
1210 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1212 return BGP_ATTR_PARSE_PROCEED
;
1215 static bgp_attr_parse_ret_t
1216 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1218 /* These checks were part of bgp_attr_aspath, but with
1219 * as4 we should to check aspath things when
1220 * aspath synthesizing with as4_path has already taken place.
1221 * Otherwise we check ASPATH and use the synthesized thing, and that is
1223 * So do the checks later, i.e. here
1225 struct bgp
*bgp
= peer
->bgp
;
1226 struct aspath
*aspath
;
1228 /* Confederation sanity check. */
1229 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1230 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1232 zlog_err ("Malformed AS path from %s", peer
->host
);
1233 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1234 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1235 return BGP_ATTR_PARSE_ERROR
;
1238 /* First AS check for EBGP. */
1239 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1241 if (peer
->sort
== BGP_PEER_EBGP
1242 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1244 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1245 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1246 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1247 return BGP_ATTR_PARSE_ERROR
;
1251 /* local-as prepend */
1252 if (peer
->change_local_as
&&
1253 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1255 aspath
= aspath_dup (attr
->aspath
);
1256 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1257 aspath_unintern (&attr
->aspath
);
1258 attr
->aspath
= aspath_intern (aspath
);
1261 return BGP_ATTR_PARSE_PROCEED
;
1264 /* Parse AS4 path information. This function is another wrapper of
1267 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1269 struct peer
*const peer
= args
->peer
;
1270 struct attr
*const attr
= args
->attr
;
1271 const bgp_size_t length
= args
->length
;
1273 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1275 /* In case of IBGP, length will be zero. */
1278 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1279 return bgp_attr_malformed (args
,
1280 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1284 /* Set aspath attribute flag. */
1286 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1288 return BGP_ATTR_PARSE_PROCEED
;
1291 /* Nexthop attribute. */
1292 static bgp_attr_parse_ret_t
1293 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1295 struct peer
*const peer
= args
->peer
;
1296 struct attr
*const attr
= args
->attr
;
1297 const bgp_size_t length
= args
->length
;
1299 in_addr_t nexthop_h
, nexthop_n
;
1301 /* Check nexthop attribute length. */
1304 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1306 return bgp_attr_malformed (args
,
1307 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1311 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1312 attribute must result in a NOTIFICATION message (this is implemented below).
1313 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1314 logged locally (this is implemented somewhere else). The UPDATE message
1315 gets ignored in any of these cases. */
1316 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1317 nexthop_h
= ntohl (nexthop_n
);
1318 if (IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1320 char buf
[INET_ADDRSTRLEN
];
1321 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1322 zlog_err ("Martian nexthop %s", buf
);
1323 return bgp_attr_malformed (args
,
1324 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1328 attr
->nexthop
.s_addr
= nexthop_n
;
1329 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1331 return BGP_ATTR_PARSE_PROCEED
;
1334 /* MED atrribute. */
1335 static bgp_attr_parse_ret_t
1336 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1338 struct peer
*const peer
= args
->peer
;
1339 struct attr
*const attr
= args
->attr
;
1340 const bgp_size_t length
= args
->length
;
1345 zlog_err ("MED attribute length isn't four [%d]", length
);
1347 return bgp_attr_malformed (args
,
1348 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1352 attr
->med
= stream_getl (peer
->ibuf
);
1354 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1356 return BGP_ATTR_PARSE_PROCEED
;
1359 /* Local preference attribute. */
1360 static bgp_attr_parse_ret_t
1361 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1363 struct peer
*const peer
= args
->peer
;
1364 struct attr
*const attr
= args
->attr
;
1365 const bgp_size_t length
= args
->length
;
1370 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1371 return bgp_attr_malformed (args
,
1372 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1376 /* If it is contained in an UPDATE message that is received from an
1377 external peer, then this attribute MUST be ignored by the
1378 receiving speaker. */
1379 if (peer
->sort
== BGP_PEER_EBGP
)
1381 stream_forward_getp (peer
->ibuf
, length
);
1382 return BGP_ATTR_PARSE_PROCEED
;
1385 attr
->local_pref
= stream_getl (peer
->ibuf
);
1387 /* Set atomic aggregate flag. */
1388 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1390 return BGP_ATTR_PARSE_PROCEED
;
1393 /* Atomic aggregate. */
1395 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1397 struct attr
*const attr
= args
->attr
;
1398 const bgp_size_t length
= args
->length
;
1403 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1404 return bgp_attr_malformed (args
,
1405 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1409 /* Set atomic aggregate flag. */
1410 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1412 return BGP_ATTR_PARSE_PROCEED
;
1415 /* Aggregator attribute */
1417 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1419 struct peer
*const peer
= args
->peer
;
1420 struct attr
*const attr
= args
->attr
;
1421 const bgp_size_t length
= args
->length
;
1424 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1426 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1427 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1430 if (length
!= wantedlen
)
1432 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1433 return bgp_attr_malformed (args
,
1434 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1438 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1439 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1441 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1442 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1444 /* Set atomic aggregate flag. */
1445 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1447 return BGP_ATTR_PARSE_PROCEED
;
1450 /* New Aggregator attribute */
1451 static bgp_attr_parse_ret_t
1452 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1453 as_t
*as4_aggregator_as
,
1454 struct in_addr
*as4_aggregator_addr
)
1456 struct peer
*const peer
= args
->peer
;
1457 struct attr
*const attr
= args
->attr
;
1458 const bgp_size_t length
= args
->length
;
1462 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1463 return bgp_attr_malformed (args
,
1464 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1468 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1469 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1471 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1473 return BGP_ATTR_PARSE_PROCEED
;
1476 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1478 static bgp_attr_parse_ret_t
1479 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1480 struct attr
*const attr
,
1481 struct aspath
*as4_path
, as_t as4_aggregator
,
1482 struct in_addr
*as4_aggregator_addr
)
1484 int ignore_as4_path
= 0;
1485 struct aspath
*newpath
;
1486 struct attr_extra
*attre
= attr
->extra
;
1490 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1491 * checked that all well-known, mandatory attributes were present.
1493 * Can only be a problem with peer itself - hard error
1495 return BGP_ATTR_PARSE_ERROR
;
1498 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1500 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1502 * It is worth a warning though, because the peer really
1503 * should not send them
1505 if (BGP_DEBUG(as4
, AS4
))
1507 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1508 zlog_debug ("[AS4] %s %s AS4_PATH",
1509 peer
->host
, "AS4 capable peer, yet it sent");
1511 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1512 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1513 peer
->host
, "AS4 capable peer, yet it sent");
1516 return BGP_ATTR_PARSE_PROCEED
;
1519 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1520 * because that may override AS4_PATH
1522 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1524 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1529 * if the as_number in aggregator is not AS_TRANS,
1530 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1531 * and the Aggregator shall be taken as
1532 * info on the aggregating node, and the AS_PATH
1533 * shall be taken as the AS_PATH
1535 * the Aggregator shall be ignored and the
1536 * AS4_AGGREGATOR shall be taken as the
1537 * Aggregating node and the AS_PATH is to be
1538 * constructed "as in all other cases"
1540 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1543 if ( BGP_DEBUG(as4
, AS4
))
1544 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1545 " send AGGREGATOR != AS_TRANS and"
1546 " AS4_AGGREGATOR, so ignore"
1547 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1548 ignore_as4_path
= 1;
1552 /* "New_aggregator shall be taken as aggregator" */
1553 attre
->aggregator_as
= as4_aggregator
;
1554 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1559 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1560 * That is bogus - but reading the conditions
1561 * we have to handle AS4_AGGREGATOR as if it were
1562 * AGGREGATOR in that case
1564 if ( BGP_DEBUG(as4
, AS4
))
1565 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1566 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1567 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1568 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1569 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1570 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1574 /* need to reconcile NEW_AS_PATH and AS_PATH */
1575 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1577 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1578 aspath_unintern (&attr
->aspath
);
1579 attr
->aspath
= aspath_intern (newpath
);
1581 return BGP_ATTR_PARSE_PROCEED
;
1584 /* Community attribute. */
1585 static bgp_attr_parse_ret_t
1586 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1588 struct peer
*const peer
= args
->peer
;
1589 struct attr
*const attr
= args
->attr
;
1590 const bgp_size_t length
= args
->length
;
1594 attr
->community
= NULL
;
1595 return BGP_ATTR_PARSE_PROCEED
;
1599 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1601 /* XXX: fix community_parse to use stream API and remove this */
1602 stream_forward_getp (peer
->ibuf
, length
);
1604 if (!attr
->community
)
1605 return bgp_attr_malformed (args
,
1606 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1609 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1611 return BGP_ATTR_PARSE_PROCEED
;
1614 /* Originator ID attribute. */
1615 static bgp_attr_parse_ret_t
1616 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1618 struct peer
*const peer
= args
->peer
;
1619 struct attr
*const attr
= args
->attr
;
1620 const bgp_size_t length
= args
->length
;
1625 zlog_err ("Bad originator ID length %d", length
);
1627 return bgp_attr_malformed (args
,
1628 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1632 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1633 = stream_get_ipv4 (peer
->ibuf
);
1635 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1637 return BGP_ATTR_PARSE_PROCEED
;
1640 /* Cluster list attribute. */
1641 static bgp_attr_parse_ret_t
1642 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1644 struct peer
*const peer
= args
->peer
;
1645 struct attr
*const attr
= args
->attr
;
1646 const bgp_size_t length
= args
->length
;
1651 zlog_err ("Bad cluster list length %d", length
);
1653 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1657 (bgp_attr_extra_get (attr
))->cluster
1658 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1660 /* XXX: Fix cluster_parse to use stream API and then remove this */
1661 stream_forward_getp (peer
->ibuf
, length
);
1663 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1665 return BGP_ATTR_PARSE_PROCEED
;
1668 /* Multiprotocol reachability information parse. */
1670 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1671 struct bgp_nlri
*mp_update
)
1675 bgp_size_t nlri_len
;
1680 struct peer
*const peer
= args
->peer
;
1681 struct attr
*const attr
= args
->attr
;
1682 const bgp_size_t length
= args
->length
;
1683 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1685 /* Set end of packet. */
1686 s
= BGP_INPUT(peer
);
1687 start
= stream_get_getp(s
);
1689 /* safe to read statically sized header? */
1690 #define BGP_MP_REACH_MIN_SIZE 5
1691 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1692 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1694 zlog_info ("%s: %s sent invalid length, %lu",
1695 __func__
, peer
->host
, (unsigned long)length
);
1696 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1699 /* Load AFI, SAFI. */
1700 afi
= stream_getw (s
);
1701 safi
= stream_getc (s
);
1703 /* Get nexthop length. */
1704 attre
->mp_nexthop_len
= stream_getc (s
);
1706 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1708 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1709 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1710 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1713 /* Nexthop length check. */
1714 switch (attre
->mp_nexthop_len
)
1716 case BGP_ATTR_NHLEN_IPV4
:
1717 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1718 /* Probably needed for RFC 2283 */
1719 if (attr
->nexthop
.s_addr
== 0)
1720 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1722 case BGP_ATTR_NHLEN_VPNV4
:
1723 stream_getl (s
); /* RD high */
1724 stream_getl (s
); /* RD low */
1725 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1728 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1729 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1730 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1732 stream_getl (s
); /* RD high */
1733 stream_getl (s
); /* RD low */
1735 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1737 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1738 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1739 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1741 stream_getl (s
); /* RD high */
1742 stream_getl (s
); /* RD low */
1744 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1745 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1747 stream_getl (s
); /* RD high */
1748 stream_getl (s
); /* RD low */
1750 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1751 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1753 char buf1
[INET6_ADDRSTRLEN
];
1754 char buf2
[INET6_ADDRSTRLEN
];
1756 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1757 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1759 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1760 buf1
, INET6_ADDRSTRLEN
),
1761 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1762 buf2
, INET6_ADDRSTRLEN
));
1764 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1767 #endif /* HAVE_IPV6 */
1769 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1770 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1771 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1776 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1777 __func__
, peer
->host
);
1778 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1783 if ((val
= stream_getc (s
)))
1784 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1788 /* must have nrli_len, what is left of the attribute */
1789 nlri_len
= LEN_LEFT
;
1790 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
1792 zlog_info ("%s: (%s) Failed to read NLRI",
1793 __func__
, peer
->host
);
1794 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1797 if (safi
!= SAFI_MPLS_LABELED_VPN
)
1799 ret
= bgp_nlri_sanity_check (peer
, afi
, safi
, stream_pnt (s
),
1800 nlri_len
, &num_mp_pfx
);
1803 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1804 __func__
, peer
->host
);
1805 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1809 mp_update
->afi
= afi
;
1810 mp_update
->safi
= safi
;
1811 mp_update
->nlri
= stream_pnt (s
);
1812 mp_update
->length
= nlri_len
;
1814 stream_forward_getp (s
, nlri_len
);
1816 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
1818 return BGP_ATTR_PARSE_PROCEED
;
1822 /* Multiprotocol unreachable parse */
1824 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
1825 struct bgp_nlri
*mp_withdraw
)
1830 u_int16_t withdraw_len
;
1833 struct peer
*const peer
= args
->peer
;
1834 struct attr
*const attr
= args
->attr
;
1835 const bgp_size_t length
= args
->length
;
1839 #define BGP_MP_UNREACH_MIN_SIZE 3
1840 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1841 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1843 afi
= stream_getw (s
);
1844 safi
= stream_getc (s
);
1846 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1848 if (safi
!= SAFI_MPLS_LABELED_VPN
)
1850 ret
= bgp_nlri_sanity_check (peer
, afi
, safi
, stream_pnt (s
),
1851 withdraw_len
, &num_mp_pfx
);
1853 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1856 mp_withdraw
->afi
= afi
;
1857 mp_withdraw
->safi
= safi
;
1858 mp_withdraw
->nlri
= stream_pnt (s
);
1859 mp_withdraw
->length
= withdraw_len
;
1861 stream_forward_getp (s
, withdraw_len
);
1863 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
1865 return BGP_ATTR_PARSE_PROCEED
;
1868 /* Extended Community attribute. */
1869 static bgp_attr_parse_ret_t
1870 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
1872 struct peer
*const peer
= args
->peer
;
1873 struct attr
*const attr
= args
->attr
;
1874 const bgp_size_t length
= args
->length
;
1879 attr
->extra
->ecommunity
= NULL
;
1880 /* Empty extcomm doesn't seem to be invalid per se */
1881 return BGP_ATTR_PARSE_PROCEED
;
1884 (bgp_attr_extra_get (attr
))->ecommunity
=
1885 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
1886 /* XXX: fix ecommunity_parse to use stream API */
1887 stream_forward_getp (peer
->ibuf
, length
);
1889 if (!attr
->extra
->ecommunity
)
1890 return bgp_attr_malformed (args
,
1891 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1894 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
1896 return BGP_ATTR_PARSE_PROCEED
;
1899 /* Parse Tunnel Encap attribute in an UPDATE */
1903 struct peer
*peer
, /* IN */
1904 bgp_size_t length
, /* IN: attr's length field */
1905 struct attr
*attr
, /* IN: caller already allocated */
1906 u_char flag
, /* IN: attr's flags field */
1910 struct attr_extra
*attre
= NULL
;
1911 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
1912 uint16_t tunneltype
;
1914 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
1916 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
1917 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
1919 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
1920 bgp_notify_send_with_data (peer
,
1921 BGP_NOTIFY_UPDATE_ERR
,
1922 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
1927 if (BGP_ATTR_ENCAP
== type
) {
1928 /* read outer TLV type and length */
1929 uint16_t tlv_length
;
1932 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
1933 bgp_notify_send_with_data(peer
,
1934 BGP_NOTIFY_UPDATE_ERR
,
1935 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1939 tunneltype
= stream_getw (BGP_INPUT (peer
));
1940 tlv_length
= stream_getw (BGP_INPUT (peer
));
1943 if (tlv_length
!= length
) {
1944 zlog_info ("%s: tlv_length(%d) != length(%d)",
1945 __func__
, tlv_length
, length
);
1949 while (length
>= 4) {
1951 uint16_t sublength
= 0;
1952 struct bgp_attr_encap_subtlv
*tlv
;
1954 if (BGP_ATTR_ENCAP
== type
) {
1955 subtype
= stream_getc (BGP_INPUT (peer
));
1956 sublength
= stream_getc (BGP_INPUT (peer
));
1960 if (sublength
> length
) {
1961 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1963 bgp_notify_send_with_data (peer
,
1964 BGP_NOTIFY_UPDATE_ERR
,
1965 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1970 /* alloc and copy sub-tlv */
1971 /* TBD make sure these are freed when attributes are released */
1972 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
1973 tlv
->type
= subtype
;
1974 tlv
->length
= sublength
;
1975 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
1976 length
-= sublength
;
1978 /* attach tlv to encap chain */
1980 attre
= bgp_attr_extra_get(attr
);
1981 if (BGP_ATTR_ENCAP
== type
) {
1982 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
1983 stlv_last
= stlv_last
->next
);
1985 stlv_last
->next
= tlv
;
1987 attre
->encap_subtlvs
= tlv
;
1991 stlv_last
->next
= tlv
;
1996 if (attre
&& (BGP_ATTR_ENCAP
== type
)) {
1997 attre
->encap_tunneltype
= tunneltype
;
2001 /* spurious leftover data */
2002 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2003 bgp_notify_send_with_data (peer
,
2004 BGP_NOTIFY_UPDATE_ERR
,
2005 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2013 /* BGP unknown attribute treatment. */
2014 static bgp_attr_parse_ret_t
2015 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2017 bgp_size_t total
= args
->total
;
2018 struct transit
*transit
;
2019 struct attr_extra
*attre
;
2020 struct peer
*const peer
= args
->peer
;
2021 struct attr
*const attr
= args
->attr
;
2022 u_char
*const startp
= args
->startp
;
2023 const u_char type
= args
->type
;
2024 const u_char flag
= args
->flags
;
2025 const bgp_size_t length
= args
->length
;
2027 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2028 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2029 peer
->host
, type
, length
);
2031 /* Forward read pointer of input stream. */
2032 stream_forward_getp (peer
->ibuf
, length
);
2034 /* If any of the mandatory well-known attributes are not recognized,
2035 then the Error Subcode is set to Unrecognized Well-known
2036 Attribute. The Data field contains the unrecognized attribute
2037 (type, length and value). */
2038 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2040 return bgp_attr_malformed (args
,
2041 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2045 /* Unrecognized non-transitive optional attributes must be quietly
2046 ignored and not passed along to other BGP peers. */
2047 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2048 return BGP_ATTR_PARSE_PROCEED
;
2050 /* If a path with recognized transitive optional attribute is
2051 accepted and passed along to other BGP peers and the Partial bit
2052 in the Attribute Flags octet is set to 1 by some previous AS, it
2053 is not set back to 0 by the current AS. */
2054 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2056 /* Store transitive attribute to the end of attr->transit. */
2057 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2058 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2060 transit
= attre
->transit
;
2063 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2064 transit
->length
+ total
);
2066 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2068 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2069 transit
->length
+= total
;
2071 return BGP_ATTR_PARSE_PROCEED
;
2074 /* Well-known attribute check. */
2076 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2080 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2082 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2083 return BGP_ATTR_PARSE_PROCEED
;
2085 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2086 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2087 are present, it should. Check for any other attribute being present
2090 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2091 return BGP_ATTR_PARSE_PROCEED
;
2093 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2094 type
= BGP_ATTR_ORIGIN
;
2096 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2097 type
= BGP_ATTR_AS_PATH
;
2099 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2100 * NLRI is empty. We can't easily check NLRI empty here though.
2102 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2103 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2104 type
= BGP_ATTR_NEXT_HOP
;
2106 if (peer
->sort
== BGP_PEER_IBGP
2107 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2108 type
= BGP_ATTR_LOCAL_PREF
;
2112 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2113 LOOKUP (attr_str
, type
));
2114 bgp_notify_send_with_data (peer
,
2115 BGP_NOTIFY_UPDATE_ERR
,
2116 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2118 return BGP_ATTR_PARSE_ERROR
;
2120 return BGP_ATTR_PARSE_PROCEED
;
2123 /* Read attribute of update packet. This function is called from
2124 bgp_update_receive() in bgp_packet.c. */
2125 bgp_attr_parse_ret_t
2126 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2127 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2133 u_char
*startp
, *endp
;
2135 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2136 /* we need the as4_path only until we have synthesized the as_path with it */
2137 /* same goes for as4_aggregator */
2138 struct aspath
*as4_path
= NULL
;
2139 as_t as4_aggregator
= 0;
2140 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2142 /* Initialize bitmap. */
2143 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2145 /* End pointer of BGP attribute. */
2146 endp
= BGP_INPUT_PNT (peer
) + size
;
2148 /* Get attributes to the end of attribute length. */
2149 while (BGP_INPUT_PNT (peer
) < endp
)
2151 /* Check remaining length check.*/
2152 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2154 /* XXX warning: long int format, int arg (arg 5) */
2155 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2157 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2159 bgp_notify_send (peer
,
2160 BGP_NOTIFY_UPDATE_ERR
,
2161 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2162 return BGP_ATTR_PARSE_ERROR
;
2165 /* Fetch attribute flag and type. */
2166 startp
= BGP_INPUT_PNT (peer
);
2167 /* "The lower-order four bits of the Attribute Flags octet are
2168 unused. They MUST be zero when sent and MUST be ignored when
2170 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2171 type
= stream_getc (BGP_INPUT (peer
));
2173 /* Check whether Extended-Length applies and is in bounds */
2174 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2175 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2177 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2179 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2181 bgp_notify_send (peer
,
2182 BGP_NOTIFY_UPDATE_ERR
,
2183 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2184 return BGP_ATTR_PARSE_ERROR
;
2187 /* Check extended attribue length bit. */
2188 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2189 length
= stream_getw (BGP_INPUT (peer
));
2191 length
= stream_getc (BGP_INPUT (peer
));
2193 /* If any attribute appears more than once in the UPDATE
2194 message, then the Error Subcode is set to Malformed Attribute
2197 if (CHECK_BITMAP (seen
, type
))
2199 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2202 bgp_notify_send (peer
,
2203 BGP_NOTIFY_UPDATE_ERR
,
2204 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2205 return BGP_ATTR_PARSE_ERROR
;
2208 /* Set type to bitmap to check duplicate attribute. `type' is
2209 unsigned char so it never overflow bitmap range. */
2211 SET_BITMAP (seen
, type
);
2213 /* Overflow check. */
2214 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2216 if (attr_endp
> endp
)
2218 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
);
2219 bgp_notify_send_with_data (peer
,
2220 BGP_NOTIFY_UPDATE_ERR
,
2221 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2222 startp
, attr_endp
- startp
);
2223 return BGP_ATTR_PARSE_ERROR
;
2226 struct bgp_attr_parser_args attr_args
= {
2233 .total
= attr_endp
- startp
,
2237 /* If any recognized attribute has Attribute Flags that conflict
2238 with the Attribute Type Code, then the Error Subcode is set to
2239 Attribute Flags Error. The Data field contains the erroneous
2240 attribute (type, length and value). */
2241 if (bgp_attr_flag_invalid (&attr_args
))
2243 bgp_attr_parse_ret_t ret
;
2244 ret
= bgp_attr_malformed (&attr_args
,
2245 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2247 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2252 /* OK check attribute and store it's value. */
2255 case BGP_ATTR_ORIGIN
:
2256 ret
= bgp_attr_origin (&attr_args
);
2258 case BGP_ATTR_AS_PATH
:
2259 ret
= bgp_attr_aspath (&attr_args
);
2261 case BGP_ATTR_AS4_PATH
:
2262 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2264 case BGP_ATTR_NEXT_HOP
:
2265 ret
= bgp_attr_nexthop (&attr_args
);
2267 case BGP_ATTR_MULTI_EXIT_DISC
:
2268 ret
= bgp_attr_med (&attr_args
);
2270 case BGP_ATTR_LOCAL_PREF
:
2271 ret
= bgp_attr_local_pref (&attr_args
);
2273 case BGP_ATTR_ATOMIC_AGGREGATE
:
2274 ret
= bgp_attr_atomic (&attr_args
);
2276 case BGP_ATTR_AGGREGATOR
:
2277 ret
= bgp_attr_aggregator (&attr_args
);
2279 case BGP_ATTR_AS4_AGGREGATOR
:
2280 ret
= bgp_attr_as4_aggregator (&attr_args
,
2282 &as4_aggregator_addr
);
2284 case BGP_ATTR_COMMUNITIES
:
2285 ret
= bgp_attr_community (&attr_args
);
2287 case BGP_ATTR_ORIGINATOR_ID
:
2288 ret
= bgp_attr_originator_id (&attr_args
);
2290 case BGP_ATTR_CLUSTER_LIST
:
2291 ret
= bgp_attr_cluster_list (&attr_args
);
2293 case BGP_ATTR_MP_REACH_NLRI
:
2294 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2296 case BGP_ATTR_MP_UNREACH_NLRI
:
2297 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2299 case BGP_ATTR_EXT_COMMUNITIES
:
2300 ret
= bgp_attr_ext_communities (&attr_args
);
2302 case BGP_ATTR_ENCAP
:
2303 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2306 ret
= bgp_attr_unknown (&attr_args
);
2310 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2312 bgp_notify_send (peer
,
2313 BGP_NOTIFY_UPDATE_ERR
,
2314 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2315 ret
= BGP_ATTR_PARSE_ERROR
;
2318 /* If hard error occured immediately return to the caller. */
2319 if (ret
== BGP_ATTR_PARSE_ERROR
)
2321 zlog_warn ("%s: Attribute %s, parse error",
2323 LOOKUP (attr_str
, type
));
2325 aspath_unintern (&as4_path
);
2328 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2331 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2333 LOOKUP (attr_str
, type
));
2335 aspath_unintern (&as4_path
);
2339 /* Check the fetched length. */
2340 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2342 zlog_warn ("%s: BGP attribute %s, fetch error",
2343 peer
->host
, LOOKUP (attr_str
, type
));
2344 bgp_notify_send (peer
,
2345 BGP_NOTIFY_UPDATE_ERR
,
2346 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2348 aspath_unintern (&as4_path
);
2349 return BGP_ATTR_PARSE_ERROR
;
2353 /* Check final read pointer is same as end pointer. */
2354 if (BGP_INPUT_PNT (peer
) != endp
)
2356 zlog_warn ("%s: BGP attribute %s, length mismatch",
2357 peer
->host
, LOOKUP (attr_str
, type
));
2358 bgp_notify_send (peer
,
2359 BGP_NOTIFY_UPDATE_ERR
,
2360 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2362 aspath_unintern (&as4_path
);
2363 return BGP_ATTR_PARSE_ERROR
;
2366 /* Check all mandatory well-known attributes are present */
2368 bgp_attr_parse_ret_t ret
;
2369 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2372 aspath_unintern (&as4_path
);
2378 * At this place we can see whether we got AS4_PATH and/or
2379 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2380 * We can not do this before we've read all attributes because
2381 * the as4 handling does not say whether AS4_PATH has to be sent
2382 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2383 * in relationship to AGGREGATOR.
2384 * So, to be defensive, we are not relying on any order and read
2385 * all attributes first, including these 32bit ones, and now,
2386 * afterwards, we look what and if something is to be done for as4.
2388 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2391 /* actually... this doesn't ever return failure currently, but
2392 * better safe than sorry */
2393 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2394 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2395 as4_aggregator
, &as4_aggregator_addr
))
2397 bgp_notify_send (peer
,
2398 BGP_NOTIFY_UPDATE_ERR
,
2399 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2401 aspath_unintern (&as4_path
);
2402 return BGP_ATTR_PARSE_ERROR
;
2405 /* At this stage, we have done all fiddling with as4, and the
2406 * resulting info is in attr->aggregator resp. attr->aspath
2407 * so we can chuck as4_aggregator and as4_path alltogether in
2408 * order to save memory
2412 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2413 /* The flag that we got this is still there, but that does not
2418 * The "rest" of the code does nothing with as4_aggregator.
2419 * there is no memory attached specifically which is not part
2421 * so ignoring just means do nothing.
2424 * Finally do the checks on the aspath we did not do yet
2425 * because we waited for a potentially synthesized aspath.
2427 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2429 ret
= bgp_attr_aspath_check (peer
, attr
);
2430 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2434 /* Finally intern unknown attribute. */
2435 if (attr
->extra
&& attr
->extra
->transit
)
2436 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2438 return BGP_ATTR_PARSE_PROCEED
;
2442 bgp_packet_mpattr_start (struct stream
*s
, afi_t afi
, safi_t safi
, afi_t nh_afi
,
2443 struct bpacket_attr_vec_arr
*vecarr
,
2448 /* Set extended bit always to encode the attribute length as 2 bytes */
2449 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2450 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2451 sizep
= stream_get_endp (s
);
2452 stream_putw (s
, 0); /* Marker: Attribute length. */
2454 stream_putw (s
, afi
);
2455 stream_putc (s
, (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
);
2464 case SAFI_MULTICAST
:
2465 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2467 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2470 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2471 stream_putc (s
, 12);
2472 stream_putl (s
, 0); /* RD = 0, per RFC */
2474 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2478 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2489 case SAFI_MULTICAST
:
2491 struct attr_extra
*attre
= attr
->extra
;
2493 assert (attr
->extra
);
2494 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2495 stream_putc (s
, attre
->mp_nexthop_len
);
2496 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2497 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2498 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2503 struct attr_extra
*attre
= attr
->extra
;
2505 assert (attr
->extra
);
2506 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2507 stream_putc (s
, 24);
2508 stream_putl (s
, 0); /* RD = 0, per RFC */
2510 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2511 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2512 stream_putc (s
, 48);
2513 stream_putl (s
, 0); /* RD = 0, per RFC */
2515 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2516 stream_putl (s
, 0); /* RD = 0, per RFC */
2518 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2523 assert (attr
->extra
);
2524 stream_putc (s
, IPV6_MAX_BYTELEN
);
2525 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2531 #endif /*HAVE_IPV6*/
2542 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2543 struct prefix
*p
, struct prefix_rd
*prd
,
2544 u_char
*tag
, int addpath_encode
,
2545 u_int32_t addpath_tx_id
)
2547 if (safi
== SAFI_MPLS_VPN
)
2550 stream_putl(s
, addpath_tx_id
);
2551 /* Tag, RD, Prefix write. */
2552 stream_putc (s
, p
->prefixlen
+ 88);
2553 stream_put (s
, tag
, 3);
2554 stream_put (s
, prd
->val
, 8);
2555 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2558 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
2562 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
2564 int size
= PSIZE (p
->prefixlen
);
2565 if (safi
== SAFI_MPLS_VPN
)
2571 * Encodes the tunnel encapsulation attribute
2574 bgp_packet_mpattr_tea(
2581 unsigned int attrlenfield
= 0;
2582 unsigned int attrhdrlen
= 0;
2583 struct bgp_attr_encap_subtlv
*subtlvs
;
2584 struct bgp_attr_encap_subtlv
*st
;
2585 const char *attrname
;
2587 if (!attr
|| !attr
->extra
)
2591 case BGP_ATTR_ENCAP
:
2592 attrname
= "Tunnel Encap";
2593 subtlvs
= attr
->extra
->encap_subtlvs
;
2596 * The tunnel encap attr has an "outer" tlv.
2598 * L = total length of subtlvs,
2599 * V = concatenated subtlvs.
2601 attrlenfield
= 2 + 2; /* T + L */
2602 attrhdrlen
= 1 + 1; /* subTLV T + L */
2610 /* if no tlvs, don't make attr */
2611 if (subtlvs
== NULL
)
2614 /* compute attr length */
2615 for (st
= subtlvs
; st
; st
= st
->next
) {
2616 attrlenfield
+= (attrhdrlen
+ st
->length
);
2619 if (attrlenfield
> 0xffff) {
2620 zlog_info ("%s attribute is too long (length=%d), can't send it",
2626 if (attrlenfield
> 0xff) {
2627 /* 2-octet length field */
2629 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2630 stream_putc (s
, attrtype
);
2631 stream_putw (s
, attrlenfield
& 0xffff);
2633 /* 1-octet length field */
2634 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
2635 stream_putc (s
, attrtype
);
2636 stream_putc (s
, attrlenfield
& 0xff);
2639 if (attrtype
== BGP_ATTR_ENCAP
) {
2640 /* write outer T+L */
2641 stream_putw(s
, attr
->extra
->encap_tunneltype
);
2642 stream_putw(s
, attrlenfield
- 4);
2645 /* write each sub-tlv */
2646 for (st
= subtlvs
; st
; st
= st
->next
) {
2647 if (attrtype
== BGP_ATTR_ENCAP
) {
2648 stream_putc (s
, st
->type
);
2649 stream_putc (s
, st
->length
);
2651 stream_put (s
, st
->value
, st
->length
);
2656 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
2658 /* Set MP attribute length. Don't count the (2) bytes used to encode
2660 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
2663 /* Make attribute packet. */
2665 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
2666 struct stream
*s
, struct attr
*attr
,
2667 struct bpacket_attr_vec_arr
*vecarr
,
2668 struct prefix
*p
, afi_t afi
, safi_t safi
,
2669 struct peer
*from
, struct prefix_rd
*prd
, u_char
*tag
,
2671 u_int32_t addpath_tx_id
)
2674 size_t aspath_sizep
;
2675 struct aspath
*aspath
;
2676 int send_as4_path
= 0;
2677 int send_as4_aggregator
= 0;
2678 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2683 /* Remember current pointer. */
2684 cp
= stream_get_endp (s
);
2686 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
2687 !peer_cap_enhe(peer
)))
2689 size_t mpattrlen_pos
= 0;
2691 mpattrlen_pos
= bgp_packet_mpattr_start(s
, afi
, safi
,
2692 (peer_cap_enhe(peer
) ? AFI_IP6
: afi
),
2694 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
2695 addpath_encode
, addpath_tx_id
);
2696 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2699 /* Origin attribute. */
2700 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2701 stream_putc (s
, BGP_ATTR_ORIGIN
);
2703 stream_putc (s
, attr
->origin
);
2705 /* AS path attribute. */
2707 /* If remote-peer is EBGP */
2708 if (peer
->sort
== BGP_PEER_EBGP
2709 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
2710 || attr
->aspath
->segments
== NULL
)
2711 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
2713 aspath
= aspath_dup (attr
->aspath
);
2715 /* Even though we may not be configured for confederations we may have
2716 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2717 aspath
= aspath_delete_confed_seq (aspath
);
2719 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
2721 /* Stuff our path CONFED_ID on the front */
2722 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
2726 if (peer
->change_local_as
) {
2727 /* If replace-as is specified, we only use the change_local_as when
2728 advertising routes. */
2729 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
2730 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2732 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
2734 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2738 else if (peer
->sort
== BGP_PEER_CONFED
)
2740 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2741 aspath
= aspath_dup (attr
->aspath
);
2742 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
2745 aspath
= attr
->aspath
;
2747 /* If peer is not AS4 capable, then:
2748 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2749 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2750 * types are in it (i.e. exclude them if they are there)
2751 * AND do this only if there is at least one asnum > 65535 in the path!
2752 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2753 * all ASnums > 65535 to BGP_AS_TRANS
2756 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2757 stream_putc (s
, BGP_ATTR_AS_PATH
);
2758 aspath_sizep
= stream_get_endp (s
);
2760 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
2762 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2765 if (!use32bit
&& aspath_has_as4 (aspath
))
2766 send_as4_path
= 1; /* we'll do this later, at the correct place */
2768 /* Nexthop attribute. */
2769 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
))
2771 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2773 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2774 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2775 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2777 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2779 else if (safi
== SAFI_UNICAST
&& peer_cap_enhe(from
))
2782 * Likely this is the case when an IPv4 prefix was received with
2783 * Extended Next-hop capability and now being advertised to
2785 * Setting the mandatory (ipv4) next-hop attribute here to enable
2786 * implicit next-hop self with correct (ipv4 address family).
2788 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2789 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2790 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
2792 stream_put_ipv4 (s
, 0);
2796 /* MED attribute. */
2797 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
2800 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2801 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
2803 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
2806 /* Local preference. */
2807 if (peer
->sort
== BGP_PEER_IBGP
||
2808 peer
->sort
== BGP_PEER_CONFED
)
2810 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2811 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
2813 stream_putl (s
, attr
->local_pref
);
2816 /* Atomic aggregate. */
2817 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
2819 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2820 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
2825 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
2827 assert (attr
->extra
);
2829 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
2830 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2831 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
2835 /* AS4 capable peer */
2837 stream_putl (s
, attr
->extra
->aggregator_as
);
2841 /* 2-byte AS peer */
2844 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2845 if ( attr
->extra
->aggregator_as
> 65535 )
2847 stream_putw (s
, BGP_AS_TRANS
);
2849 /* we have to send AS4_AGGREGATOR, too.
2850 * we'll do that later in order to send attributes in ascending
2853 send_as4_aggregator
= 1;
2856 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
2858 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
2861 /* Community attribute. */
2862 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
2863 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
2865 if (attr
->community
->size
* 4 > 255)
2867 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2868 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2869 stream_putw (s
, attr
->community
->size
* 4);
2873 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2874 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2875 stream_putc (s
, attr
->community
->size
* 4);
2877 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
2880 /* Route Reflector. */
2881 if (peer
->sort
== BGP_PEER_IBGP
2883 && from
->sort
== BGP_PEER_IBGP
)
2885 /* Originator ID. */
2886 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2887 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
2890 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
2891 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
2893 stream_put_in_addr (s
, &from
->remote_id
);
2896 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2897 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
2899 if (attr
->extra
&& attr
->extra
->cluster
)
2901 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
2902 /* If this peer configuration's parent BGP has cluster_id. */
2903 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
2904 stream_put_in_addr (s
, &bgp
->cluster_id
);
2906 stream_put_in_addr (s
, &bgp
->router_id
);
2907 stream_put (s
, attr
->extra
->cluster
->list
,
2908 attr
->extra
->cluster
->length
);
2913 /* If this peer configuration's parent BGP has cluster_id. */
2914 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
2915 stream_put_in_addr (s
, &bgp
->cluster_id
);
2917 stream_put_in_addr (s
, &bgp
->router_id
);
2921 /* Extended Communities attribute. */
2922 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
2923 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
2925 struct attr_extra
*attre
= attr
->extra
;
2929 if (peer
->sort
== BGP_PEER_IBGP
2930 || peer
->sort
== BGP_PEER_CONFED
)
2932 if (attre
->ecommunity
->size
* 8 > 255)
2934 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2935 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2936 stream_putw (s
, attre
->ecommunity
->size
* 8);
2940 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2941 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2942 stream_putc (s
, attre
->ecommunity
->size
* 8);
2944 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
2950 int ecom_tr_size
= 0;
2953 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
2955 pnt
= attre
->ecommunity
->val
+ (i
* 8);
2958 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
2966 if (ecom_tr_size
* 8 > 255)
2968 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2969 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2970 stream_putw (s
, ecom_tr_size
* 8);
2974 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2975 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2976 stream_putc (s
, ecom_tr_size
* 8);
2979 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
2981 pnt
= attre
->ecommunity
->val
+ (i
* 8);
2984 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
2987 stream_put (s
, pnt
, 8);
2993 if ( send_as4_path
)
2995 /* If the peer is NOT As4 capable, AND */
2996 /* there are ASnums > 65535 in path THEN
2997 * give out AS4_PATH */
2999 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3001 * Hm, I wonder... confederation things *should* only be at
3002 * the beginning of an aspath, right? Then we should use
3003 * aspath_delete_confed_seq for this, because it is already
3005 * Folks, talk to me: what is reasonable here!?
3007 aspath
= aspath_delete_confed_seq (aspath
);
3009 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3010 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3011 aspath_sizep
= stream_get_endp (s
);
3013 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3016 if (aspath
!= attr
->aspath
)
3017 aspath_free (aspath
);
3019 if ( send_as4_aggregator
)
3021 assert (attr
->extra
);
3023 /* send AS4_AGGREGATOR, at this place */
3024 /* this section of code moved here in order to ensure the correct
3025 * *ascending* order of attributes
3027 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3028 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3030 stream_putl (s
, attr
->extra
->aggregator_as
);
3031 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3034 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3035 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3037 /* Tunnel Encap attribute */
3038 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3041 /* Unknown transit attribute. */
3042 if (attr
->extra
&& attr
->extra
->transit
)
3043 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3045 /* Return total size of attribute. */
3046 return stream_get_endp (s
) - cp
;
3050 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3052 unsigned long attrlen_pnt
;
3054 /* Set extended bit always to encode the attribute length as 2 bytes */
3055 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3056 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3058 attrlen_pnt
= stream_get_endp (s
);
3059 stream_putw (s
, 0); /* Length of this attribute. */
3061 stream_putw (s
, afi
);
3062 stream_putc (s
, (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
);
3067 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3068 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3069 u_char
*tag
, int addpath_encode
,
3070 u_int32_t addpath_tx_id
)
3072 if (safi
== SAFI_MPLS_VPN
)
3076 stream_putl(s
, addpath_tx_id
);
3078 stream_putc (s
, p
->prefixlen
+ 88);
3079 stream_put (s
, tag
, 3);
3080 stream_put (s
, prd
->val
, 8);
3081 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3084 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
3088 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3090 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3093 /* Initialization of attribute. */
3095 bgp_attr_init (void)
3106 bgp_attr_finish (void)
3110 community_finish ();
3111 ecommunity_finish ();
3116 /* Make attribute packet. */
3118 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3119 struct prefix
*prefix
)
3124 struct aspath
*aspath
;
3125 int addpath_encode
= 0;
3126 u_int32_t addpath_tx_id
= 0;
3128 /* Remember current pointer. */
3129 cp
= stream_get_endp (s
);
3131 /* Place holder of length. */
3134 /* Origin attribute. */
3135 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3136 stream_putc (s
, BGP_ATTR_ORIGIN
);
3138 stream_putc (s
, attr
->origin
);
3140 aspath
= attr
->aspath
;
3142 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3143 stream_putc (s
, BGP_ATTR_AS_PATH
);
3144 aspath_lenp
= stream_get_endp (s
);
3147 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3149 /* Nexthop attribute. */
3150 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3153 && prefix
->family
!= AF_INET6
3154 #endif /* HAVE_IPV6 */
3157 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3158 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3160 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3163 /* MED attribute. */
3164 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3166 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3167 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3169 stream_putl (s
, attr
->med
);
3172 /* Local preference. */
3173 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3175 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3176 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3178 stream_putl (s
, attr
->local_pref
);
3181 /* Atomic aggregate. */
3182 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3184 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3185 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3190 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3192 assert (attr
->extra
);
3193 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3194 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3196 stream_putl (s
, attr
->extra
->aggregator_as
);
3197 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3200 /* Community attribute. */
3201 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3203 if (attr
->community
->size
* 4 > 255)
3205 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3206 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3207 stream_putw (s
, attr
->community
->size
* 4);
3211 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3212 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3213 stream_putc (s
, attr
->community
->size
* 4);
3215 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3219 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3220 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3221 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3222 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3225 struct attr_extra
*attre
= attr
->extra
;
3227 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3228 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3229 sizep
= stream_get_endp (s
);
3232 stream_putc (s
, 0); /* Marker: Attribute length. */
3233 stream_putw(s
, AFI_IP6
); /* AFI */
3234 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3237 stream_putc(s
, attre
->mp_nexthop_len
);
3238 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3239 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3240 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3246 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3248 /* Set MP attribute length. */
3249 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3251 #endif /* HAVE_IPV6 */
3253 /* Return total size of attribute. */
3254 len
= stream_get_endp (s
) - cp
- 2;
3255 stream_putw_at (s
, cp
, len
);