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
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_packet.h"
44 #include "bgpd/bgp_ecommunity.h"
45 #include "bgpd/bgp_updgrp.h"
46 #include "bgpd/bgp_encap_types.h"
48 # include "bgpd/rfapi/bgp_rfapi_cfg.h"
49 # include "bgp_encap_types.h"
50 # include "bgp_vnc_types.h"
53 /* Attribute strings for logging. */
54 static const struct message attr_str
[] =
56 { BGP_ATTR_ORIGIN
, "ORIGIN" },
57 { BGP_ATTR_AS_PATH
, "AS_PATH" },
58 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
59 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
60 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
61 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
62 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
63 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
64 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
65 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
66 { BGP_ATTR_DPA
, "DPA" },
67 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
68 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
69 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
70 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
71 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
72 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
73 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
74 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
75 { BGP_ATTR_ENCAP
, "ENCAP" },
77 { BGP_ATTR_VNC
, "VNC" },
80 static const int attr_str_max
= array_size(attr_str
);
82 static const struct message attr_flag_str
[] =
84 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
85 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
86 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
87 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
88 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
91 static struct hash
*cluster_hash
;
94 cluster_hash_alloc (void *p
)
96 const struct cluster_list
*val
= (const struct cluster_list
*) p
;
97 struct cluster_list
*cluster
;
99 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
100 cluster
->length
= val
->length
;
104 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
105 memcpy (cluster
->list
, val
->list
, val
->length
);
108 cluster
->list
= NULL
;
115 /* Cluster list related functions. */
116 static struct cluster_list
*
117 cluster_parse (struct in_addr
* pnt
, int length
)
119 struct cluster_list tmp
;
120 struct cluster_list
*cluster
;
125 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
131 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
135 for (i
= 0; i
< cluster
->length
/ 4; i
++)
136 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
142 cluster_hash_key_make (void *p
)
144 const struct cluster_list
*cluster
= p
;
146 return jhash(cluster
->list
, cluster
->length
, 0);
150 cluster_hash_cmp (const void *p1
, const void *p2
)
152 const struct cluster_list
* cluster1
= p1
;
153 const struct cluster_list
* cluster2
= p2
;
155 return (cluster1
->length
== cluster2
->length
&&
156 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
160 cluster_free (struct cluster_list
*cluster
)
163 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
164 XFREE (MTYPE_CLUSTER
, cluster
);
167 static struct cluster_list
*
168 cluster_dup (struct cluster_list
*cluster
)
170 struct cluster_list
*new;
172 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
173 new->length
= cluster
->length
;
177 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
178 memcpy (new->list
, cluster
->list
, cluster
->length
);
186 static struct cluster_list
*
187 cluster_intern (struct cluster_list
*cluster
)
189 struct cluster_list
*find
;
191 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
198 cluster_unintern (struct cluster_list
*cluster
)
203 if (cluster
->refcnt
== 0)
205 hash_release (cluster_hash
, cluster
);
206 cluster_free (cluster
);
213 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
217 cluster_finish (void)
219 hash_clean (cluster_hash
, (void (*)(void *))cluster_free
);
220 hash_free (cluster_hash
);
224 static struct hash
*encap_hash
= NULL
;
226 static struct hash
*vnc_hash
= NULL
;
229 struct bgp_attr_encap_subtlv
*
230 encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
232 struct bgp_attr_encap_subtlv
*new;
233 struct bgp_attr_encap_subtlv
*tail
;
234 struct bgp_attr_encap_subtlv
*p
;
236 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
237 int size
= sizeof(struct bgp_attr_encap_subtlv
) - 1 + p
->length
;
239 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
242 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
245 memcpy(tail
, p
, size
);
253 encap_free(struct bgp_attr_encap_subtlv
*p
)
255 struct bgp_attr_encap_subtlv
*next
;
259 XFREE(MTYPE_ENCAP_TLV
, p
);
265 bgp_attr_flush_encap(struct attr
*attr
)
267 if (!attr
|| !attr
->extra
)
270 if (attr
->extra
->encap_subtlvs
) {
271 encap_free(attr
->extra
->encap_subtlvs
);
272 attr
->extra
->encap_subtlvs
= NULL
;
275 if (attr
->extra
->vnc_subtlvs
) {
276 encap_free(attr
->extra
->vnc_subtlvs
);
277 attr
->extra
->vnc_subtlvs
= NULL
;
283 * Compare encap sub-tlv chains
288 * This algorithm could be made faster if needed
291 encap_same(struct bgp_attr_encap_subtlv
*h1
, struct bgp_attr_encap_subtlv
*h2
)
293 struct bgp_attr_encap_subtlv
*p
;
294 struct bgp_attr_encap_subtlv
*q
;
298 if (h1
== NULL
|| h2
== NULL
)
301 for (p
= h1
; p
; p
= p
->next
) {
302 for (q
= h2
; q
; q
= q
->next
) {
303 if ((p
->type
== q
->type
) &&
304 (p
->length
== q
->length
) &&
305 !memcmp(p
->value
, q
->value
, p
->length
)) {
314 for (p
= h2
; p
; p
= p
->next
) {
315 for (q
= h1
; q
; q
= q
->next
) {
316 if ((p
->type
== q
->type
) &&
317 (p
->length
== q
->length
) &&
318 !memcmp(p
->value
, q
->value
, p
->length
)) {
331 encap_hash_alloc (void *p
)
333 /* Encap structure is already allocated. */
345 static struct bgp_attr_encap_subtlv
*
346 encap_intern (struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
348 struct bgp_attr_encap_subtlv
*find
;
349 struct hash
*hash
= encap_hash
;
351 if (type
== VNC_SUBTLV_TYPE
)
355 find
= hash_get (hash
, encap
, encap_hash_alloc
);
364 encap_unintern (struct bgp_attr_encap_subtlv
**encapp
, encap_subtlv_type type
)
366 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
370 if (encap
->refcnt
== 0)
372 struct hash
*hash
= encap_hash
;
374 if (type
== VNC_SUBTLV_TYPE
)
377 hash_release (hash
, encap
);
384 encap_hash_key_make (void *p
)
386 const struct bgp_attr_encap_subtlv
* encap
= p
;
388 return jhash(encap
->value
, encap
->length
, 0);
392 encap_hash_cmp (const void *p1
, const void *p2
)
394 return encap_same((struct bgp_attr_encap_subtlv
*)p1
,
395 (struct bgp_attr_encap_subtlv
*)p2
);
401 encap_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
403 vnc_hash
= hash_create (encap_hash_key_make
, encap_hash_cmp
);
410 hash_clean (encap_hash
, (void (*)(void *))encap_free
);
411 hash_free (encap_hash
);
414 hash_clean (vnc_hash
, (void (*)(void *))encap_free
);
415 hash_free (vnc_hash
);
420 /* Unknown transit attribute. */
421 static struct hash
*transit_hash
;
424 transit_free (struct transit
*transit
)
427 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
428 XFREE (MTYPE_TRANSIT
, transit
);
431 static struct transit
*
432 transit_dup (struct transit
*transit
)
436 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
437 new->length
= transit
->length
;
440 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
441 memcpy (new->val
, transit
->val
, transit
->length
);
450 transit_hash_alloc (void *p
)
452 /* Transit structure is already allocated. */
456 static struct transit
*
457 transit_intern (struct transit
*transit
)
459 struct transit
*find
;
461 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
463 transit_free (transit
);
470 transit_unintern (struct transit
*transit
)
475 if (transit
->refcnt
== 0)
477 hash_release (transit_hash
, transit
);
478 transit_free (transit
);
483 transit_hash_key_make (void *p
)
485 const struct transit
* transit
= p
;
487 return jhash(transit
->val
, transit
->length
, 0);
491 transit_hash_cmp (const void *p1
, const void *p2
)
493 const struct transit
* transit1
= p1
;
494 const struct transit
* transit2
= p2
;
496 return (transit1
->length
== transit2
->length
&&
497 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
503 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
507 transit_finish (void)
509 hash_clean (transit_hash
, (void (*)(void *))transit_free
);
510 hash_free (transit_hash
);
514 /* Attribute hash routines. */
515 static struct hash
*attrhash
;
517 static struct attr_extra
*
518 bgp_attr_extra_new (void)
520 return XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
524 bgp_attr_extra_free (struct attr
*attr
)
528 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
534 bgp_attr_extra_get (struct attr
*attr
)
537 attr
->extra
= bgp_attr_extra_new();
541 /* Shallow copy of an attribute
542 * Though, not so shallow that it doesn't copy the contents
543 * of the attr_extra pointed to by 'extra'
546 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
548 struct attr_extra
*extra
= new->extra
;
551 /* if caller provided attr_extra space, use it in any case.
553 * This is neccesary even if orig->extra equals NULL, because otherwise
554 * memory may be later allocated on the heap by bgp_attr_extra_get.
556 * That memory would eventually be leaked, because the caller must not
557 * call bgp_attr_extra_free if he provided attr_extra on the stack.
562 memset(new->extra
, 0, sizeof(struct attr_extra
));
564 *new->extra
= *orig
->extra
;
567 else if (orig
->extra
)
569 new->extra
= bgp_attr_extra_new();
570 *new->extra
= *orig
->extra
;
575 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
578 new->aspath
= aspath_dup(orig
->aspath
);
581 new->community
= community_dup(orig
->community
);
585 if (orig
->extra
->ecommunity
)
586 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
587 if (orig
->extra
->cluster
)
588 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
589 if (orig
->extra
->transit
)
590 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
591 if (orig
->extra
->encap_subtlvs
)
592 new->extra
->encap_subtlvs
= encap_tlv_dup(orig
->extra
->encap_subtlvs
);
594 if (orig
->extra
->vnc_subtlvs
)
595 new->extra
->vnc_subtlvs
= encap_tlv_dup(orig
->extra
->vnc_subtlvs
);
601 bgp_attr_deep_free (struct attr
*attr
)
604 aspath_free(attr
->aspath
);
607 community_free(attr
->community
);
611 if (attr
->extra
->ecommunity
)
612 ecommunity_free(&attr
->extra
->ecommunity
);
613 if (attr
->extra
->cluster
)
614 cluster_free(attr
->extra
->cluster
);
615 if (attr
->extra
->transit
)
616 transit_free(attr
->extra
->transit
);
617 if (attr
->extra
->encap_subtlvs
)
618 encap_free(attr
->extra
->encap_subtlvs
);
620 if (attr
->extra
->vnc_subtlvs
)
621 encap_free(attr
->extra
->vnc_subtlvs
);
629 return attrhash
->count
;
633 attr_unknown_count (void)
635 return transit_hash
->count
;
639 attrhash_key_make (void *p
)
641 const struct attr
*attr
= (struct attr
*) p
;
642 const struct attr_extra
*extra
= attr
->extra
;
644 #define MIX(val) key = jhash_1word(val, key)
647 MIX(attr
->nexthop
.s_addr
);
649 MIX(attr
->local_pref
);
652 key
+= attr
->nexthop
.s_addr
;
654 key
+= attr
->local_pref
;
658 MIX(extra
->aggregator_as
);
659 MIX(extra
->aggregator_addr
.s_addr
);
661 MIX(extra
->mp_nexthop_global_in
.s_addr
);
662 MIX(extra
->originator_id
.s_addr
);
667 MIX(aspath_key_make (attr
->aspath
));
669 MIX(community_hash_make (attr
->community
));
673 if (extra
->ecommunity
)
674 MIX(ecommunity_hash_make (extra
->ecommunity
));
676 MIX(cluster_hash_key_make (extra
->cluster
));
678 MIX(transit_hash_key_make (extra
->transit
));
679 if (extra
->encap_subtlvs
)
680 MIX(encap_hash_key_make (extra
->encap_subtlvs
));
682 if (extra
->vnc_subtlvs
)
683 MIX(encap_hash_key_make (extra
->vnc_subtlvs
));
686 MIX(extra
->mp_nexthop_len
);
687 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
688 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
689 #endif /* HAVE_IPV6 */
696 attrhash_cmp (const void *p1
, const void *p2
)
698 const struct attr
* attr1
= p1
;
699 const struct attr
* attr2
= p2
;
701 if (attr1
->flag
== attr2
->flag
702 && attr1
->origin
== attr2
->origin
703 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
704 && attr1
->aspath
== attr2
->aspath
705 && attr1
->community
== attr2
->community
706 && attr1
->med
== attr2
->med
707 && attr1
->local_pref
== attr2
->local_pref
708 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
)
710 const struct attr_extra
*ae1
= attr1
->extra
;
711 const struct attr_extra
*ae2
= attr2
->extra
;
714 && ae1
->aggregator_as
== ae2
->aggregator_as
715 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
716 && ae1
->weight
== ae2
->weight
717 && ae1
->tag
== ae2
->tag
719 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
720 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
721 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
722 #endif /* HAVE_IPV6 */
723 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
724 && ae1
->ecommunity
== ae2
->ecommunity
725 && ae1
->cluster
== ae2
->cluster
726 && ae1
->transit
== ae2
->transit
727 && (ae1
->encap_tunneltype
== ae2
->encap_tunneltype
)
728 && encap_same(ae1
->encap_subtlvs
, ae2
->encap_subtlvs
)
730 && encap_same(ae1
->vnc_subtlvs
, ae2
->vnc_subtlvs
)
732 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
))
736 /* neither attribute has extra attributes, so they're same */
746 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
750 * special for hash_clean below
753 attr_vfree (void *attr
)
755 bgp_attr_extra_free ((struct attr
*)attr
);
756 XFREE (MTYPE_ATTR
, attr
);
760 attrhash_finish (void)
762 hash_clean(attrhash
, attr_vfree
);
763 hash_free (attrhash
);
768 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
770 struct attr
*attr
= backet
->data
;
772 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
773 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
777 attr_show_all (struct vty
*vty
)
779 hash_iterate (attrhash
,
780 (void (*)(struct hash_backet
*, void *))
781 attr_show_all_iterator
,
786 bgp_attr_hash_alloc (void *p
)
788 const struct attr
* val
= (const struct attr
*) p
;
791 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
795 attr
->extra
= bgp_attr_extra_new ();
796 *attr
->extra
= *val
->extra
;
797 if (val
->extra
->encap_subtlvs
) {
798 val
->extra
->encap_subtlvs
= NULL
;
801 if (val
->extra
->vnc_subtlvs
) {
802 val
->extra
->vnc_subtlvs
= NULL
;
810 /* Internet argument attribute. */
812 bgp_attr_intern (struct attr
*attr
)
816 /* Intern referenced strucutre. */
819 if (! attr
->aspath
->refcnt
)
820 attr
->aspath
= aspath_intern (attr
->aspath
);
822 attr
->aspath
->refcnt
++;
826 if (! attr
->community
->refcnt
)
827 attr
->community
= community_intern (attr
->community
);
829 attr
->community
->refcnt
++;
833 struct attr_extra
*attre
= attr
->extra
;
835 if (attre
->ecommunity
)
837 if (! attre
->ecommunity
->refcnt
)
838 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
840 attre
->ecommunity
->refcnt
++;
845 if (! attre
->cluster
->refcnt
)
846 attre
->cluster
= cluster_intern (attre
->cluster
);
848 attre
->cluster
->refcnt
++;
852 if (! attre
->transit
->refcnt
)
853 attre
->transit
= transit_intern (attre
->transit
);
855 attre
->transit
->refcnt
++;
857 if (attre
->encap_subtlvs
)
859 if (! attre
->encap_subtlvs
->refcnt
)
860 attre
->encap_subtlvs
= encap_intern (attre
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
862 attre
->encap_subtlvs
->refcnt
++;
865 if (attre
->vnc_subtlvs
)
867 if (! attre
->vnc_subtlvs
->refcnt
)
868 attre
->vnc_subtlvs
= encap_intern (attre
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
870 attre
->vnc_subtlvs
->refcnt
++;
875 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
882 * Increment the refcount on various structures that attr holds.
883 * Note on usage: call _only_ when the 'attr' object has already
884 * been 'intern'ed and exists in 'attrhash' table. The function
885 * serves to hold a reference to that (real) object.
886 * Note also that the caller can safely call bgp_attr_unintern()
887 * after calling bgp_attr_refcount(). That would release the
888 * reference and could result in a free() of the attr object.
891 bgp_attr_refcount (struct attr
*attr
)
893 /* Intern referenced strucutre. */
895 attr
->aspath
->refcnt
++;
898 attr
->community
->refcnt
++;
902 struct attr_extra
*attre
= attr
->extra
;
903 if (attre
->ecommunity
)
904 attre
->ecommunity
->refcnt
++;
907 attre
->cluster
->refcnt
++;
910 attre
->transit
->refcnt
++;
912 if (attre
->encap_subtlvs
)
913 attre
->encap_subtlvs
->refcnt
++;
916 if (attre
->vnc_subtlvs
)
917 attre
->vnc_subtlvs
->refcnt
++;
924 /* Make network statement's attribute. */
926 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
928 memset (attr
, 0, sizeof (struct attr
));
929 bgp_attr_extra_get (attr
);
931 attr
->origin
= origin
;
932 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
933 attr
->aspath
= aspath_empty ();
934 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
935 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
936 attr
->extra
->tag
= 0;
937 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
939 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
946 /* Make network statement's attribute. */
948 bgp_attr_default_intern (u_char origin
)
953 memset (&attr
, 0, sizeof (struct attr
));
954 bgp_attr_extra_get (&attr
);
956 bgp_attr_default_set(&attr
, origin
);
958 new = bgp_attr_intern (&attr
);
959 bgp_attr_extra_free (&attr
);
961 aspath_unintern (&new->aspath
);
965 /* Create the attributes for an aggregate */
967 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
968 struct aspath
*aspath
,
969 struct community
*community
, int as_set
,
970 u_char atomic_aggregate
)
974 struct attr_extra attre
;
976 memset (&attr
, 0, sizeof (struct attr
));
977 memset (&attre
, 0, sizeof (struct attr_extra
));
980 /* Origin attribute. */
981 attr
.origin
= origin
;
982 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
984 /* AS path attribute. */
986 attr
.aspath
= aspath_intern (aspath
);
988 attr
.aspath
= aspath_empty ();
989 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
991 /* Next hop attribute. */
992 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
996 attr
.community
= community
;
997 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1000 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1002 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1004 if (! as_set
|| atomic_aggregate
)
1005 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1006 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1007 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1008 attre
.aggregator_as
= bgp
->confed_id
;
1010 attre
.aggregator_as
= bgp
->as
;
1011 attre
.aggregator_addr
= bgp
->router_id
;
1013 new = bgp_attr_intern (&attr
);
1015 aspath_unintern (&new->aspath
);
1019 /* Unintern just the sub-components of the attr, but not the attr */
1021 bgp_attr_unintern_sub (struct attr
*attr
)
1023 /* aspath refcount shoud be decrement. */
1025 aspath_unintern (&attr
->aspath
);
1026 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
1028 if (attr
->community
)
1029 community_unintern (&attr
->community
);
1030 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
1034 if (attr
->extra
->ecommunity
)
1035 ecommunity_unintern (&attr
->extra
->ecommunity
);
1036 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
1038 if (attr
->extra
->cluster
)
1039 cluster_unintern (attr
->extra
->cluster
);
1040 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
1042 if (attr
->extra
->transit
)
1043 transit_unintern (attr
->extra
->transit
);
1045 if (attr
->extra
->encap_subtlvs
)
1046 encap_unintern (&attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1049 if (attr
->extra
->vnc_subtlvs
)
1050 encap_unintern (&attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1055 /* Free bgp attribute and aspath. */
1057 bgp_attr_unintern (struct attr
**pattr
)
1059 struct attr
*attr
= *pattr
;
1062 struct attr_extra tmp_extra
;
1064 /* Decrement attribute reference. */
1071 tmp
.extra
= &tmp_extra
;
1072 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
1075 /* If reference becomes zero then free attribute object. */
1076 if (attr
->refcnt
== 0)
1078 ret
= hash_release (attrhash
, attr
);
1079 assert (ret
!= NULL
);
1080 bgp_attr_extra_free (attr
);
1081 XFREE (MTYPE_ATTR
, attr
);
1085 bgp_attr_unintern_sub (&tmp
);
1089 bgp_attr_flush (struct attr
*attr
)
1091 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
1093 aspath_free (attr
->aspath
);
1094 attr
->aspath
= NULL
;
1096 if (attr
->community
&& ! attr
->community
->refcnt
)
1098 community_free (attr
->community
);
1099 attr
->community
= NULL
;
1103 struct attr_extra
*attre
= attr
->extra
;
1105 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
1106 ecommunity_free (&attre
->ecommunity
);
1107 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
1109 cluster_free (attre
->cluster
);
1110 attre
->cluster
= NULL
;
1112 if (attre
->transit
&& ! attre
->transit
->refcnt
)
1114 transit_free (attre
->transit
);
1115 attre
->transit
= NULL
;
1117 if (attre
->encap_subtlvs
&& ! attre
->encap_subtlvs
->refcnt
)
1119 encap_free(attre
->encap_subtlvs
);
1120 attre
->encap_subtlvs
= NULL
;
1123 if (attre
->vnc_subtlvs
&& ! attre
->vnc_subtlvs
->refcnt
)
1125 encap_free(attre
->vnc_subtlvs
);
1126 attre
->vnc_subtlvs
= NULL
;
1132 /* Implement draft-scudder-idr-optional-transitive behaviour and
1133 * avoid resetting sessions for malformed attributes which are
1134 * are partial/optional and hence where the error likely was not
1135 * introduced by the sending neighbour.
1137 static bgp_attr_parse_ret_t
1138 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
1141 struct peer
*const peer
= args
->peer
;
1142 const u_int8_t flags
= args
->flags
;
1143 /* startp and length must be special-cased, as whether or not to
1144 * send the attribute data with the NOTIFY depends on the error,
1145 * the caller therefore signals this with the seperate length argument
1147 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1149 /* Only relax error handling for eBGP peers */
1150 if (peer
->sort
!= BGP_PEER_EBGP
)
1152 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1153 notify_datap
, length
);
1154 return BGP_ATTR_PARSE_ERROR
;
1158 /* Adjust the stream getp to the end of the attribute, in case we can
1159 * still proceed but the caller hasn't read all the attribute.
1161 stream_set_getp (BGP_INPUT (peer
),
1162 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
1165 switch (args
->type
) {
1166 /* where an attribute is relatively inconsequential, e.g. it does not
1167 * affect route selection, and can be safely ignored, then any such
1168 * attributes which are malformed should just be ignored and the route
1169 * processed as normal.
1171 case BGP_ATTR_AS4_AGGREGATOR
:
1172 case BGP_ATTR_AGGREGATOR
:
1173 case BGP_ATTR_ATOMIC_AGGREGATE
:
1174 return BGP_ATTR_PARSE_PROCEED
;
1176 /* Core attributes, particularly ones which may influence route
1177 * selection, should always cause session resets
1179 case BGP_ATTR_ORIGIN
:
1180 case BGP_ATTR_AS_PATH
:
1181 case BGP_ATTR_NEXT_HOP
:
1182 case BGP_ATTR_MULTI_EXIT_DISC
:
1183 case BGP_ATTR_LOCAL_PREF
:
1184 case BGP_ATTR_COMMUNITIES
:
1185 case BGP_ATTR_ORIGINATOR_ID
:
1186 case BGP_ATTR_CLUSTER_LIST
:
1187 case BGP_ATTR_MP_REACH_NLRI
:
1188 case BGP_ATTR_MP_UNREACH_NLRI
:
1189 case BGP_ATTR_EXT_COMMUNITIES
:
1190 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1191 notify_datap
, length
);
1192 return BGP_ATTR_PARSE_ERROR
;
1195 /* Partial optional attributes that are malformed should not cause
1196 * the whole session to be reset. Instead treat it as a withdrawal
1197 * of the routes, if possible.
1199 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
1200 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1201 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1202 return BGP_ATTR_PARSE_WITHDRAW
;
1204 /* default to reset */
1205 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1208 /* Find out what is wrong with the path attribute flag bits and log the error.
1209 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1210 Extended Length. Checking O/T/P bits at once implies, that the attribute
1211 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1212 non-transitive" attribute. */
1214 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
1215 u_int8_t desired_flags
/* how RFC says it must be */
1219 u_char real_flags
= args
->flags
;
1220 const u_int8_t attr_code
= args
->type
;
1222 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1223 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1224 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1227 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
1228 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
1231 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1232 LOOKUP (attr_str
, attr_code
),
1233 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
1234 attr_flag_str
[i
].str
);
1239 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1240 " (real flags 0x%x, desired 0x%x)",
1241 __func__
, LOOKUP (attr_str
, attr_code
),
1242 real_flags
, desired_flags
);
1246 /* Required flags for attributes. EXTLEN will be masked off when testing,
1247 * as will PARTIAL for optional+transitive attributes.
1249 const u_int8_t attr_flags_values
[] = {
1250 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1251 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1252 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1253 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1254 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1255 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1256 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1257 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1258 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1259 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1260 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1261 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1262 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1263 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1264 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1266 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1269 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
1271 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1272 const u_int8_t flags
= args
->flags
;
1273 const u_int8_t attr_code
= args
->type
;
1275 /* there may be attributes we don't know about */
1276 if (attr_code
> attr_flags_values_max
)
1278 if (attr_flags_values
[attr_code
] == 0)
1281 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1284 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
1285 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
1287 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1288 LOOKUP (attr_str
, attr_code
), flags
);
1292 /* "For well-known attributes and for optional non-transitive attributes,
1293 * the Partial bit MUST be set to 0."
1295 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
1297 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
1299 zlog_err ("%s well-known attribute "
1300 "must NOT have the partial flag set (%x)",
1301 LOOKUP (attr_str
, attr_code
), flags
);
1304 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1305 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1307 zlog_err ("%s optional + transitive attribute "
1308 "must NOT have the partial flag set (%x)",
1309 LOOKUP (attr_str
, attr_code
), flags
);
1314 /* Optional transitive attributes may go through speakers that don't
1315 * reocgnise them and set the Partial bit.
1317 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
1318 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
1319 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
1322 == attr_flags_values
[attr_code
])
1325 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
1329 /* Get origin attribute of the update message. */
1330 static bgp_attr_parse_ret_t
1331 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
1333 struct peer
*const peer
= args
->peer
;
1334 struct attr
*const attr
= args
->attr
;
1335 const bgp_size_t length
= args
->length
;
1337 /* If any recognized attribute has Attribute Length that conflicts
1338 with the expected length (based on the attribute type code), then
1339 the Error Subcode is set to Attribute Length Error. The Data
1340 field contains the erroneous attribute (type, length and
1344 zlog_err ("Origin attribute length is not one %d", length
);
1345 return bgp_attr_malformed (args
,
1346 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1350 /* Fetch origin attribute. */
1351 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1353 /* If the ORIGIN attribute has an undefined value, then the Error
1354 Subcode is set to Invalid Origin Attribute. The Data field
1355 contains the unrecognized attribute (type, length and value). */
1356 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1357 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1358 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1360 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1361 return bgp_attr_malformed (args
,
1362 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1366 /* Set oring attribute flag. */
1367 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1372 /* Parse AS path information. This function is wrapper of
1375 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1377 struct attr
*const attr
= args
->attr
;
1378 struct peer
*const peer
= args
->peer
;
1379 const bgp_size_t length
= args
->length
;
1382 * peer with AS4 => will get 4Byte ASnums
1383 * otherwise, will get 16 Bit
1385 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1386 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1388 /* In case of IBGP, length will be zero. */
1391 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1392 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1395 /* Set aspath attribute flag. */
1396 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1398 return BGP_ATTR_PARSE_PROCEED
;
1401 static bgp_attr_parse_ret_t
1402 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1404 /* These checks were part of bgp_attr_aspath, but with
1405 * as4 we should to check aspath things when
1406 * aspath synthesizing with as4_path has already taken place.
1407 * Otherwise we check ASPATH and use the synthesized thing, and that is
1409 * So do the checks later, i.e. here
1411 struct bgp
*bgp
= peer
->bgp
;
1412 struct aspath
*aspath
;
1414 /* Confederation sanity check. */
1415 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1416 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1418 zlog_err ("Malformed AS path from %s", peer
->host
);
1419 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1420 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1421 return BGP_ATTR_PARSE_ERROR
;
1424 /* First AS check for EBGP. */
1425 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1427 if (peer
->sort
== BGP_PEER_EBGP
1428 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1430 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1431 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1432 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1433 return BGP_ATTR_PARSE_ERROR
;
1437 /* local-as prepend */
1438 if (peer
->change_local_as
&&
1439 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1441 aspath
= aspath_dup (attr
->aspath
);
1442 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1443 aspath_unintern (&attr
->aspath
);
1444 attr
->aspath
= aspath_intern (aspath
);
1447 return BGP_ATTR_PARSE_PROCEED
;
1450 /* Parse AS4 path information. This function is another wrapper of
1453 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1455 struct peer
*const peer
= args
->peer
;
1456 struct attr
*const attr
= args
->attr
;
1457 const bgp_size_t length
= args
->length
;
1459 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1461 /* In case of IBGP, length will be zero. */
1464 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1465 return bgp_attr_malformed (args
,
1466 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1470 /* Set aspath attribute flag. */
1472 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1474 return BGP_ATTR_PARSE_PROCEED
;
1477 /* Nexthop attribute. */
1478 static bgp_attr_parse_ret_t
1479 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1481 struct peer
*const peer
= args
->peer
;
1482 struct attr
*const attr
= args
->attr
;
1483 const bgp_size_t length
= args
->length
;
1485 in_addr_t nexthop_h
, nexthop_n
;
1487 /* Check nexthop attribute length. */
1490 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1492 return bgp_attr_malformed (args
,
1493 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1497 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1498 attribute must result in a NOTIFICATION message (this is implemented below).
1499 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1500 logged locally (this is implemented somewhere else). The UPDATE message
1501 gets ignored in any of these cases. */
1502 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1503 nexthop_h
= ntohl (nexthop_n
);
1504 if ((IPV4_NET0 (nexthop_h
) || IPV4_NET127 (nexthop_h
) || IPV4_CLASS_DE (nexthop_h
))
1505 && !BGP_DEBUG (allow_martians
, ALLOW_MARTIANS
)) /* loopbacks may be used in testing */
1507 char buf
[INET_ADDRSTRLEN
];
1508 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1509 zlog_err ("Martian nexthop %s", buf
);
1510 return bgp_attr_malformed (args
,
1511 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1515 attr
->nexthop
.s_addr
= nexthop_n
;
1516 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1518 return BGP_ATTR_PARSE_PROCEED
;
1521 /* MED atrribute. */
1522 static bgp_attr_parse_ret_t
1523 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1525 struct peer
*const peer
= args
->peer
;
1526 struct attr
*const attr
= args
->attr
;
1527 const bgp_size_t length
= args
->length
;
1532 zlog_err ("MED attribute length isn't four [%d]", length
);
1534 return bgp_attr_malformed (args
,
1535 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1539 attr
->med
= stream_getl (peer
->ibuf
);
1541 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1543 return BGP_ATTR_PARSE_PROCEED
;
1546 /* Local preference attribute. */
1547 static bgp_attr_parse_ret_t
1548 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1550 struct peer
*const peer
= args
->peer
;
1551 struct attr
*const attr
= args
->attr
;
1552 const bgp_size_t length
= args
->length
;
1557 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1558 return bgp_attr_malformed (args
,
1559 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1563 /* If it is contained in an UPDATE message that is received from an
1564 external peer, then this attribute MUST be ignored by the
1565 receiving speaker. */
1566 if (peer
->sort
== BGP_PEER_EBGP
)
1568 stream_forward_getp (peer
->ibuf
, length
);
1569 return BGP_ATTR_PARSE_PROCEED
;
1572 attr
->local_pref
= stream_getl (peer
->ibuf
);
1574 /* Set atomic aggregate flag. */
1575 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1577 return BGP_ATTR_PARSE_PROCEED
;
1580 /* Atomic aggregate. */
1582 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1584 struct attr
*const attr
= args
->attr
;
1585 const bgp_size_t length
= args
->length
;
1590 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1591 return bgp_attr_malformed (args
,
1592 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1596 /* Set atomic aggregate flag. */
1597 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1599 return BGP_ATTR_PARSE_PROCEED
;
1602 /* Aggregator attribute */
1604 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1606 struct peer
*const peer
= args
->peer
;
1607 struct attr
*const attr
= args
->attr
;
1608 const bgp_size_t length
= args
->length
;
1611 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1613 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1614 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1617 if (length
!= wantedlen
)
1619 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1620 return bgp_attr_malformed (args
,
1621 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1625 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1626 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1628 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1629 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1631 /* Set atomic aggregate flag. */
1632 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1634 return BGP_ATTR_PARSE_PROCEED
;
1637 /* New Aggregator attribute */
1638 static bgp_attr_parse_ret_t
1639 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1640 as_t
*as4_aggregator_as
,
1641 struct in_addr
*as4_aggregator_addr
)
1643 struct peer
*const peer
= args
->peer
;
1644 struct attr
*const attr
= args
->attr
;
1645 const bgp_size_t length
= args
->length
;
1649 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1650 return bgp_attr_malformed (args
,
1651 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1655 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1656 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1658 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1660 return BGP_ATTR_PARSE_PROCEED
;
1663 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1665 static bgp_attr_parse_ret_t
1666 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1667 struct attr
*const attr
,
1668 struct aspath
*as4_path
, as_t as4_aggregator
,
1669 struct in_addr
*as4_aggregator_addr
)
1671 int ignore_as4_path
= 0;
1672 struct aspath
*newpath
;
1673 struct attr_extra
*attre
= attr
->extra
;
1677 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1678 * checked that all well-known, mandatory attributes were present.
1680 * Can only be a problem with peer itself - hard error
1682 return BGP_ATTR_PARSE_ERROR
;
1685 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1687 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1689 * It is worth a warning though, because the peer really
1690 * should not send them
1692 if (BGP_DEBUG(as4
, AS4
))
1694 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1695 zlog_debug ("[AS4] %s %s AS4_PATH",
1696 peer
->host
, "AS4 capable peer, yet it sent");
1698 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1699 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1700 peer
->host
, "AS4 capable peer, yet it sent");
1703 return BGP_ATTR_PARSE_PROCEED
;
1706 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1707 * because that may override AS4_PATH
1709 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1711 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1716 * if the as_number in aggregator is not AS_TRANS,
1717 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1718 * and the Aggregator shall be taken as
1719 * info on the aggregating node, and the AS_PATH
1720 * shall be taken as the AS_PATH
1722 * the Aggregator shall be ignored and the
1723 * AS4_AGGREGATOR shall be taken as the
1724 * Aggregating node and the AS_PATH is to be
1725 * constructed "as in all other cases"
1727 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1730 if ( BGP_DEBUG(as4
, AS4
))
1731 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1732 " send AGGREGATOR != AS_TRANS and"
1733 " AS4_AGGREGATOR, so ignore"
1734 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1735 ignore_as4_path
= 1;
1739 /* "New_aggregator shall be taken as aggregator" */
1740 attre
->aggregator_as
= as4_aggregator
;
1741 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1746 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1747 * That is bogus - but reading the conditions
1748 * we have to handle AS4_AGGREGATOR as if it were
1749 * AGGREGATOR in that case
1751 if ( BGP_DEBUG(as4
, AS4
))
1752 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1753 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1754 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1755 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1756 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1757 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1761 /* need to reconcile NEW_AS_PATH and AS_PATH */
1762 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1764 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1765 aspath_unintern (&attr
->aspath
);
1766 attr
->aspath
= aspath_intern (newpath
);
1768 return BGP_ATTR_PARSE_PROCEED
;
1771 /* Community attribute. */
1772 static bgp_attr_parse_ret_t
1773 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1775 struct peer
*const peer
= args
->peer
;
1776 struct attr
*const attr
= args
->attr
;
1777 const bgp_size_t length
= args
->length
;
1781 attr
->community
= NULL
;
1782 return BGP_ATTR_PARSE_PROCEED
;
1786 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1788 /* XXX: fix community_parse to use stream API and remove this */
1789 stream_forward_getp (peer
->ibuf
, length
);
1791 if (!attr
->community
)
1792 return bgp_attr_malformed (args
,
1793 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1796 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1798 return BGP_ATTR_PARSE_PROCEED
;
1801 /* Originator ID attribute. */
1802 static bgp_attr_parse_ret_t
1803 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1805 struct peer
*const peer
= args
->peer
;
1806 struct attr
*const attr
= args
->attr
;
1807 const bgp_size_t length
= args
->length
;
1812 zlog_err ("Bad originator ID length %d", length
);
1814 return bgp_attr_malformed (args
,
1815 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1819 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1820 = stream_get_ipv4 (peer
->ibuf
);
1822 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1824 return BGP_ATTR_PARSE_PROCEED
;
1827 /* Cluster list attribute. */
1828 static bgp_attr_parse_ret_t
1829 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1831 struct peer
*const peer
= args
->peer
;
1832 struct attr
*const attr
= args
->attr
;
1833 const bgp_size_t length
= args
->length
;
1838 zlog_err ("Bad cluster list length %d", length
);
1840 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1844 (bgp_attr_extra_get (attr
))->cluster
1845 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1847 /* XXX: Fix cluster_parse to use stream API and then remove this */
1848 stream_forward_getp (peer
->ibuf
, length
);
1850 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1852 return BGP_ATTR_PARSE_PROCEED
;
1855 /* Multiprotocol reachability information parse. */
1857 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1858 struct bgp_nlri
*mp_update
)
1862 bgp_size_t nlri_len
;
1865 struct peer
*const peer
= args
->peer
;
1866 struct attr
*const attr
= args
->attr
;
1867 const bgp_size_t length
= args
->length
;
1868 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1870 /* Set end of packet. */
1871 s
= BGP_INPUT(peer
);
1872 start
= stream_get_getp(s
);
1874 /* safe to read statically sized header? */
1875 #define BGP_MP_REACH_MIN_SIZE 5
1876 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1877 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1879 zlog_info ("%s: %s sent invalid length, %lu",
1880 __func__
, peer
->host
, (unsigned long)length
);
1881 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1884 /* Load AFI, SAFI. */
1885 afi
= stream_getw (s
);
1886 safi
= stream_getc (s
);
1888 /* Get nexthop length. */
1889 attre
->mp_nexthop_len
= stream_getc (s
);
1891 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1893 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1894 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1895 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1898 /* Nexthop length check. */
1899 switch (attre
->mp_nexthop_len
)
1901 case BGP_ATTR_NHLEN_IPV4
:
1902 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1903 /* Probably needed for RFC 2283 */
1904 if (attr
->nexthop
.s_addr
== 0)
1905 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1907 case BGP_ATTR_NHLEN_VPNV4
:
1908 stream_getl (s
); /* RD high */
1909 stream_getl (s
); /* RD low */
1910 stream_get (&attre
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1913 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1914 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1915 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
)
1917 stream_getl (s
); /* RD high */
1918 stream_getl (s
); /* RD low */
1920 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1922 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1923 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1924 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1926 stream_getl (s
); /* RD high */
1927 stream_getl (s
); /* RD low */
1929 stream_get (&attre
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1930 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
1932 stream_getl (s
); /* RD high */
1933 stream_getl (s
); /* RD low */
1935 stream_get (&attre
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1936 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1938 char buf1
[INET6_ADDRSTRLEN
];
1939 char buf2
[INET6_ADDRSTRLEN
];
1941 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1942 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1944 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1945 buf1
, INET6_ADDRSTRLEN
),
1946 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1947 buf2
, INET6_ADDRSTRLEN
));
1949 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1952 #endif /* HAVE_IPV6 */
1954 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1955 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1956 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1961 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1962 __func__
, peer
->host
);
1963 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1968 if ((val
= stream_getc (s
)))
1969 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1973 /* must have nrli_len, what is left of the attribute */
1974 nlri_len
= LEN_LEFT
;
1975 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
1977 zlog_info ("%s: (%s) Failed to read NLRI",
1978 __func__
, peer
->host
);
1979 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1982 mp_update
->afi
= afi
;
1983 mp_update
->safi
= safi
;
1984 mp_update
->nlri
= stream_pnt (s
);
1985 mp_update
->length
= nlri_len
;
1987 stream_forward_getp (s
, nlri_len
);
1989 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
);
1991 return BGP_ATTR_PARSE_PROCEED
;
1995 /* Multiprotocol unreachable parse */
1997 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
1998 struct bgp_nlri
*mp_withdraw
)
2003 u_int16_t withdraw_len
;
2004 struct peer
*const peer
= args
->peer
;
2005 struct attr
*const attr
= args
->attr
;
2006 const bgp_size_t length
= args
->length
;
2010 #define BGP_MP_UNREACH_MIN_SIZE 3
2011 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2012 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2014 afi
= stream_getw (s
);
2015 safi
= stream_getc (s
);
2017 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2019 mp_withdraw
->afi
= afi
;
2020 mp_withdraw
->safi
= safi
;
2021 mp_withdraw
->nlri
= stream_pnt (s
);
2022 mp_withdraw
->length
= withdraw_len
;
2024 stream_forward_getp (s
, withdraw_len
);
2026 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
);
2028 return BGP_ATTR_PARSE_PROCEED
;
2031 /* Extended Community attribute. */
2032 static bgp_attr_parse_ret_t
2033 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
2035 struct peer
*const peer
= args
->peer
;
2036 struct attr
*const attr
= args
->attr
;
2037 const bgp_size_t length
= args
->length
;
2042 attr
->extra
->ecommunity
= NULL
;
2043 /* Empty extcomm doesn't seem to be invalid per se */
2044 return BGP_ATTR_PARSE_PROCEED
;
2047 (bgp_attr_extra_get (attr
))->ecommunity
=
2048 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
2049 /* XXX: fix ecommunity_parse to use stream API */
2050 stream_forward_getp (peer
->ibuf
, length
);
2052 if (!attr
->extra
->ecommunity
)
2053 return bgp_attr_malformed (args
,
2054 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2057 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
2059 return BGP_ATTR_PARSE_PROCEED
;
2062 /* Parse Tunnel Encap attribute in an UPDATE */
2066 struct peer
*peer
, /* IN */
2067 bgp_size_t length
, /* IN: attr's length field */
2068 struct attr
*attr
, /* IN: caller already allocated */
2069 u_char flag
, /* IN: attr's flags field */
2073 struct attr_extra
*attre
= NULL
;
2074 struct bgp_attr_encap_subtlv
*stlv_last
= NULL
;
2075 uint16_t tunneltype
= 0;
2077 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2079 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2080 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
2082 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag
);
2083 bgp_notify_send_with_data (peer
,
2084 BGP_NOTIFY_UPDATE_ERR
,
2085 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2090 if (BGP_ATTR_ENCAP
== type
) {
2091 /* read outer TLV type and length */
2092 uint16_t tlv_length
;
2095 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2096 bgp_notify_send_with_data(peer
,
2097 BGP_NOTIFY_UPDATE_ERR
,
2098 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2102 tunneltype
= stream_getw (BGP_INPUT (peer
));
2103 tlv_length
= stream_getw (BGP_INPUT (peer
));
2106 if (tlv_length
!= length
) {
2107 zlog_info ("%s: tlv_length(%d) != length(%d)",
2108 __func__
, tlv_length
, length
);
2112 while (length
>= 4) {
2113 uint16_t subtype
= 0;
2114 uint16_t sublength
= 0;
2115 struct bgp_attr_encap_subtlv
*tlv
;
2117 if (BGP_ATTR_ENCAP
== type
) {
2118 subtype
= stream_getc (BGP_INPUT (peer
));
2119 sublength
= stream_getc (BGP_INPUT (peer
));
2123 subtype
= stream_getw (BGP_INPUT (peer
));
2124 sublength
= stream_getw (BGP_INPUT (peer
));
2129 if (sublength
> length
) {
2130 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2132 bgp_notify_send_with_data (peer
,
2133 BGP_NOTIFY_UPDATE_ERR
,
2134 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2139 /* alloc and copy sub-tlv */
2140 /* TBD make sure these are freed when attributes are released */
2141 tlv
= XCALLOC (MTYPE_ENCAP_TLV
, sizeof(struct bgp_attr_encap_subtlv
)-1+sublength
);
2142 tlv
->type
= subtype
;
2143 tlv
->length
= sublength
;
2144 stream_get(tlv
->value
, peer
->ibuf
, sublength
);
2145 length
-= sublength
;
2147 /* attach tlv to encap chain */
2149 attre
= bgp_attr_extra_get(attr
);
2150 if (BGP_ATTR_ENCAP
== type
) {
2151 for (stlv_last
= attre
->encap_subtlvs
; stlv_last
&& stlv_last
->next
;
2152 stlv_last
= stlv_last
->next
);
2154 stlv_last
->next
= tlv
;
2156 attre
->encap_subtlvs
= tlv
;
2160 for (stlv_last
= attre
->vnc_subtlvs
; stlv_last
&& stlv_last
->next
;
2161 stlv_last
= stlv_last
->next
);
2163 stlv_last
->next
= tlv
;
2165 attre
->vnc_subtlvs
= tlv
;
2170 stlv_last
->next
= tlv
;
2175 if (attre
&& (BGP_ATTR_ENCAP
== type
)) {
2176 attre
->encap_tunneltype
= tunneltype
;
2180 /* spurious leftover data */
2181 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length
);
2182 bgp_notify_send_with_data (peer
,
2183 BGP_NOTIFY_UPDATE_ERR
,
2184 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2192 /* BGP unknown attribute treatment. */
2193 static bgp_attr_parse_ret_t
2194 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
2196 bgp_size_t total
= args
->total
;
2197 struct transit
*transit
;
2198 struct attr_extra
*attre
;
2199 struct peer
*const peer
= args
->peer
;
2200 struct attr
*const attr
= args
->attr
;
2201 u_char
*const startp
= args
->startp
;
2202 const u_char type
= args
->type
;
2203 const u_char flag
= args
->flags
;
2204 const bgp_size_t length
= args
->length
;
2206 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2207 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2208 peer
->host
, type
, length
);
2210 /* Forward read pointer of input stream. */
2211 stream_forward_getp (peer
->ibuf
, length
);
2213 /* If any of the mandatory well-known attributes are not recognized,
2214 then the Error Subcode is set to Unrecognized Well-known
2215 Attribute. The Data field contains the unrecognized attribute
2216 (type, length and value). */
2217 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
2219 return bgp_attr_malformed (args
,
2220 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2224 /* Unrecognized non-transitive optional attributes must be quietly
2225 ignored and not passed along to other BGP peers. */
2226 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
2227 return BGP_ATTR_PARSE_PROCEED
;
2229 /* If a path with recognized transitive optional attribute is
2230 accepted and passed along to other BGP peers and the Partial bit
2231 in the Attribute Flags octet is set to 1 by some previous AS, it
2232 is not set back to 0 by the current AS. */
2233 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
2235 /* Store transitive attribute to the end of attr->transit. */
2236 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
2237 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
2239 transit
= attre
->transit
;
2242 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
2243 transit
->length
+ total
);
2245 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
2247 memcpy (transit
->val
+ transit
->length
, startp
, total
);
2248 transit
->length
+= total
;
2250 return BGP_ATTR_PARSE_PROCEED
;
2253 /* Well-known attribute check. */
2255 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2259 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2261 if (CHECK_FLAG (peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2262 return BGP_ATTR_PARSE_PROCEED
;
2264 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2265 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2266 are present, it should. Check for any other attribute being present
2269 if (attr
->flag
== ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI
))
2270 return BGP_ATTR_PARSE_PROCEED
;
2272 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2273 type
= BGP_ATTR_ORIGIN
;
2275 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2276 type
= BGP_ATTR_AS_PATH
;
2278 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2279 * NLRI is empty. We can't easily check NLRI empty here though.
2281 if (!CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2282 && !CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI
)))
2283 type
= BGP_ATTR_NEXT_HOP
;
2285 if (peer
->sort
== BGP_PEER_IBGP
2286 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2287 type
= BGP_ATTR_LOCAL_PREF
;
2291 zlog_warn ("%s Missing well-known attribute %s.", peer
->host
,
2292 LOOKUP (attr_str
, type
));
2293 bgp_notify_send_with_data (peer
,
2294 BGP_NOTIFY_UPDATE_ERR
,
2295 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2297 return BGP_ATTR_PARSE_ERROR
;
2299 return BGP_ATTR_PARSE_PROCEED
;
2302 /* Read attribute of update packet. This function is called from
2303 bgp_update_receive() in bgp_packet.c. */
2304 bgp_attr_parse_ret_t
2305 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
2306 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
2312 u_char
*startp
, *endp
;
2314 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
2315 /* we need the as4_path only until we have synthesized the as_path with it */
2316 /* same goes for as4_aggregator */
2317 struct aspath
*as4_path
= NULL
;
2318 as_t as4_aggregator
= 0;
2319 struct in_addr as4_aggregator_addr
= { .s_addr
= 0 };
2321 /* Initialize bitmap. */
2322 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2324 /* End pointer of BGP attribute. */
2325 endp
= BGP_INPUT_PNT (peer
) + size
;
2327 /* Get attributes to the end of attribute length. */
2328 while (BGP_INPUT_PNT (peer
) < endp
)
2330 /* Check remaining length check.*/
2331 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
2333 /* XXX warning: long int format, int arg (arg 5) */
2334 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2336 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2338 bgp_notify_send (peer
,
2339 BGP_NOTIFY_UPDATE_ERR
,
2340 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2341 return BGP_ATTR_PARSE_ERROR
;
2344 /* Fetch attribute flag and type. */
2345 startp
= BGP_INPUT_PNT (peer
);
2346 /* "The lower-order four bits of the Attribute Flags octet are
2347 unused. They MUST be zero when sent and MUST be ignored when
2349 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
2350 type
= stream_getc (BGP_INPUT (peer
));
2352 /* Check whether Extended-Length applies and is in bounds */
2353 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
2354 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
2356 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2358 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
2360 bgp_notify_send (peer
,
2361 BGP_NOTIFY_UPDATE_ERR
,
2362 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2363 return BGP_ATTR_PARSE_ERROR
;
2366 /* Check extended attribue length bit. */
2367 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
2368 length
= stream_getw (BGP_INPUT (peer
));
2370 length
= stream_getc (BGP_INPUT (peer
));
2372 /* If any attribute appears more than once in the UPDATE
2373 message, then the Error Subcode is set to Malformed Attribute
2376 if (CHECK_BITMAP (seen
, type
))
2378 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2381 bgp_notify_send (peer
,
2382 BGP_NOTIFY_UPDATE_ERR
,
2383 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2384 return BGP_ATTR_PARSE_ERROR
;
2387 /* Set type to bitmap to check duplicate attribute. `type' is
2388 unsigned char so it never overflow bitmap range. */
2390 SET_BITMAP (seen
, type
);
2392 /* Overflow check. */
2393 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
2395 if (attr_endp
> endp
)
2397 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
);
2398 bgp_notify_send_with_data (peer
,
2399 BGP_NOTIFY_UPDATE_ERR
,
2400 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2401 startp
, attr_endp
- startp
);
2402 return BGP_ATTR_PARSE_ERROR
;
2405 struct bgp_attr_parser_args attr_args
= {
2412 .total
= attr_endp
- startp
,
2416 /* If any recognized attribute has Attribute Flags that conflict
2417 with the Attribute Type Code, then the Error Subcode is set to
2418 Attribute Flags Error. The Data field contains the erroneous
2419 attribute (type, length and value). */
2420 if (bgp_attr_flag_invalid (&attr_args
))
2422 bgp_attr_parse_ret_t ret
;
2423 ret
= bgp_attr_malformed (&attr_args
,
2424 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2426 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2431 /* OK check attribute and store it's value. */
2434 case BGP_ATTR_ORIGIN
:
2435 ret
= bgp_attr_origin (&attr_args
);
2437 case BGP_ATTR_AS_PATH
:
2438 ret
= bgp_attr_aspath (&attr_args
);
2440 case BGP_ATTR_AS4_PATH
:
2441 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
2443 case BGP_ATTR_NEXT_HOP
:
2444 ret
= bgp_attr_nexthop (&attr_args
);
2446 case BGP_ATTR_MULTI_EXIT_DISC
:
2447 ret
= bgp_attr_med (&attr_args
);
2449 case BGP_ATTR_LOCAL_PREF
:
2450 ret
= bgp_attr_local_pref (&attr_args
);
2452 case BGP_ATTR_ATOMIC_AGGREGATE
:
2453 ret
= bgp_attr_atomic (&attr_args
);
2455 case BGP_ATTR_AGGREGATOR
:
2456 ret
= bgp_attr_aggregator (&attr_args
);
2458 case BGP_ATTR_AS4_AGGREGATOR
:
2459 ret
= bgp_attr_as4_aggregator (&attr_args
,
2461 &as4_aggregator_addr
);
2463 case BGP_ATTR_COMMUNITIES
:
2464 ret
= bgp_attr_community (&attr_args
);
2466 case BGP_ATTR_ORIGINATOR_ID
:
2467 ret
= bgp_attr_originator_id (&attr_args
);
2469 case BGP_ATTR_CLUSTER_LIST
:
2470 ret
= bgp_attr_cluster_list (&attr_args
);
2472 case BGP_ATTR_MP_REACH_NLRI
:
2473 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
2475 case BGP_ATTR_MP_UNREACH_NLRI
:
2476 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
2478 case BGP_ATTR_EXT_COMMUNITIES
:
2479 ret
= bgp_attr_ext_communities (&attr_args
);
2484 case BGP_ATTR_ENCAP
:
2485 ret
= bgp_attr_encap (type
, peer
, length
, attr
, flag
, startp
);
2488 ret
= bgp_attr_unknown (&attr_args
);
2492 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
2494 bgp_notify_send (peer
,
2495 BGP_NOTIFY_UPDATE_ERR
,
2496 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2497 ret
= BGP_ATTR_PARSE_ERROR
;
2500 /* If hard error occured immediately return to the caller. */
2501 if (ret
== BGP_ATTR_PARSE_ERROR
)
2503 zlog_warn ("%s: Attribute %s, parse error",
2505 LOOKUP (attr_str
, type
));
2507 aspath_unintern (&as4_path
);
2510 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
2513 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2515 LOOKUP (attr_str
, type
));
2517 aspath_unintern (&as4_path
);
2521 /* Check the fetched length. */
2522 if (BGP_INPUT_PNT (peer
) != attr_endp
)
2524 zlog_warn ("%s: BGP attribute %s, fetch error",
2525 peer
->host
, LOOKUP (attr_str
, type
));
2526 bgp_notify_send (peer
,
2527 BGP_NOTIFY_UPDATE_ERR
,
2528 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2530 aspath_unintern (&as4_path
);
2531 return BGP_ATTR_PARSE_ERROR
;
2535 /* Check final read pointer is same as end pointer. */
2536 if (BGP_INPUT_PNT (peer
) != endp
)
2538 zlog_warn ("%s: BGP attribute %s, length mismatch",
2539 peer
->host
, LOOKUP (attr_str
, type
));
2540 bgp_notify_send (peer
,
2541 BGP_NOTIFY_UPDATE_ERR
,
2542 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2544 aspath_unintern (&as4_path
);
2545 return BGP_ATTR_PARSE_ERROR
;
2548 /* Check all mandatory well-known attributes are present */
2550 bgp_attr_parse_ret_t ret
;
2551 if ((ret
= bgp_attr_check (peer
, attr
)) < 0)
2554 aspath_unintern (&as4_path
);
2560 * At this place we can see whether we got AS4_PATH and/or
2561 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2562 * We can not do this before we've read all attributes because
2563 * the as4 handling does not say whether AS4_PATH has to be sent
2564 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2565 * in relationship to AGGREGATOR.
2566 * So, to be defensive, we are not relying on any order and read
2567 * all attributes first, including these 32bit ones, and now,
2568 * afterwards, we look what and if something is to be done for as4.
2570 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2573 /* actually... this doesn't ever return failure currently, but
2574 * better safe than sorry */
2575 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
))
2576 && bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2577 as4_aggregator
, &as4_aggregator_addr
))
2579 bgp_notify_send (peer
,
2580 BGP_NOTIFY_UPDATE_ERR
,
2581 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2583 aspath_unintern (&as4_path
);
2584 return BGP_ATTR_PARSE_ERROR
;
2587 /* At this stage, we have done all fiddling with as4, and the
2588 * resulting info is in attr->aggregator resp. attr->aspath
2589 * so we can chuck as4_aggregator and as4_path alltogether in
2590 * order to save memory
2594 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2595 /* The flag that we got this is still there, but that does not
2600 * The "rest" of the code does nothing with as4_aggregator.
2601 * there is no memory attached specifically which is not part
2603 * so ignoring just means do nothing.
2606 * Finally do the checks on the aspath we did not do yet
2607 * because we waited for a potentially synthesized aspath.
2609 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2611 ret
= bgp_attr_aspath_check (peer
, attr
);
2612 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2617 /* Finally intern unknown attribute. */
2618 if (attr
->extra
->transit
)
2619 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2620 if (attr
->extra
->encap_subtlvs
)
2621 attr
->extra
->encap_subtlvs
= encap_intern (attr
->extra
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2623 if (attr
->extra
->vnc_subtlvs
)
2624 attr
->extra
->vnc_subtlvs
= encap_intern (attr
->extra
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2628 return BGP_ATTR_PARSE_PROCEED
;
2632 bgp_packet_mpattr_start (struct stream
*s
, afi_t afi
, safi_t safi
, afi_t nh_afi
,
2633 struct bpacket_attr_vec_arr
*vecarr
,
2638 /* Set extended bit always to encode the attribute length as 2 bytes */
2639 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2640 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2641 sizep
= stream_get_endp (s
);
2642 stream_putw (s
, 0); /* Marker: Attribute length. */
2644 stream_putw (s
, afi
);
2645 stream_putc (s
, (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
);
2654 case SAFI_MULTICAST
:
2655 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2657 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2660 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2661 stream_putc (s
, 12);
2662 stream_putl (s
, 0); /* RD = 0, per RFC */
2664 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2668 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2679 case SAFI_MULTICAST
:
2681 struct attr_extra
*attre
= attr
->extra
;
2683 assert (attr
->extra
);
2684 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2685 stream_putc (s
, attre
->mp_nexthop_len
);
2686 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2687 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2688 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2693 struct attr_extra
*attre
= attr
->extra
;
2695 assert (attr
->extra
);
2696 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2697 stream_putc (s
, 24);
2698 stream_putl (s
, 0); /* RD = 0, per RFC */
2700 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2701 } else if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2702 stream_putc (s
, 48);
2703 stream_putl (s
, 0); /* RD = 0, per RFC */
2705 stream_put (s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2706 stream_putl (s
, 0); /* RD = 0, per RFC */
2708 stream_put (s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
2713 assert (attr
->extra
);
2714 stream_putc (s
, IPV6_MAX_BYTELEN
);
2715 stream_put (s
, &attr
->extra
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
2721 #endif /*HAVE_IPV6*/
2732 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2733 struct prefix
*p
, struct prefix_rd
*prd
,
2734 u_char
*tag
, int addpath_encode
,
2735 u_int32_t addpath_tx_id
)
2737 if (safi
== SAFI_MPLS_VPN
)
2740 stream_putl(s
, addpath_tx_id
);
2741 /* Tag, RD, Prefix write. */
2742 stream_putc (s
, p
->prefixlen
+ 88);
2743 stream_put (s
, tag
, 3);
2744 stream_put (s
, prd
->val
, 8);
2745 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2748 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
2752 bgp_packet_mpattr_prefix_size (afi_t afi
, safi_t safi
, struct prefix
*p
)
2754 int size
= PSIZE (p
->prefixlen
);
2755 if (safi
== SAFI_MPLS_VPN
)
2761 * Encodes the tunnel encapsulation attribute,
2762 * and with ENABLE_BGP_VNC the VNC attribute which uses
2763 * almost the same TLV format
2766 bgp_packet_mpattr_tea(
2773 unsigned int attrlenfield
= 0;
2774 unsigned int attrhdrlen
= 0;
2775 struct bgp_attr_encap_subtlv
*subtlvs
;
2776 struct bgp_attr_encap_subtlv
*st
;
2777 const char *attrname
;
2779 if (!attr
|| !attr
->extra
)
2783 case BGP_ATTR_ENCAP
:
2784 attrname
= "Tunnel Encap";
2785 subtlvs
= attr
->extra
->encap_subtlvs
;
2788 * The tunnel encap attr has an "outer" tlv.
2790 * L = total length of subtlvs,
2791 * V = concatenated subtlvs.
2793 attrlenfield
= 2 + 2; /* T + L */
2794 attrhdrlen
= 1 + 1; /* subTLV T + L */
2800 subtlvs
= attr
->extra
->vnc_subtlvs
;
2801 attrlenfield
= 0; /* no outer T + L */
2802 attrhdrlen
= 2 + 2; /* subTLV T + L */
2811 /* if no tlvs, don't make attr */
2812 if (subtlvs
== NULL
)
2815 /* compute attr length */
2816 for (st
= subtlvs
; st
; st
= st
->next
) {
2817 attrlenfield
+= (attrhdrlen
+ st
->length
);
2820 if (attrlenfield
> 0xffff) {
2821 zlog_info ("%s attribute is too long (length=%d), can't send it",
2827 if (attrlenfield
> 0xff) {
2828 /* 2-octet length field */
2830 BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2831 stream_putc (s
, attrtype
);
2832 stream_putw (s
, attrlenfield
& 0xffff);
2834 /* 1-octet length field */
2835 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
);
2836 stream_putc (s
, attrtype
);
2837 stream_putc (s
, attrlenfield
& 0xff);
2840 if (attrtype
== BGP_ATTR_ENCAP
) {
2841 /* write outer T+L */
2842 stream_putw(s
, attr
->extra
->encap_tunneltype
);
2843 stream_putw(s
, attrlenfield
- 4);
2846 /* write each sub-tlv */
2847 for (st
= subtlvs
; st
; st
= st
->next
) {
2848 if (attrtype
== BGP_ATTR_ENCAP
) {
2849 stream_putc (s
, st
->type
);
2850 stream_putc (s
, st
->length
);
2853 stream_putw (s
, st
->type
);
2854 stream_putw (s
, st
->length
);
2857 stream_put (s
, st
->value
, st
->length
);
2862 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
2864 /* Set MP attribute length. Don't count the (2) bytes used to encode
2866 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
2869 /* Make attribute packet. */
2871 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
2872 struct stream
*s
, struct attr
*attr
,
2873 struct bpacket_attr_vec_arr
*vecarr
,
2874 struct prefix
*p
, afi_t afi
, safi_t safi
,
2875 struct peer
*from
, struct prefix_rd
*prd
, u_char
*tag
,
2877 u_int32_t addpath_tx_id
)
2880 size_t aspath_sizep
;
2881 struct aspath
*aspath
;
2882 int send_as4_path
= 0;
2883 int send_as4_aggregator
= 0;
2884 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2889 /* Remember current pointer. */
2890 cp
= stream_get_endp (s
);
2892 if (p
&& !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
2893 !peer_cap_enhe(peer
)))
2895 size_t mpattrlen_pos
= 0;
2897 mpattrlen_pos
= bgp_packet_mpattr_start(s
, afi
, safi
,
2898 (peer_cap_enhe(peer
) ? AFI_IP6
: afi
),
2900 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
,
2901 addpath_encode
, addpath_tx_id
);
2902 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2905 /* Origin attribute. */
2906 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2907 stream_putc (s
, BGP_ATTR_ORIGIN
);
2909 stream_putc (s
, attr
->origin
);
2911 /* AS path attribute. */
2913 /* If remote-peer is EBGP */
2914 if (peer
->sort
== BGP_PEER_EBGP
2915 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
2916 || attr
->aspath
->segments
== NULL
)
2917 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
2919 aspath
= aspath_dup (attr
->aspath
);
2921 /* Even though we may not be configured for confederations we may have
2922 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2923 aspath
= aspath_delete_confed_seq (aspath
);
2925 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
2927 /* Stuff our path CONFED_ID on the front */
2928 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
2932 if (peer
->change_local_as
) {
2933 /* If replace-as is specified, we only use the change_local_as when
2934 advertising routes. */
2935 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
2936 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2938 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
2940 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2944 else if (peer
->sort
== BGP_PEER_CONFED
)
2946 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2947 aspath
= aspath_dup (attr
->aspath
);
2948 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
2951 aspath
= attr
->aspath
;
2953 /* If peer is not AS4 capable, then:
2954 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2955 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2956 * types are in it (i.e. exclude them if they are there)
2957 * AND do this only if there is at least one asnum > 65535 in the path!
2958 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2959 * all ASnums > 65535 to BGP_AS_TRANS
2962 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2963 stream_putc (s
, BGP_ATTR_AS_PATH
);
2964 aspath_sizep
= stream_get_endp (s
);
2966 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
2968 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2971 if (!use32bit
&& aspath_has_as4 (aspath
))
2972 send_as4_path
= 1; /* we'll do this later, at the correct place */
2974 /* Nexthop attribute. */
2975 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&& !peer_cap_enhe(peer
))
2977 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
))
2979 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2980 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2981 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2983 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2985 else if (safi
== SAFI_UNICAST
&& peer_cap_enhe(from
))
2988 * Likely this is the case when an IPv4 prefix was received with
2989 * Extended Next-hop capability and now being advertised to
2991 * Setting the mandatory (ipv4) next-hop attribute here to enable
2992 * implicit next-hop self with correct (ipv4 address family).
2994 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2995 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2996 bpacket_attr_vec_arr_set_vec (vecarr
, BGP_ATTR_VEC_NH
, s
, NULL
);
2998 stream_put_ipv4 (s
, 0);
3002 /* MED attribute. */
3003 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
3006 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3007 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3009 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
3012 /* Local preference. */
3013 if (peer
->sort
== BGP_PEER_IBGP
||
3014 peer
->sort
== BGP_PEER_CONFED
)
3016 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3017 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3019 stream_putl (s
, attr
->local_pref
);
3022 /* Atomic aggregate. */
3023 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3025 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3026 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3031 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3033 assert (attr
->extra
);
3035 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3036 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3037 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3041 /* AS4 capable peer */
3043 stream_putl (s
, attr
->extra
->aggregator_as
);
3047 /* 2-byte AS peer */
3050 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3051 if ( attr
->extra
->aggregator_as
> 65535 )
3053 stream_putw (s
, BGP_AS_TRANS
);
3055 /* we have to send AS4_AGGREGATOR, too.
3056 * we'll do that later in order to send attributes in ascending
3059 send_as4_aggregator
= 1;
3062 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
3064 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3067 /* Community attribute. */
3068 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3069 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
3071 if (attr
->community
->size
* 4 > 255)
3073 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3074 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3075 stream_putw (s
, attr
->community
->size
* 4);
3079 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3080 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3081 stream_putc (s
, attr
->community
->size
* 4);
3083 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3086 /* Route Reflector. */
3087 if (peer
->sort
== BGP_PEER_IBGP
3089 && from
->sort
== BGP_PEER_IBGP
)
3091 /* Originator ID. */
3092 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3093 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
3096 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3097 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
3099 stream_put_in_addr (s
, &from
->remote_id
);
3102 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3103 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
3105 if (attr
->extra
&& attr
->extra
->cluster
)
3107 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
3108 /* If this peer configuration's parent BGP has cluster_id. */
3109 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3110 stream_put_in_addr (s
, &bgp
->cluster_id
);
3112 stream_put_in_addr (s
, &bgp
->router_id
);
3113 stream_put (s
, attr
->extra
->cluster
->list
,
3114 attr
->extra
->cluster
->length
);
3119 /* If this peer configuration's parent BGP has cluster_id. */
3120 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3121 stream_put_in_addr (s
, &bgp
->cluster_id
);
3123 stream_put_in_addr (s
, &bgp
->router_id
);
3127 /* Extended Communities attribute. */
3128 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3129 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
3131 struct attr_extra
*attre
= attr
->extra
;
3135 if (peer
->sort
== BGP_PEER_IBGP
3136 || peer
->sort
== BGP_PEER_CONFED
)
3138 if (attre
->ecommunity
->size
* 8 > 255)
3140 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3141 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3142 stream_putw (s
, attre
->ecommunity
->size
* 8);
3146 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3147 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3148 stream_putc (s
, attre
->ecommunity
->size
* 8);
3150 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
3156 int ecom_tr_size
= 0;
3159 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3161 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3164 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3172 if (ecom_tr_size
* 8 > 255)
3174 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3175 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3176 stream_putw (s
, ecom_tr_size
* 8);
3180 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3181 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
3182 stream_putc (s
, ecom_tr_size
* 8);
3185 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
3187 pnt
= attre
->ecommunity
->val
+ (i
* 8);
3190 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3193 stream_put (s
, pnt
, 8);
3199 if ( send_as4_path
)
3201 /* If the peer is NOT As4 capable, AND */
3202 /* there are ASnums > 65535 in path THEN
3203 * give out AS4_PATH */
3205 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3207 * Hm, I wonder... confederation things *should* only be at
3208 * the beginning of an aspath, right? Then we should use
3209 * aspath_delete_confed_seq for this, because it is already
3211 * Folks, talk to me: what is reasonable here!?
3213 aspath
= aspath_delete_confed_seq (aspath
);
3215 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3216 stream_putc (s
, BGP_ATTR_AS4_PATH
);
3217 aspath_sizep
= stream_get_endp (s
);
3219 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
3222 if (aspath
!= attr
->aspath
)
3223 aspath_free (aspath
);
3225 if ( send_as4_aggregator
)
3227 assert (attr
->extra
);
3229 /* send AS4_AGGREGATOR, at this place */
3230 /* this section of code moved here in order to ensure the correct
3231 * *ascending* order of attributes
3233 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3234 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
3236 stream_putl (s
, attr
->extra
->aggregator_as
);
3237 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3240 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) &&
3241 (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3243 /* Tunnel Encap attribute */
3244 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3248 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3252 /* Unknown transit attribute. */
3253 if (attr
->extra
&& attr
->extra
->transit
)
3254 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
3256 /* Return total size of attribute. */
3257 return stream_get_endp (s
) - cp
;
3261 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
3263 unsigned long attrlen_pnt
;
3265 /* Set extended bit always to encode the attribute length as 2 bytes */
3266 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
3267 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
3269 attrlen_pnt
= stream_get_endp (s
);
3270 stream_putw (s
, 0); /* Length of this attribute. */
3272 stream_putw (s
, afi
);
3273 stream_putc (s
, (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
);
3278 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
3279 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
3280 u_char
*tag
, int addpath_encode
,
3281 u_int32_t addpath_tx_id
)
3283 if (safi
== SAFI_MPLS_VPN
)
3287 stream_putl(s
, addpath_tx_id
);
3289 stream_putc (s
, p
->prefixlen
+ 88);
3290 stream_put (s
, tag
, 3);
3291 stream_put (s
, prd
->val
, 8);
3292 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3295 stream_put_prefix_addpath (s
, p
, addpath_encode
, addpath_tx_id
);
3299 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
3301 bgp_packet_mpattr_end (s
, attrlen_pnt
);
3304 /* Initialization of attribute. */
3306 bgp_attr_init (void)
3318 bgp_attr_finish (void)
3322 community_finish ();
3323 ecommunity_finish ();
3329 /* Make attribute packet. */
3331 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
3332 struct prefix
*prefix
)
3337 struct aspath
*aspath
;
3338 int addpath_encode
= 0;
3339 u_int32_t addpath_tx_id
= 0;
3341 /* Remember current pointer. */
3342 cp
= stream_get_endp (s
);
3344 /* Place holder of length. */
3347 /* Origin attribute. */
3348 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3349 stream_putc (s
, BGP_ATTR_ORIGIN
);
3351 stream_putc (s
, attr
->origin
);
3353 aspath
= attr
->aspath
;
3355 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3356 stream_putc (s
, BGP_ATTR_AS_PATH
);
3357 aspath_lenp
= stream_get_endp (s
);
3360 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
3362 /* Nexthop attribute. */
3363 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3366 && prefix
->family
!= AF_INET6
3367 #endif /* HAVE_IPV6 */
3370 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3371 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
3373 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
3376 /* MED attribute. */
3377 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
3379 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
3380 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
3382 stream_putl (s
, attr
->med
);
3385 /* Local preference. */
3386 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
3388 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3389 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
3391 stream_putl (s
, attr
->local_pref
);
3394 /* Atomic aggregate. */
3395 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
3397 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
3398 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3403 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
3405 assert (attr
->extra
);
3406 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3407 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
3409 stream_putl (s
, attr
->extra
->aggregator_as
);
3410 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
3413 /* Community attribute. */
3414 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
3416 if (attr
->community
->size
* 4 > 255)
3418 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
3419 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3420 stream_putw (s
, attr
->community
->size
* 4);
3424 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
3425 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
3426 stream_putc (s
, attr
->community
->size
* 4);
3428 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
3432 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3433 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
3434 (attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
||
3435 attr
->extra
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) )
3438 struct attr_extra
*attre
= attr
->extra
;
3440 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3441 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3442 sizep
= stream_get_endp (s
);
3445 stream_putc (s
, 0); /* Marker: Attribute length. */
3446 stream_putw(s
, AFI_IP6
); /* AFI */
3447 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3450 stream_putc(s
, attre
->mp_nexthop_len
);
3451 stream_put(s
, &attre
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3452 if (attre
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3453 stream_put(s
, &attre
->mp_nexthop_local
, IPV6_MAX_BYTELEN
);
3459 stream_put_prefix_addpath (s
, prefix
, addpath_encode
, addpath_tx_id
);
3461 /* Set MP attribute length. */
3462 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
3464 #endif /* HAVE_IPV6 */
3466 /* Return total size of attribute. */
3467 len
= stream_get_endp (s
) - cp
- 2;
3468 stream_putw_at (s
, cp
, len
);