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
35 #include "bgpd/bgpd.h"
36 #include "bgpd/bgp_attr.h"
37 #include "bgpd/bgp_route.h"
38 #include "bgpd/bgp_aspath.h"
39 #include "bgpd/bgp_community.h"
40 #include "bgpd/bgp_debug.h"
41 #include "bgpd/bgp_packet.h"
42 #include "bgpd/bgp_ecommunity.h"
43 #include "bgpd/bgp_updgrp.h"
44 #include "bgpd/bgp_encap_types.h"
46 /* Attribute strings for logging. */
47 static const struct message attr_str
[] =
49 { BGP_ATTR_ORIGIN
, "ORIGIN" },
50 { BGP_ATTR_AS_PATH
, "AS_PATH" },
51 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
52 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
53 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
54 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
55 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
56 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
57 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
58 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
59 { BGP_ATTR_DPA
, "DPA" },
60 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
61 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
62 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
63 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
64 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
65 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
66 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
67 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
68 { BGP_ATTR_ENCAP
, "ENCAP" },
70 static const int attr_str_max
= array_size(attr_str
);
72 static const struct message attr_flag_str
[] =
74 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
75 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
76 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
77 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
78 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
81 static struct hash
*cluster_hash
;
84 cluster_hash_alloc (void *p
)
86 const struct cluster_list
*val
= (const struct cluster_list
*) p
;
87 struct cluster_list
*cluster
;
89 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
90 cluster
->length
= val
->length
;
94 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
95 memcpy (cluster
->list
, val
->list
, val
->length
);
105 /* Cluster list related functions. */
106 static struct cluster_list
*
107 cluster_parse (struct in_addr
* pnt
, int length
)
109 struct cluster_list tmp
;
110 struct cluster_list
*cluster
;
115 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
121 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
125 for (i
= 0; i
< cluster
->length
/ 4; i
++)
126 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
132 cluster_hash_key_make (void *p
)
134 const struct cluster_list
*cluster
= p
;
136 return jhash(cluster
->list
, cluster
->length
, 0);
140 cluster_hash_cmp (const void *p1
, const void *p2
)
142 const struct cluster_list
* cluster1
= p1
;
143 const struct cluster_list
* cluster2
= p2
;
145 return (cluster1
->length
== cluster2
->length
&&
146 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
150 cluster_free (struct cluster_list
*cluster
)
153 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
154 XFREE (MTYPE_CLUSTER
, cluster
);
157 static struct cluster_list
*
158 cluster_dup (struct cluster_list
*cluster
)
160 struct cluster_list
*new;
162 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
163 new->length
= cluster
->length
;
167 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
168 memcpy (new->list
, cluster
->list
, cluster
->length
);
176 static struct cluster_list
*
177 cluster_intern (struct cluster_list
*cluster
)
179 struct cluster_list
*find
;
181 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
188 cluster_unintern (struct cluster_list
*cluster
)
193 if (cluster
->refcnt
== 0)
195 hash_release (cluster_hash
, cluster
);
196 cluster_free (cluster
);
203 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
207 cluster_finish (void)
209 hash_free (cluster_hash
);
213 struct bgp_attr_encap_subtlv
*
214 encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
216 struct bgp_attr_encap_subtlv
*new;
217 struct bgp_attr_encap_subtlv
*tail
;
218 struct bgp_attr_encap_subtlv
*p
;
220 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
221 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
223 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
226 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
229 memcpy(tail
, p
, size
);
237 encap_free(struct bgp_attr_encap_subtlv
*p
)
239 struct bgp_attr_encap_subtlv
*next
;
243 XFREE(MTYPE_ENCAP_TLV
, p
);
249 bgp_attr_flush_encap(struct attr
*attr
)
251 if (!attr
|| !attr
->extra
)
254 if (attr
->extra
->encap_subtlvs
) {
255 encap_free(attr
->extra
->encap_subtlvs
);
256 attr
->extra
->encap_subtlvs
= NULL
;
261 * Compare encap sub-tlv chains
266 * This algorithm could be made faster if needed
269 encap_same(struct bgp_attr_encap_subtlv
*h1
, struct bgp_attr_encap_subtlv
*h2
)
271 struct bgp_attr_encap_subtlv
*p
;
272 struct bgp_attr_encap_subtlv
*q
;
283 for (p
= h1
; p
; p
= p
->next
) {
284 for (q
= h2
; q
; q
= q
->next
) {
285 if ((p
->type
== q
->type
) &&
286 (p
->length
== q
->length
) &&
287 !memcmp(p
->value
, q
->value
, p
->length
)) {
296 for (p
= h2
; p
; p
= p
->next
) {
297 for (q
= h1
; q
; q
= q
->next
) {
298 if ((p
->type
== q
->type
) &&
299 (p
->length
== q
->length
) &&
300 !memcmp(p
->value
, q
->value
, p
->length
)) {
312 /* Unknown transit attribute. */
313 static struct hash
*transit_hash
;
316 transit_free (struct transit
*transit
)
319 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
320 XFREE (MTYPE_TRANSIT
, transit
);
323 static struct transit
*
324 transit_dup (struct transit
*transit
)
328 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
329 new->length
= transit
->length
;
332 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
333 memcpy (new->val
, transit
->val
, transit
->length
);
342 transit_hash_alloc (void *p
)
344 /* Transit structure is already allocated. */
348 static struct transit
*
349 transit_intern (struct transit
*transit
)
351 struct transit
*find
;
353 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
355 transit_free (transit
);
362 transit_unintern (struct transit
*transit
)
367 if (transit
->refcnt
== 0)
369 hash_release (transit_hash
, transit
);
370 transit_free (transit
);
375 transit_hash_key_make (void *p
)
377 const struct transit
* transit
= p
;
379 return jhash(transit
->val
, transit
->length
, 0);
383 transit_hash_cmp (const void *p1
, const void *p2
)
385 const struct transit
* transit1
= p1
;
386 const struct transit
* transit2
= p2
;
388 return (transit1
->length
== transit2
->length
&&
389 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
395 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
399 transit_finish (void)
401 hash_free (transit_hash
);
405 /* Attribute hash routines. */
406 static struct hash
*attrhash
;
408 static struct attr_extra
*
409 bgp_attr_extra_new (void)
411 return XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
415 bgp_attr_extra_free (struct attr
*attr
)
419 if (attr
->extra
->encap_subtlvs
) {
420 encap_free(attr
->extra
->encap_subtlvs
);
421 attr
->extra
->encap_subtlvs
= NULL
;
423 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
429 bgp_attr_extra_get (struct attr
*attr
)
432 attr
->extra
= bgp_attr_extra_new();
436 /* Shallow copy of an attribute
437 * Though, not so shallow that it doesn't copy the contents
438 * of the attr_extra pointed to by 'extra'
441 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
443 struct attr_extra
*extra
= new->extra
;
446 /* if caller provided attr_extra space, use it in any case.
448 * This is neccesary even if orig->extra equals NULL, because otherwise
449 * memory may be later allocated on the heap by bgp_attr_extra_get.
451 * That memory would eventually be leaked, because the caller must not
452 * call bgp_attr_extra_free if he provided attr_extra on the stack.
457 memset(new->extra
, 0, sizeof(struct attr_extra
));
459 *new->extra
= *orig
->extra
;
460 if (orig
->extra
->encap_subtlvs
) {
461 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
465 else if (orig
->extra
)
467 new->extra
= bgp_attr_extra_new();
468 *new->extra
= *orig
->extra
;
469 if (orig
->extra
->encap_subtlvs
) {
470 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
476 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
479 new->aspath
= aspath_dup(orig
->aspath
);
482 new->community
= community_dup(orig
->community
);
486 if (orig
->extra
->ecommunity
)
487 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
488 if (orig
->extra
->cluster
)
489 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
490 if (orig
->extra
->transit
)
491 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
496 bgp_attr_deep_free (struct attr
*attr
)
499 aspath_free(attr
->aspath
);
502 community_free(attr
->community
);
506 if (attr
->extra
->ecommunity
)
507 ecommunity_free(&attr
->extra
->ecommunity
);
508 if (attr
->extra
->cluster
)
509 cluster_free(attr
->extra
->cluster
);
510 if (attr
->extra
->transit
)
511 transit_free(attr
->extra
->transit
);
518 return attrhash
->count
;
522 attr_unknown_count (void)
524 return transit_hash
->count
;
528 attrhash_key_make (void *p
)
530 const struct attr
*attr
= (struct attr
*) p
;
531 const struct attr_extra
*extra
= attr
->extra
;
533 #define MIX(val) key = jhash_1word(val, key)
536 MIX(attr
->nexthop
.s_addr
);
538 MIX(attr
->local_pref
);
541 key
+= attr
->nexthop
.s_addr
;
543 key
+= attr
->local_pref
;
547 MIX(extra
->aggregator_as
);
548 MIX(extra
->aggregator_addr
.s_addr
);
550 MIX(extra
->mp_nexthop_global_in
.s_addr
);
551 MIX(extra
->originator_id
.s_addr
);
556 MIX(aspath_key_make (attr
->aspath
));
558 MIX(community_hash_make (attr
->community
));
562 if (extra
->ecommunity
)
563 MIX(ecommunity_hash_make (extra
->ecommunity
));
565 MIX(cluster_hash_key_make (extra
->cluster
));
567 MIX(transit_hash_key_make (extra
->transit
));
570 MIX(extra
->mp_nexthop_len
);
571 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
572 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
573 #endif /* HAVE_IPV6 */
580 attrhash_cmp (const void *p1
, const void *p2
)
582 const struct attr
* attr1
= p1
;
583 const struct attr
* attr2
= p2
;
585 if (attr1
->flag
== attr2
->flag
586 && attr1
->origin
== attr2
->origin
587 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
588 && attr1
->aspath
== attr2
->aspath
589 && attr1
->community
== attr2
->community
590 && attr1
->med
== attr2
->med
591 && attr1
->local_pref
== attr2
->local_pref
592 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
594 const struct attr_extra
*ae1
= attr1
->extra
;
595 const struct attr_extra
*ae2
= attr2
->extra
;
598 && ae1
->aggregator_as
== ae2
->aggregator_as
599 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
600 && ae1
->weight
== ae2
->weight
601 && ae1
->tag
== ae2
->tag
603 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
604 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
605 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
606 #endif /* HAVE_IPV6 */
607 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
608 && ae1
->ecommunity
== ae2
->ecommunity
609 && ae1
->cluster
== ae2
->cluster
610 && ae1
->transit
== ae2
->transit
611 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
612 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
613 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
))
617 /* neither attribute has extra attributes, so they're same */
627 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
631 attrhash_finish (void)
633 hash_free (attrhash
);
638 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
640 struct attr
*attr
= backet
->data
;
642 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
643 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
647 attr_show_all (struct vty
*vty
)
649 hash_iterate (attrhash
,
650 (void (*)(struct hash_backet
*, void *))
651 attr_show_all_iterator
,
656 bgp_attr_hash_alloc (void *p
)
658 const struct attr
* val
= (const struct attr
*) p
;
661 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
665 attr
->extra
= bgp_attr_extra_new ();
666 *attr
->extra
= *val
->extra
;
668 if (attr
->extra
->encap_subtlvs
) {
669 attr
->extra
->encap_subtlvs
= encap_tlv_dup(attr
->extra
->encap_subtlvs
);
676 /* Internet argument attribute. */
678 bgp_attr_intern (struct attr
*attr
)
682 /* Intern referenced strucutre. */
685 if (! attr
->aspath
->refcnt
)
686 attr
->aspath
= aspath_intern (attr
->aspath
);
688 attr
->aspath
->refcnt
++;
692 if (! attr
->community
->refcnt
)
693 attr
->community
= community_intern (attr
->community
);
695 attr
->community
->refcnt
++;
699 struct attr_extra
*attre
= attr
->extra
;
701 if (attre
->ecommunity
)
703 if (! attre
->ecommunity
->refcnt
)
704 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
706 attre
->ecommunity
->refcnt
++;
711 if (! attre
->cluster
->refcnt
)
712 attre
->cluster
= cluster_intern (attre
->cluster
);
714 attre
->cluster
->refcnt
++;
718 if (! attre
->transit
->refcnt
)
719 attre
->transit
= transit_intern (attre
->transit
);
721 attre
->transit
->refcnt
++;
725 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
732 * Increment the refcount on various structures that attr holds.
733 * Note on usage: call _only_ when the 'attr' object has already
734 * been 'intern'ed and exists in 'attrhash' table. The function
735 * serves to hold a reference to that (real) object.
736 * Note also that the caller can safely call bgp_attr_unintern()
737 * after calling bgp_attr_refcount(). That would release the
738 * reference and could result in a free() of the attr object.
741 bgp_attr_refcount (struct attr
*attr
)
743 /* Intern referenced strucutre. */
745 attr
->aspath
->refcnt
++;
748 attr
->community
->refcnt
++;
752 struct attr_extra
*attre
= attr
->extra
;
753 if (attre
->ecommunity
)
754 attre
->ecommunity
->refcnt
++;
757 attre
->cluster
->refcnt
++;
760 attre
->transit
->refcnt
++;
766 /* Make network statement's attribute. */
768 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
770 memset (attr
, 0, sizeof (struct attr
));
771 bgp_attr_extra_get (attr
);
773 attr
->origin
= origin
;
774 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
775 attr
->aspath
= aspath_empty ();
776 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
777 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
778 attr
->extra
->tag
= 0;
779 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
781 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
788 /* Make network statement's attribute. */
790 bgp_attr_default_intern (u_char origin
)
795 memset (&attr
, 0, sizeof (struct attr
));
796 bgp_attr_extra_get (&attr
);
798 bgp_attr_default_set(&attr
, origin
);
800 new = bgp_attr_intern (&attr
);
801 bgp_attr_extra_free (&attr
);
803 aspath_unintern (&new->aspath
);
807 /* Create the attributes for an aggregate */
809 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
810 struct aspath
*aspath
,
811 struct community
*community
, int as_set
,
812 u_char atomic_aggregate
)
816 struct attr_extra attre
;
818 memset (&attr
, 0, sizeof (struct attr
));
819 memset (&attre
, 0, sizeof (struct attr_extra
));
822 /* Origin attribute. */
823 attr
.origin
= origin
;
824 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
826 /* AS path attribute. */
828 attr
.aspath
= aspath_intern (aspath
);
830 attr
.aspath
= aspath_empty ();
831 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
833 /* Next hop attribute. */
834 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
838 attr
.community
= community
;
839 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
842 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
844 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
846 if (! as_set
|| atomic_aggregate
)
847 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
848 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
849 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
850 attre
.aggregator_as
= bgp
->confed_id
;
852 attre
.aggregator_as
= bgp
->as
;
853 attre
.aggregator_addr
= bgp
->router_id
;
855 new = bgp_attr_intern (&attr
);
857 aspath_unintern (&new->aspath
);
861 /* Unintern just the sub-components of the attr, but not the attr */
863 bgp_attr_unintern_sub (struct attr
*attr
)
865 /* aspath refcount shoud be decrement. */
867 aspath_unintern (&attr
->aspath
);
868 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
871 community_unintern (&attr
->community
);
872 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
876 if (attr
->extra
->ecommunity
)
877 ecommunity_unintern (&attr
->extra
->ecommunity
);
878 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
880 if (attr
->extra
->cluster
)
881 cluster_unintern (attr
->extra
->cluster
);
882 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
884 if (attr
->extra
->transit
)
885 transit_unintern (attr
->extra
->transit
);
889 /* Free bgp attribute and aspath. */
891 bgp_attr_unintern (struct attr
**pattr
)
893 struct attr
*attr
= *pattr
;
896 struct attr_extra tmp_extra
;
898 /* Decrement attribute reference. */
905 tmp
.extra
= &tmp_extra
;
906 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
909 /* If reference becomes zero then free attribute object. */
910 if (attr
->refcnt
== 0)
912 ret
= hash_release (attrhash
, attr
);
913 assert (ret
!= NULL
);
914 bgp_attr_extra_free (attr
);
915 XFREE (MTYPE_ATTR
, attr
);
919 bgp_attr_unintern_sub (&tmp
);
923 bgp_attr_flush (struct attr
*attr
)
925 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
926 aspath_free (attr
->aspath
);
927 if (attr
->community
&& ! attr
->community
->refcnt
)
928 community_free (attr
->community
);
931 struct attr_extra
*attre
= attr
->extra
;
933 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
934 ecommunity_free (&attre
->ecommunity
);
935 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
936 cluster_free (attre
->cluster
);
937 if (attre
->transit
&& ! attre
->transit
->refcnt
)
938 transit_free (attre
->transit
);
939 encap_free(attre
->encap_subtlvs
);
940 attre
->encap_subtlvs
= NULL
;
944 /* Implement draft-scudder-idr-optional-transitive behaviour and
945 * avoid resetting sessions for malformed attributes which are
946 * are partial/optional and hence where the error likely was not
947 * introduced by the sending neighbour.
949 static bgp_attr_parse_ret_t
950 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
953 struct peer
*const peer
= args
->peer
;
954 const u_int8_t flags
= args
->flags
;
955 /* startp and length must be special-cased, as whether or not to
956 * send the attribute data with the NOTIFY depends on the error,
957 * the caller therefore signals this with the seperate length argument
959 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
961 /* Only relax error handling for eBGP peers */
962 if (peer
->sort
!= BGP_PEER_EBGP
)
964 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
965 notify_datap
, length
);
966 return BGP_ATTR_PARSE_ERROR
;
970 /* Adjust the stream getp to the end of the attribute, in case we can
971 * still proceed but the caller hasn't read all the attribute.
973 stream_set_getp (BGP_INPUT (peer
),
974 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
977 switch (args
->type
) {
978 /* where an attribute is relatively inconsequential, e.g. it does not
979 * affect route selection, and can be safely ignored, then any such
980 * attributes which are malformed should just be ignored and the route
981 * processed as normal.
983 case BGP_ATTR_AS4_AGGREGATOR
:
984 case BGP_ATTR_AGGREGATOR
:
985 case BGP_ATTR_ATOMIC_AGGREGATE
:
986 return BGP_ATTR_PARSE_PROCEED
;
988 /* Core attributes, particularly ones which may influence route
989 * selection, should always cause session resets
991 case BGP_ATTR_ORIGIN
:
992 case BGP_ATTR_AS_PATH
:
993 case BGP_ATTR_NEXT_HOP
:
994 case BGP_ATTR_MULTI_EXIT_DISC
:
995 case BGP_ATTR_LOCAL_PREF
:
996 case BGP_ATTR_COMMUNITIES
:
997 case BGP_ATTR_ORIGINATOR_ID
:
998 case BGP_ATTR_CLUSTER_LIST
:
999 case BGP_ATTR_MP_REACH_NLRI
:
1000 case BGP_ATTR_MP_UNREACH_NLRI
:
1001 case BGP_ATTR_EXT_COMMUNITIES
:
1002 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1003 notify_datap
, length
);
1004 return BGP_ATTR_PARSE_ERROR
;
1007 /* Partial optional attributes that are malformed should not cause
1008 * the whole session to be reset. Instead treat it as a withdrawal
1009 * of the routes, if possible.
1011 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1012 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1013 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1014 return BGP_ATTR_PARSE_WITHDRAW
;
1016 /* default to reset */
1017 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1020 /* Find out what is wrong with the path attribute flag bits and log the error.
1021 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1022 Extended Length. Checking O/T/P bits at once implies, that the attribute
1023 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1024 non-transitive" attribute. */
1026 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1027 u_int8_t desired_flags
/* how RFC says it must be */
1031 u_char real_flags
= args
->flags
;
1032 const u_int8_t attr_code
= args
->type
;
1034 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1035 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1036 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1039 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1040 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1043 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1044 LOOKUP (attr_str
, attr_code
),
1045 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1046 attr_flag_str
[i
].str
);
1051 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1052 " (real flags 0x%x, desired 0x%x)",
1053 __func__
, LOOKUP (attr_str
, attr_code
),
1054 real_flags
, desired_flags
);
1058 /* Required flags for attributes. EXTLEN will be masked off when testing,
1059 * as will PARTIAL for optional+transitive attributes.
1061 const u_int8_t attr_flags_values
[] = {
1062 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1063 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1064 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1065 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1066 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1067 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1068 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1069 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1070 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1071 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1072 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1073 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1074 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1075 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1076 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1078 static const size_t attr_flags_values_max
=
1079 sizeof (attr_flags_values
) / sizeof (attr_flags_values
[0]);
1082 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1084 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1085 const u_int8_t flags
= args
->flags
;
1086 const u_int8_t attr_code
= args
->type
;
1088 /* there may be attributes we don't know about */
1089 if (attr_code
> attr_flags_values_max
)
1091 if (attr_flags_values
[attr_code
] == 0)
1094 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1097 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1098 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1100 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1101 LOOKUP (attr_str
, attr_code
), flags
);
1105 /* "For well-known attributes and for optional non-transitive attributes,
1106 * the Partial bit MUST be set to 0."
1108 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1110 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1112 zlog_err ("%s well-known attribute "
1113 "must NOT have the partial flag set (%x)",
1114 LOOKUP (attr_str
, attr_code
), flags
);
1117 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1118 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1120 zlog_err ("%s optional + transitive attribute "
1121 "must NOT have the partial flag set (%x)",
1122 LOOKUP (attr_str
, attr_code
), flags
);
1127 /* Optional transitive attributes may go through speakers that don't
1128 * reocgnise them and set the Partial bit.
1130 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1131 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1132 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1135 == attr_flags_values
[attr_code
])
1138 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1142 /* Get origin attribute of the update message. */
1143 static bgp_attr_parse_ret_t
1144 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1146 struct peer
*const peer
= args
->peer
;
1147 struct attr
*const attr
= args
->attr
;
1148 const bgp_size_t length
= args
->length
;
1150 /* If any recognized attribute has Attribute Length that conflicts
1151 with the expected length (based on the attribute type code), then
1152 the Error Subcode is set to Attribute Length Error. The Data
1153 field contains the erroneous attribute (type, length and
1157 zlog_err ("Origin attribute length is not one %d", length
);
1158 return bgp_attr_malformed (args
,
1159 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1163 /* Fetch origin attribute. */
1164 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1166 /* If the ORIGIN attribute has an undefined value, then the Error
1167 Subcode is set to Invalid Origin Attribute. The Data field
1168 contains the unrecognized attribute (type, length and value). */
1169 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1170 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1171 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1173 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1174 return bgp_attr_malformed (args
,
1175 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1179 /* Set oring attribute flag. */
1180 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1185 /* Parse AS path information. This function is wrapper of
1188 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1190 struct attr
*const attr
= args
->attr
;
1191 struct peer
*const peer
= args
->peer
;
1192 const bgp_size_t length
= args
->length
;
1195 * peer with AS4 => will get 4Byte ASnums
1196 * otherwise, will get 16 Bit
1198 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1199 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1201 /* In case of IBGP, length will be zero. */
1204 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1205 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1208 /* Set aspath attribute flag. */
1209 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1211 return BGP_ATTR_PARSE_PROCEED
;
1214 static bgp_attr_parse_ret_t
1215 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1217 /* These checks were part of bgp_attr_aspath, but with
1218 * as4 we should to check aspath things when
1219 * aspath synthesizing with as4_path has already taken place.
1220 * Otherwise we check ASPATH and use the synthesized thing, and that is
1222 * So do the checks later, i.e. here
1224 struct bgp
*bgp
= peer
->bgp
;
1225 struct aspath
*aspath
;
1227 /* Confederation sanity check. */
1228 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1229 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1231 zlog_err ("Malformed AS path from %s", peer
->host
);
1232 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1233 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1234 return BGP_ATTR_PARSE_ERROR
;
1237 /* First AS check for EBGP. */
1238 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1240 if (peer
->sort
== BGP_PEER_EBGP
1241 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1243 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1244 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1245 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1246 return BGP_ATTR_PARSE_ERROR
;
1250 /* local-as prepend */
1251 if (peer
->change_local_as
&&
1252 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1254 aspath
= aspath_dup (attr
->aspath
);
1255 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1256 aspath_unintern (&attr
->aspath
);
1257 attr
->aspath
= aspath_intern (aspath
);
1260 return BGP_ATTR_PARSE_PROCEED
;
1263 /* Parse AS4 path information. This function is another wrapper of
1266 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1268 struct peer
*const peer
= args
->peer
;
1269 struct attr
*const attr
= args
->attr
;
1270 const bgp_size_t length
= args
->length
;
1272 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1274 /* In case of IBGP, length will be zero. */
1277 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1278 return bgp_attr_malformed (args
,
1279 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1283 /* Set aspath attribute flag. */
1285 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1287 return BGP_ATTR_PARSE_PROCEED
;
1290 /* Nexthop attribute. */
1291 static bgp_attr_parse_ret_t
1292 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1294 struct peer
*const peer
= args
->peer
;
1295 struct attr
*const attr
= args
->attr
;
1296 const bgp_size_t length
= args
->length
;
1298 in_addr_t nexthop_h
, nexthop_n
;
1300 /* Check nexthop attribute length. */
1303 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1305 return bgp_attr_malformed (args
,
1306 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1310 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1311 attribute must result in a NOTIFICATION message (this is implemented below).
1312 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1313 logged locally (this is implemented somewhere else). The UPDATE message
1314 gets ignored in any of these cases. */
1315 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1316 nexthop_h
= ntohl (nexthop_n
);
1317 if (IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1319 char buf
[INET_ADDRSTRLEN
];
1320 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1321 zlog_err ("Martian nexthop %s", buf
);
1322 return bgp_attr_malformed (args
,
1323 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1327 attr
->nexthop
.s_addr
= nexthop_n
;
1328 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1330 return BGP_ATTR_PARSE_PROCEED
;
1333 /* MED atrribute. */
1334 static bgp_attr_parse_ret_t
1335 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1337 struct peer
*const peer
= args
->peer
;
1338 struct attr
*const attr
= args
->attr
;
1339 const bgp_size_t length
= args
->length
;
1344 zlog_err ("MED attribute length isn't four [%d]", length
);
1346 return bgp_attr_malformed (args
,
1347 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1351 attr
->med
= stream_getl (peer
->ibuf
);
1353 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1355 return BGP_ATTR_PARSE_PROCEED
;
1358 /* Local preference attribute. */
1359 static bgp_attr_parse_ret_t
1360 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1362 struct peer
*const peer
= args
->peer
;
1363 struct attr
*const attr
= args
->attr
;
1364 const bgp_size_t length
= args
->length
;
1369 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1370 return bgp_attr_malformed (args
,
1371 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1375 /* If it is contained in an UPDATE message that is received from an
1376 external peer, then this attribute MUST be ignored by the
1377 receiving speaker. */
1378 if (peer
->sort
== BGP_PEER_EBGP
)
1380 stream_forward_getp (peer
->ibuf
, length
);
1381 return BGP_ATTR_PARSE_PROCEED
;
1384 attr
->local_pref
= stream_getl (peer
->ibuf
);
1386 /* Set atomic aggregate flag. */
1387 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1389 return BGP_ATTR_PARSE_PROCEED
;
1392 /* Atomic aggregate. */
1394 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1396 struct attr
*const attr
= args
->attr
;
1397 const bgp_size_t length
= args
->length
;
1402 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1403 return bgp_attr_malformed (args
,
1404 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1408 /* Set atomic aggregate flag. */
1409 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1411 return BGP_ATTR_PARSE_PROCEED
;
1414 /* Aggregator attribute */
1416 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1418 struct peer
*const peer
= args
->peer
;
1419 struct attr
*const attr
= args
->attr
;
1420 const bgp_size_t length
= args
->length
;
1423 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1425 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1426 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1429 if (length
!= wantedlen
)
1431 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1432 return bgp_attr_malformed (args
,
1433 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1437 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1438 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1440 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1441 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1443 /* Set atomic aggregate flag. */
1444 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1446 return BGP_ATTR_PARSE_PROCEED
;
1449 /* New Aggregator attribute */
1450 static bgp_attr_parse_ret_t
1451 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1452 as_t
*as4_aggregator_as
,
1453 struct in_addr
*as4_aggregator_addr
)
1455 struct peer
*const peer
= args
->peer
;
1456 struct attr
*const attr
= args
->attr
;
1457 const bgp_size_t length
= args
->length
;
1461 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1462 return bgp_attr_malformed (args
,
1463 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1467 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1468 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1470 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1472 return BGP_ATTR_PARSE_PROCEED
;
1475 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1477 static bgp_attr_parse_ret_t
1478 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1479 struct attr
*const attr
,
1480 struct aspath
*as4_path
, as_t as4_aggregator
,
1481 struct in_addr
*as4_aggregator_addr
)
1483 int ignore_as4_path
= 0;
1484 struct aspath
*newpath
;
1485 struct attr_extra
*attre
= attr
->extra
;
1489 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1490 * checked that all well-known, mandatory attributes were present.
1492 * Can only be a problem with peer itself - hard error
1494 return BGP_ATTR_PARSE_ERROR
;
1497 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1499 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1501 * It is worth a warning though, because the peer really
1502 * should not send them
1504 if (BGP_DEBUG(as4
, AS4
))
1506 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1507 zlog_debug ("[AS4] %s %s AS4_PATH",
1508 peer
->host
, "AS4 capable peer, yet it sent");
1510 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1511 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1512 peer
->host
, "AS4 capable peer, yet it sent");
1515 return BGP_ATTR_PARSE_PROCEED
;
1518 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1519 * because that may override AS4_PATH
1521 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1523 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1528 * if the as_number in aggregator is not AS_TRANS,
1529 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1530 * and the Aggregator shall be taken as
1531 * info on the aggregating node, and the AS_PATH
1532 * shall be taken as the AS_PATH
1534 * the Aggregator shall be ignored and the
1535 * AS4_AGGREGATOR shall be taken as the
1536 * Aggregating node and the AS_PATH is to be
1537 * constructed "as in all other cases"
1539 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1542 if ( BGP_DEBUG(as4
, AS4
))
1543 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1544 " send AGGREGATOR != AS_TRANS and"
1545 " AS4_AGGREGATOR, so ignore"
1546 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1547 ignore_as4_path
= 1;
1551 /* "New_aggregator shall be taken as aggregator" */
1552 attre
->aggregator_as
= as4_aggregator
;
1553 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1558 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1559 * That is bogus - but reading the conditions
1560 * we have to handle AS4_AGGREGATOR as if it were
1561 * AGGREGATOR in that case
1563 if ( BGP_DEBUG(as4
, AS4
))
1564 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1565 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1566 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1567 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1568 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1569 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1573 /* need to reconcile NEW_AS_PATH and AS_PATH */
1574 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1576 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1577 aspath_unintern (&attr
->aspath
);
1578 attr
->aspath
= aspath_intern (newpath
);
1580 return BGP_ATTR_PARSE_PROCEED
;
1583 /* Community attribute. */
1584 static bgp_attr_parse_ret_t
1585 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1587 struct peer
*const peer
= args
->peer
;
1588 struct attr
*const attr
= args
->attr
;
1589 const bgp_size_t length
= args
->length
;
1593 attr
->community
= NULL
;
1594 return BGP_ATTR_PARSE_PROCEED
;
1598 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1600 /* XXX: fix community_parse to use stream API and remove this */
1601 stream_forward_getp (peer
->ibuf
, length
);
1603 if (!attr
->community
)
1604 return bgp_attr_malformed (args
,
1605 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1608 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1610 return BGP_ATTR_PARSE_PROCEED
;
1613 /* Originator ID attribute. */
1614 static bgp_attr_parse_ret_t
1615 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1617 struct peer
*const peer
= args
->peer
;
1618 struct attr
*const attr
= args
->attr
;
1619 const bgp_size_t length
= args
->length
;
1624 zlog_err ("Bad originator ID length %d", length
);
1626 return bgp_attr_malformed (args
,
1627 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1631 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1632 = stream_get_ipv4 (peer
->ibuf
);
1634 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1636 return BGP_ATTR_PARSE_PROCEED
;
1639 /* Cluster list attribute. */
1640 static bgp_attr_parse_ret_t
1641 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1643 struct peer
*const peer
= args
->peer
;
1644 struct attr
*const attr
= args
->attr
;
1645 const bgp_size_t length
= args
->length
;
1650 zlog_err ("Bad cluster list length %d", length
);
1652 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1656 (bgp_attr_extra_get (attr
))->cluster
1657 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1659 /* XXX: Fix cluster_parse to use stream API and then remove this */
1660 stream_forward_getp (peer
->ibuf
, length
);
1662 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1664 return BGP_ATTR_PARSE_PROCEED
;
1667 /* Multiprotocol reachability information parse. */
1669 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1670 struct bgp_nlri
*mp_update
)
1674 bgp_size_t nlri_len
;
1679 struct peer
*const peer
= args
->peer
;
1680 struct attr
*const attr
= args
->attr
;
1681 const bgp_size_t length
= args
->length
;
1682 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1684 /* Set end of packet. */
1685 s
= BGP_INPUT(peer
);
1686 start
= stream_get_getp(s
);
1688 /* safe to read statically sized header? */
1689 #define BGP_MP_REACH_MIN_SIZE 5
1690 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1691 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1693 zlog_info ("%s: %s sent invalid length, %lu",
1694 __func__
, peer
->host
, (unsigned long)length
);
1695 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1698 /* Load AFI, SAFI. */
1699 afi
= stream_getw (s
);
1700 safi
= stream_getc (s
);
1702 /* Get nexthop length. */
1703 attre
->mp_nexthop_len
= stream_getc (s
);
1705 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1707 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1708 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1709 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1712 /* Nexthop length check. */
1713 switch (attre
->mp_nexthop_len
)
1715 case BGP_ATTR_NHLEN_IPV4
:
1716 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1717 /* Probably needed for RFC 2283 */
1718 if (attr
->nexthop
.s_addr
== 0)
1719 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1721 case BGP_ATTR_NHLEN_VPNV4
:
1722 stream_getl (s
); /* RD high */
1723 stream_getl (s
); /* RD low */
1724 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1727 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1728 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1729 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1731 stream_getl (s
); /* RD high */
1732 stream_getl (s
); /* RD low */
1734 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1736 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1737 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1738 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1740 stream_getl (s
); /* RD high */
1741 stream_getl (s
); /* RD low */
1743 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1744 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1746 stream_getl (s
); /* RD high */
1747 stream_getl (s
); /* RD low */
1749 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1750 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1752 char buf1
[INET6_ADDRSTRLEN
];
1753 char buf2
[INET6_ADDRSTRLEN
];
1755 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1756 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1758 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1759 buf1
, INET6_ADDRSTRLEN
),
1760 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1761 buf2
, INET6_ADDRSTRLEN
));
1763 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1766 #endif /* HAVE_IPV6 */
1768 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1769 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1770 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1775 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1776 __func__
, peer
->host
);
1777 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1782 if ((val
= stream_getc (s
)))
1783 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1787 /* must have nrli_len, what is left of the attribute */
1788 nlri_len
= LEN_LEFT
;
1789 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
1791 zlog_info ("%s: (%s) Failed to read NLRI",
1792 __func__
, peer
->host
);
1793 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1796 if (safi
!= SAFI_MPLS_LABELED_VPN
)
1798 ret
= bgp_nlri_sanity_check (peer
, afi
, safi
, stream_pnt (s
),
1799 nlri_len
, &num_mp_pfx
);
1802 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1803 __func__
, peer
->host
);
1804 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1808 mp_update
->afi
= afi
;
1809 mp_update
->safi
= safi
;
1810 mp_update
->nlri
= stream_pnt (s
);
1811 mp_update
->length
= nlri_len
;
1813 stream_forward_getp (s
, nlri_len
);
1815 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
1817 return BGP_ATTR_PARSE_PROCEED
;
1821 /* Multiprotocol unreachable parse */
1823 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
1824 struct bgp_nlri
*mp_withdraw
)
1829 u_int16_t withdraw_len
;
1832 struct peer
*const peer
= args
->peer
;
1833 struct attr
*const attr
= args
->attr
;
1834 const bgp_size_t length
= args
->length
;
1838 #define BGP_MP_UNREACH_MIN_SIZE 3
1839 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1840 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1842 afi
= stream_getw (s
);
1843 safi
= stream_getc (s
);
1845 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1847 if (safi
!= SAFI_MPLS_LABELED_VPN
)
1849 ret
= bgp_nlri_sanity_check (peer
, afi
, safi
, stream_pnt (s
),
1850 withdraw_len
, &num_mp_pfx
);
1852 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1855 mp_withdraw
->afi
= afi
;
1856 mp_withdraw
->safi
= safi
;
1857 mp_withdraw
->nlri
= stream_pnt (s
);
1858 mp_withdraw
->length
= withdraw_len
;
1860 stream_forward_getp (s
, withdraw_len
);
1862 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
1864 return BGP_ATTR_PARSE_PROCEED
;
1867 /* Extended Community attribute. */
1868 static bgp_attr_parse_ret_t
1869 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
1871 struct peer
*const peer
= args
->peer
;
1872 struct attr
*const attr
= args
->attr
;
1873 const bgp_size_t length
= args
->length
;
1878 attr
->extra
->ecommunity
= NULL
;
1879 /* Empty extcomm doesn't seem to be invalid per se */
1880 return BGP_ATTR_PARSE_PROCEED
;
1883 (bgp_attr_extra_get (attr
))->ecommunity
=
1884 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
1885 /* XXX: fix ecommunity_parse to use stream API */
1886 stream_forward_getp (peer
->ibuf
, length
);
1888 if (!attr
->extra
->ecommunity
)
1889 return bgp_attr_malformed (args
,
1890 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1893 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
1895 return BGP_ATTR_PARSE_PROCEED
;
1898 /* Parse Tunnel Encap attribute in an UPDATE */
1902 struct peer
*peer
, /* IN */
1903 bgp_size_t length
, /* IN: attr's length field */
1904 struct attr
*attr
, /* IN: caller already allocated */
1905 u_char flag
, /* IN: attr's flags field */
1909 struct attr_extra
*attre
= NULL
;
1910 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
1911 uint16_t tunneltype
;
1913 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
1915 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
1916 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
1918 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
1919 bgp_notify_send_with_data (peer
,
1920 BGP_NOTIFY_UPDATE_ERR
,
1921 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
1926 if (BGP_ATTR_ENCAP
== type
) {
1927 /* read outer TLV type and length */
1928 uint16_t tlv_length
;
1931 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
1932 bgp_notify_send_with_data(peer
,
1933 BGP_NOTIFY_UPDATE_ERR
,
1934 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1938 tunneltype
= stream_getw (BGP_INPUT (peer
));
1939 tlv_length
= stream_getw (BGP_INPUT (peer
));
1942 if (tlv_length
!= length
) {
1943 zlog_info ("%s: tlv_length(%d) != length(%d)",
1944 __func__
, tlv_length
, length
);
1948 while (length
>= 4) {
1951 struct bgp_attr_encap_subtlv
*tlv
;
1953 subtype
= stream_getw (BGP_INPUT (peer
));
1954 sublength
= stream_getw (BGP_INPUT (peer
));
1957 if (sublength
> length
) {
1958 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1960 bgp_notify_send_with_data (peer
,
1961 BGP_NOTIFY_UPDATE_ERR
,
1962 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1967 /* alloc and copy sub-tlv */
1968 /* TBD make sure these are freed when attributes are released */
1969 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
1970 tlv
->type
= subtype
;
1971 tlv
->length
= sublength
;
1972 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
1973 length
-= sublength
;
1975 /* attach tlv to encap chain */
1977 attre
= bgp_attr_extra_get(attr
);
1978 if (BGP_ATTR_ENCAP
== type
) {
1979 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
1980 stlv_last
= stlv_last
->next
);
1982 stlv_last
->next
= tlv
;
1984 attre
->encap_subtlvs
= tlv
;
1988 stlv_last
->next
= tlv
;
1993 if (attre
&& (BGP_ATTR_ENCAP
== type
)) {
1994 attre
->encap_tunneltype
= tunneltype
;
1998 /* spurious leftover data */
1999 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2000 bgp_notify_send_with_data (peer
,
2001 BGP_NOTIFY_UPDATE_ERR
,
2002 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2010 /* BGP unknown attribute treatment. */
2011 static bgp_attr_parse_ret_t
2012 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2014 bgp_size_t total
= args
->total
;
2015 struct transit
*transit
;
2016 struct attr_extra
*attre
;
2017 struct peer
*const peer
= args
->peer
;
2018 struct attr
*const attr
= args
->attr
;
2019 u_char
*const startp
= args
->startp
;
2020 const u_char type
= args
->type
;
2021 const u_char flag
= args
->flags
;
2022 const bgp_size_t length
= args
->length
;
2024 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2025 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2026 peer
->host
, type
, length
);
2028 /* Forward read pointer of input stream. */
2029 stream_forward_getp (peer
->ibuf
, length
);
2031 /* If any of the mandatory well-known attributes are not recognized,
2032 then the Error Subcode is set to Unrecognized Well-known
2033 Attribute. The Data field contains the unrecognized attribute
2034 (type, length and value). */
2035 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2037 return bgp_attr_malformed (args
,
2038 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2042 /* Unrecognized non-transitive optional attributes must be quietly
2043 ignored and not passed along to other BGP peers. */
2044 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2045 return BGP_ATTR_PARSE_PROCEED
;
2047 /* If a path with recognized transitive optional attribute is
2048 accepted and passed along to other BGP peers and the Partial bit
2049 in the Attribute Flags octet is set to 1 by some previous AS, it
2050 is not set back to 0 by the current AS. */
2051 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2053 /* Store transitive attribute to the end of attr->transit. */
2054 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2055 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2057 transit
= attre
->transit
;
2060 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2061 transit
->length
+ total
);
2063 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2065 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2066 transit
->length
+= total
;
2068 return BGP_ATTR_PARSE_PROCEED
;
2071 /* Well-known attribute check. */
2073 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2077 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2079 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2080 return BGP_ATTR_PARSE_PROCEED
;
2082 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2083 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2084 are present, it should. Check for any other attribute being present
2087 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2088 return BGP_ATTR_PARSE_PROCEED
;
2090 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2091 type
= BGP_ATTR_ORIGIN
;
2093 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2094 type
= BGP_ATTR_AS_PATH
;
2096 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2097 * NLRI is empty. We can't easily check NLRI empty here though.
2099 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2100 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2101 type
= BGP_ATTR_NEXT_HOP
;
2103 if (peer
->sort
== BGP_PEER_IBGP
2104 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2105 type
= BGP_ATTR_LOCAL_PREF
;
2109 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2110 LOOKUP (attr_str
, type
));
2111 bgp_notify_send_with_data (peer
,
2112 BGP_NOTIFY_UPDATE_ERR
,
2113 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2115 return BGP_ATTR_PARSE_ERROR
;
2117 return BGP_ATTR_PARSE_PROCEED
;
2120 /* Read attribute of update packet. This function is called from
2121 bgp_update_receive() in bgp_packet.c. */
2122 bgp_attr_parse_ret_t
2123 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2124 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2130 u_char
*startp
, *endp
;
2132 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2133 /* we need the as4_path only until we have synthesized the as_path with it */
2134 /* same goes for as4_aggregator */
2135 struct aspath
*as4_path
= NULL
;
2136 as_t as4_aggregator
= 0;
2137 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2139 /* Initialize bitmap. */
2140 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2142 /* End pointer of BGP attribute. */
2143 endp
= BGP_INPUT_PNT (peer
) + size
;
2145 /* Get attributes to the end of attribute length. */
2146 while (BGP_INPUT_PNT (peer
) < endp
)
2148 /* Check remaining length check.*/
2149 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2151 /* XXX warning: long int format, int arg (arg 5) */
2152 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2154 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2156 bgp_notify_send (peer
,
2157 BGP_NOTIFY_UPDATE_ERR
,
2158 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2159 return BGP_ATTR_PARSE_ERROR
;
2162 /* Fetch attribute flag and type. */
2163 startp
= BGP_INPUT_PNT (peer
);
2164 /* "The lower-order four bits of the Attribute Flags octet are
2165 unused. They MUST be zero when sent and MUST be ignored when
2167 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2168 type
= stream_getc (BGP_INPUT (peer
));
2170 /* Check whether Extended-Length applies and is in bounds */
2171 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2172 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2174 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2176 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2178 bgp_notify_send (peer
,
2179 BGP_NOTIFY_UPDATE_ERR
,
2180 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2181 return BGP_ATTR_PARSE_ERROR
;
2184 /* Check extended attribue length bit. */
2185 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2186 length
= stream_getw (BGP_INPUT (peer
));
2188 length
= stream_getc (BGP_INPUT (peer
));
2190 /* If any attribute appears more than once in the UPDATE
2191 message, then the Error Subcode is set to Malformed Attribute
2194 if (CHECK_BITMAP (seen
, type
))
2196 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2199 bgp_notify_send (peer
,
2200 BGP_NOTIFY_UPDATE_ERR
,
2201 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2202 return BGP_ATTR_PARSE_ERROR
;
2205 /* Set type to bitmap to check duplicate attribute. `type' is
2206 unsigned char so it never overflow bitmap range. */
2208 SET_BITMAP (seen
, type
);
2210 /* Overflow check. */
2211 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2213 if (attr_endp
> endp
)
2215 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
);
2216 bgp_notify_send_with_data (peer
,
2217 BGP_NOTIFY_UPDATE_ERR
,
2218 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2219 startp
, attr_endp
- startp
);
2220 return BGP_ATTR_PARSE_ERROR
;
2223 struct bgp_attr_parser_args attr_args
= {
2230 .total
= attr_endp
- startp
,
2234 /* If any recognized attribute has Attribute Flags that conflict
2235 with the Attribute Type Code, then the Error Subcode is set to
2236 Attribute Flags Error. The Data field contains the erroneous
2237 attribute (type, length and value). */
2238 if (bgp_attr_flag_invalid (&attr_args
))
2240 bgp_attr_parse_ret_t ret
;
2241 ret
= bgp_attr_malformed (&attr_args
,
2242 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2244 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2249 /* OK check attribute and store it's value. */
2252 case BGP_ATTR_ORIGIN
:
2253 ret
= bgp_attr_origin (&attr_args
);
2255 case BGP_ATTR_AS_PATH
:
2256 ret
= bgp_attr_aspath (&attr_args
);
2258 case BGP_ATTR_AS4_PATH
:
2259 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2261 case BGP_ATTR_NEXT_HOP
:
2262 ret
= bgp_attr_nexthop (&attr_args
);
2264 case BGP_ATTR_MULTI_EXIT_DISC
:
2265 ret
= bgp_attr_med (&attr_args
);
2267 case BGP_ATTR_LOCAL_PREF
:
2268 ret
= bgp_attr_local_pref (&attr_args
);
2270 case BGP_ATTR_ATOMIC_AGGREGATE
:
2271 ret
= bgp_attr_atomic (&attr_args
);
2273 case BGP_ATTR_AGGREGATOR
:
2274 ret
= bgp_attr_aggregator (&attr_args
);
2276 case BGP_ATTR_AS4_AGGREGATOR
:
2277 ret
= bgp_attr_as4_aggregator (&attr_args
,
2279 &as4_aggregator_addr
);
2281 case BGP_ATTR_COMMUNITIES
:
2282 ret
= bgp_attr_community (&attr_args
);
2284 case BGP_ATTR_ORIGINATOR_ID
:
2285 ret
= bgp_attr_originator_id (&attr_args
);
2287 case BGP_ATTR_CLUSTER_LIST
:
2288 ret
= bgp_attr_cluster_list (&attr_args
);
2290 case BGP_ATTR_MP_REACH_NLRI
:
2291 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2293 case BGP_ATTR_MP_UNREACH_NLRI
:
2294 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2296 case BGP_ATTR_EXT_COMMUNITIES
:
2297 ret
= bgp_attr_ext_communities (&attr_args
);
2299 case BGP_ATTR_ENCAP
:
2300 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2303 ret
= bgp_attr_unknown (&attr_args
);
2307 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2309 bgp_notify_send (peer
,
2310 BGP_NOTIFY_UPDATE_ERR
,
2311 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2312 ret
= BGP_ATTR_PARSE_ERROR
;
2315 /* If hard error occured immediately return to the caller. */
2316 if (ret
== BGP_ATTR_PARSE_ERROR
)
2318 zlog_warn ("%s: Attribute %s, parse error",
2320 LOOKUP (attr_str
, type
));
2322 aspath_unintern (&as4_path
);
2325 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2328 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2330 LOOKUP (attr_str
, type
));
2332 aspath_unintern (&as4_path
);
2336 /* Check the fetched length. */
2337 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2339 zlog_warn ("%s: BGP attribute %s, fetch error",
2340 peer
->host
, LOOKUP (attr_str
, type
));
2341 bgp_notify_send (peer
,
2342 BGP_NOTIFY_UPDATE_ERR
,
2343 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2345 aspath_unintern (&as4_path
);
2346 return BGP_ATTR_PARSE_ERROR
;
2350 /* Check final read pointer is same as end pointer. */
2351 if (BGP_INPUT_PNT (peer
) != endp
)
2353 zlog_warn ("%s: BGP attribute %s, length mismatch",
2354 peer
->host
, LOOKUP (attr_str
, type
));
2355 bgp_notify_send (peer
,
2356 BGP_NOTIFY_UPDATE_ERR
,
2357 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2359 aspath_unintern (&as4_path
);
2360 return BGP_ATTR_PARSE_ERROR
;
2363 /* Check all mandatory well-known attributes are present */
2365 bgp_attr_parse_ret_t ret
;
2366 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2369 aspath_unintern (&as4_path
);
2375 * At this place we can see whether we got AS4_PATH and/or
2376 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2377 * We can not do this before we've read all attributes because
2378 * the as4 handling does not say whether AS4_PATH has to be sent
2379 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2380 * in relationship to AGGREGATOR.
2381 * So, to be defensive, we are not relying on any order and read
2382 * all attributes first, including these 32bit ones, and now,
2383 * afterwards, we look what and if something is to be done for as4.
2385 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2388 /* actually... this doesn't ever return failure currently, but
2389 * better safe than sorry */
2390 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2391 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2392 as4_aggregator
, &as4_aggregator_addr
))
2394 bgp_notify_send (peer
,
2395 BGP_NOTIFY_UPDATE_ERR
,
2396 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2398 aspath_unintern (&as4_path
);
2399 return BGP_ATTR_PARSE_ERROR
;
2402 /* At this stage, we have done all fiddling with as4, and the
2403 * resulting info is in attr->aggregator resp. attr->aspath
2404 * so we can chuck as4_aggregator and as4_path alltogether in
2405 * order to save memory
2409 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2410 /* The flag that we got this is still there, but that does not
2415 * The "rest" of the code does nothing with as4_aggregator.
2416 * there is no memory attached specifically which is not part
2418 * so ignoring just means do nothing.
2421 * Finally do the checks on the aspath we did not do yet
2422 * because we waited for a potentially synthesized aspath.
2424 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2426 ret
= bgp_attr_aspath_check (peer
, attr
);
2427 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2431 /* Finally intern unknown attribute. */
2432 if (attr
->extra
&& attr
->extra
->transit
)
2433 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2435 return BGP_ATTR_PARSE_PROCEED
;
2439 bgp_packet_mpattr_start (struct stream
*s
, afi_t afi
, safi_t safi
, afi_t nh_afi
,
2440 struct bpacket_attr_vec_arr
*vecarr
,
2445 /* Set extended bit always to encode the attribute length as 2 bytes */
2446 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2447 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2448 sizep
= stream_get_endp (s
);
2449 stream_putw (s
, 0); /* Marker: Attribute length. */
2451 stream_putw (s
, afi
);
2452 stream_putc (s
, (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
);
2461 case SAFI_MULTICAST
:
2462 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2464 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2467 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2468 stream_putc (s
, 12);
2469 stream_putl (s
, 0); /* RD = 0, per RFC */
2471 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2482 case SAFI_MULTICAST
:
2484 struct attr_extra
*attre
= attr
->extra
;
2486 assert (attr
->extra
);
2487 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2488 stream_putc (s
, attre
->mp_nexthop_len
);
2489 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2490 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2491 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2496 struct attr_extra
*attre
= attr
->extra
;
2498 assert (attr
->extra
);
2499 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2500 stream_putc (s
, 24);
2501 stream_putl (s
, 0); /* RD = 0, per RFC */
2503 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2504 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2505 stream_putc (s
, 48);
2506 stream_putl (s
, 0); /* RD = 0, per RFC */
2508 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2509 stream_putl (s
, 0); /* RD = 0, per RFC */
2511 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2519 #endif /*HAVE_IPV6*/
2530 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2531 struct prefix
*p
, struct prefix_rd
*prd
,
2532 u_char
*tag
, int addpath_encode
,
2533 u_int32_t addpath_tx_id
)
2535 if (safi
== SAFI_MPLS_VPN
)
2538 stream_putl(s
, addpath_tx_id
);
2539 /* Tag, RD, Prefix write. */
2540 stream_putc (s
, p
->prefixlen
+ 88);
2541 stream_put (s
, tag
, 3);
2542 stream_put (s
, prd
->val
, 8);
2543 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2546 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
2550 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
2552 int size
= PSIZE (p
->prefixlen
);
2553 if (safi
== SAFI_MPLS_VPN
)
2560 * Encodes the tunnel encapsulation attribute
2563 bgp_packet_mpattr_tea(
2570 unsigned int attrlenfield
= 0;
2571 struct bgp_attr_encap_subtlv
*subtlvs
;
2572 struct bgp_attr_encap_subtlv
*st
;
2573 const char *attrname
;
2575 if (!attr
|| !attr
->extra
)
2579 case BGP_ATTR_ENCAP
:
2580 attrname
= "Tunnel Encap";
2581 subtlvs
= attr
->extra
->encap_subtlvs
;
2584 * The tunnel encap attr has an "outer" tlv.
2586 * L = total length of subtlvs,
2587 * V = concatenated subtlvs.
2589 attrlenfield
= 2 + 2; /* T + L */
2597 /* compute attr length */
2598 for (st
= subtlvs
; st
; st
= st
->next
) {
2599 attrlenfield
+= (4 + st
->length
);
2602 /* if no tlvs, don't make attr */
2606 if (attrlenfield
> 0xffff) {
2607 zlog_info ("%s attribute is too long (length=%d), can't send it",
2613 if (attrlenfield
> 0xff) {
2614 /* 2-octet length field */
2616 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2617 stream_putc (s
, attrtype
);
2618 stream_putw (s
, attrlenfield
& 0xffff);
2620 /* 1-octet length field */
2621 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
2622 stream_putc (s
, attrtype
);
2623 stream_putc (s
, attrlenfield
& 0xff);
2626 if (attrtype
== BGP_ATTR_ENCAP
) {
2627 /* write outer T+L */
2628 stream_putw(s
, attr
->extra
->encap_tunneltype
);
2629 stream_putw(s
, attrlenfield
- 4);
2632 /* write each sub-tlv */
2633 for (st
= subtlvs
; st
; st
= st
->next
) {
2634 stream_putw (s
, st
->type
);
2635 stream_putw (s
, st
->length
);
2636 stream_put (s
, st
->value
, st
->length
);
2642 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
2644 /* Set MP attribute length. Don't count the (2) bytes used to encode
2646 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
2649 /* Make attribute packet. */
2651 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
2652 struct stream
*s
, struct attr
*attr
,
2653 struct bpacket_attr_vec_arr
*vecarr
,
2654 struct prefix
*p
, afi_t afi
, safi_t safi
,
2655 struct peer
*from
, struct prefix_rd
*prd
, u_char
*tag
,
2657 u_int32_t addpath_tx_id
)
2660 size_t aspath_sizep
;
2661 struct aspath
*aspath
;
2662 int send_as4_path
= 0;
2663 int send_as4_aggregator
= 0;
2664 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2669 /* Remember current pointer. */
2670 cp
= stream_get_endp (s
);
2672 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
2673 !peer_cap_enhe(peer
)))
2675 size_t mpattrlen_pos
= 0;
2677 mpattrlen_pos
= bgp_packet_mpattr_start(s
, afi
, safi
,
2678 (peer_cap_enhe(peer
) ? AFI_IP6
: afi
),
2680 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
2681 addpath_encode
, addpath_tx_id
);
2682 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2685 /* Origin attribute. */
2686 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2687 stream_putc (s
, BGP_ATTR_ORIGIN
);
2689 stream_putc (s
, attr
->origin
);
2691 /* AS path attribute. */
2693 /* If remote-peer is EBGP */
2694 if (peer
->sort
== BGP_PEER_EBGP
2695 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
2696 || attr
->aspath
->segments
== NULL
)
2697 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
2699 aspath
= aspath_dup (attr
->aspath
);
2701 /* Even though we may not be configured for confederations we may have
2702 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2703 aspath
= aspath_delete_confed_seq (aspath
);
2705 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
2707 /* Stuff our path CONFED_ID on the front */
2708 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
2712 if (peer
->change_local_as
) {
2713 /* If replace-as is specified, we only use the change_local_as when
2714 advertising routes. */
2715 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
2716 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2718 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
2720 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2724 else if (peer
->sort
== BGP_PEER_CONFED
)
2726 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2727 aspath
= aspath_dup (attr
->aspath
);
2728 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
2731 aspath
= attr
->aspath
;
2733 /* If peer is not AS4 capable, then:
2734 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2735 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2736 * types are in it (i.e. exclude them if they are there)
2737 * AND do this only if there is at least one asnum > 65535 in the path!
2738 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2739 * all ASnums > 65535 to BGP_AS_TRANS
2742 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2743 stream_putc (s
, BGP_ATTR_AS_PATH
);
2744 aspath_sizep
= stream_get_endp (s
);
2746 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
2748 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2751 if (!use32bit
&& aspath_has_as4 (aspath
))
2752 send_as4_path
= 1; /* we'll do this later, at the correct place */
2754 /* Nexthop attribute. */
2755 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
))
2757 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2759 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2760 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2761 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2763 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2765 else if (safi
== SAFI_UNICAST
&& peer_cap_enhe(from
))
2768 * Likely this is the case when an IPv4 prefix was received with
2769 * Extended Next-hop capability and now being advertised to
2771 * Setting the mandatory (ipv4) next-hop attribute here to enable
2772 * implicit next-hop self with correct (ipv4 address family).
2774 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2775 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2776 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
2778 stream_put_ipv4 (s
, 0);
2782 /* MED attribute. */
2783 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
2786 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2787 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
2789 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
2792 /* Local preference. */
2793 if (peer
->sort
== BGP_PEER_IBGP
||
2794 peer
->sort
== BGP_PEER_CONFED
)
2796 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2797 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
2799 stream_putl (s
, attr
->local_pref
);
2802 /* Atomic aggregate. */
2803 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
2805 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2806 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
2811 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
2813 assert (attr
->extra
);
2815 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
2816 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2817 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
2821 /* AS4 capable peer */
2823 stream_putl (s
, attr
->extra
->aggregator_as
);
2827 /* 2-byte AS peer */
2830 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2831 if ( attr
->extra
->aggregator_as
> 65535 )
2833 stream_putw (s
, BGP_AS_TRANS
);
2835 /* we have to send AS4_AGGREGATOR, too.
2836 * we'll do that later in order to send attributes in ascending
2839 send_as4_aggregator
= 1;
2842 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
2844 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
2847 /* Community attribute. */
2848 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
2849 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
2851 if (attr
->community
->size
* 4 > 255)
2853 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2854 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2855 stream_putw (s
, attr
->community
->size
* 4);
2859 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2860 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2861 stream_putc (s
, attr
->community
->size
* 4);
2863 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
2866 /* Route Reflector. */
2867 if (peer
->sort
== BGP_PEER_IBGP
2869 && from
->sort
== BGP_PEER_IBGP
)
2871 /* Originator ID. */
2872 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2873 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
2876 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
2877 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
2879 stream_put_in_addr (s
, &from
->remote_id
);
2882 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2883 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
2885 if (attr
->extra
&& attr
->extra
->cluster
)
2887 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
2888 /* If this peer configuration's parent BGP has cluster_id. */
2889 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
2890 stream_put_in_addr (s
, &bgp
->cluster_id
);
2892 stream_put_in_addr (s
, &bgp
->router_id
);
2893 stream_put (s
, attr
->extra
->cluster
->list
,
2894 attr
->extra
->cluster
->length
);
2899 /* If this peer configuration's parent BGP has cluster_id. */
2900 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
2901 stream_put_in_addr (s
, &bgp
->cluster_id
);
2903 stream_put_in_addr (s
, &bgp
->router_id
);
2907 /* Extended Communities attribute. */
2908 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
2909 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
2911 struct attr_extra
*attre
= attr
->extra
;
2915 if (peer
->sort
== BGP_PEER_IBGP
2916 || peer
->sort
== BGP_PEER_CONFED
)
2918 if (attre
->ecommunity
->size
* 8 > 255)
2920 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2921 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2922 stream_putw (s
, attre
->ecommunity
->size
* 8);
2926 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2927 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2928 stream_putc (s
, attre
->ecommunity
->size
* 8);
2930 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
2936 int ecom_tr_size
= 0;
2939 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
2941 pnt
= attre
->ecommunity
->val
+ (i
* 8);
2944 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
2952 if (ecom_tr_size
* 8 > 255)
2954 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2955 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2956 stream_putw (s
, ecom_tr_size
* 8);
2960 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2961 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2962 stream_putc (s
, ecom_tr_size
* 8);
2965 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
2967 pnt
= attre
->ecommunity
->val
+ (i
* 8);
2970 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
2973 stream_put (s
, pnt
, 8);
2979 if ( send_as4_path
)
2981 /* If the peer is NOT As4 capable, AND */
2982 /* there are ASnums > 65535 in path THEN
2983 * give out AS4_PATH */
2985 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2987 * Hm, I wonder... confederation things *should* only be at
2988 * the beginning of an aspath, right? Then we should use
2989 * aspath_delete_confed_seq for this, because it is already
2991 * Folks, talk to me: what is reasonable here!?
2993 aspath
= aspath_delete_confed_seq (aspath
);
2995 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2996 stream_putc (s
, BGP_ATTR_AS4_PATH
);
2997 aspath_sizep
= stream_get_endp (s
);
2999 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3002 if (aspath
!= attr
->aspath
)
3003 aspath_free (aspath
);
3005 if ( send_as4_aggregator
)
3007 assert (attr
->extra
);
3009 /* send AS4_AGGREGATOR, at this place */
3010 /* this section of code moved here in order to ensure the correct
3011 * *ascending* order of attributes
3013 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3014 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3016 stream_putl (s
, attr
->extra
->aggregator_as
);
3017 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3020 /* Unknown transit attribute. */
3021 if (attr
->extra
&& attr
->extra
->transit
)
3022 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3024 /* Return total size of attribute. */
3025 return stream_get_endp (s
) - cp
;
3029 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3031 unsigned long attrlen_pnt
;
3033 /* Set extended bit always to encode the attribute length as 2 bytes */
3034 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3035 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3037 attrlen_pnt
= stream_get_endp (s
);
3038 stream_putw (s
, 0); /* Length of this attribute. */
3040 stream_putw (s
, afi
);
3041 stream_putc (s
, (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
);
3046 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3047 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3048 u_char
*tag
, int addpath_encode
,
3049 u_int32_t addpath_tx_id
)
3051 if (safi
== SAFI_MPLS_VPN
)
3055 stream_putl(s
, addpath_tx_id
);
3057 stream_putc (s
, p
->prefixlen
+ 88);
3058 stream_put (s
, tag
, 3);
3059 stream_put (s
, prd
->val
, 8);
3060 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3063 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
3067 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3069 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3072 /* Initialization of attribute. */
3074 bgp_attr_init (void)
3085 bgp_attr_finish (void)
3089 community_finish ();
3090 ecommunity_finish ();
3095 /* Make attribute packet. */
3097 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3098 struct prefix
*prefix
)
3103 struct aspath
*aspath
;
3104 int addpath_encode
= 0;
3105 u_int32_t addpath_tx_id
= 0;
3107 /* Remember current pointer. */
3108 cp
= stream_get_endp (s
);
3110 /* Place holder of length. */
3113 /* Origin attribute. */
3114 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3115 stream_putc (s
, BGP_ATTR_ORIGIN
);
3117 stream_putc (s
, attr
->origin
);
3119 aspath
= attr
->aspath
;
3121 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3122 stream_putc (s
, BGP_ATTR_AS_PATH
);
3123 aspath_lenp
= stream_get_endp (s
);
3126 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3128 /* Nexthop attribute. */
3129 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3132 && prefix
->family
!= AF_INET6
3133 #endif /* HAVE_IPV6 */
3136 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3137 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3139 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3142 /* MED attribute. */
3143 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3145 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3146 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3148 stream_putl (s
, attr
->med
);
3151 /* Local preference. */
3152 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3154 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3155 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3157 stream_putl (s
, attr
->local_pref
);
3160 /* Atomic aggregate. */
3161 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3163 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3164 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3169 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3171 assert (attr
->extra
);
3172 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3173 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3175 stream_putl (s
, attr
->extra
->aggregator_as
);
3176 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3179 /* Community attribute. */
3180 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3182 if (attr
->community
->size
* 4 > 255)
3184 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3185 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3186 stream_putw (s
, attr
->community
->size
* 4);
3190 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3191 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3192 stream_putc (s
, attr
->community
->size
* 4);
3194 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3198 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3199 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3200 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3201 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3204 struct attr_extra
*attre
= attr
->extra
;
3206 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3207 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3208 sizep
= stream_get_endp (s
);
3211 stream_putc (s
, 0); /* Marker: Attribute length. */
3212 stream_putw(s
, AFI_IP6
); /* AFI */
3213 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3216 stream_putc(s
, attre
->mp_nexthop_len
);
3217 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3218 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3219 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3225 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3227 /* Set MP attribute length. */
3228 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3230 #endif /* HAVE_IPV6 */
3232 /* Return total size of attribute. */
3233 len
= stream_get_endp (s
) - cp
- 2;
3234 stream_putw_at (s
, cp
, len
);