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
33 #include "bgpd/bgpd.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_route.h"
36 #include "bgpd/bgp_aspath.h"
37 #include "bgpd/bgp_community.h"
38 #include "bgpd/bgp_debug.h"
39 #include "bgpd/bgp_packet.h"
40 #include "bgpd/bgp_ecommunity.h"
42 /* Attribute strings for logging. */
43 static const struct message attr_str
[] =
45 { BGP_ATTR_ORIGIN
, "ORIGIN" },
46 { BGP_ATTR_AS_PATH
, "AS_PATH" },
47 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
48 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
49 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
50 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
51 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
52 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
53 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
54 { BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST" },
55 { BGP_ATTR_DPA
, "DPA" },
56 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
57 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
58 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
59 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
60 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
61 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
62 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
63 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
65 static const int attr_str_max
= array_size(attr_str
);
67 static const struct message attr_flag_str
[] =
69 { BGP_ATTR_FLAG_OPTIONAL
, "Optional" },
70 { BGP_ATTR_FLAG_TRANS
, "Transitive" },
71 { BGP_ATTR_FLAG_PARTIAL
, "Partial" },
72 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
73 { BGP_ATTR_FLAG_EXTLEN
, "Extended Length" },
75 static const size_t attr_flag_str_max
= array_size(attr_flag_str
);
77 static struct hash
*cluster_hash
;
80 cluster_hash_alloc (void *p
)
82 struct cluster_list
* val
= (struct cluster_list
*) p
;
83 struct cluster_list
*cluster
;
85 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
86 cluster
->length
= val
->length
;
90 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
91 memcpy (cluster
->list
, val
->list
, val
->length
);
101 /* Cluster list related functions. */
102 static struct cluster_list
*
103 cluster_parse (struct in_addr
* pnt
, int length
)
105 struct cluster_list tmp
;
106 struct cluster_list
*cluster
;
111 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
117 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
121 for (i
= 0; i
< cluster
->length
/ 4; i
++)
122 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
128 cluster_hash_key_make (void *p
)
130 const struct cluster_list
*cluster
= p
;
132 return jhash(cluster
->list
, cluster
->length
, 0);
136 cluster_hash_cmp (const void *p1
, const void *p2
)
138 const struct cluster_list
* cluster1
= p1
;
139 const struct cluster_list
* cluster2
= p2
;
141 return (cluster1
->length
== cluster2
->length
&&
142 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
146 cluster_free (struct cluster_list
*cluster
)
149 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
150 XFREE (MTYPE_CLUSTER
, cluster
);
153 static struct cluster_list
*
154 cluster_dup (struct cluster_list
*cluster
)
156 struct cluster_list
*new;
158 new = XCALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
159 new->length
= cluster
->length
;
163 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
164 memcpy (new->list
, cluster
->list
, cluster
->length
);
172 static struct cluster_list
*
173 cluster_intern (struct cluster_list
*cluster
)
175 struct cluster_list
*find
;
177 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
184 cluster_unintern (struct cluster_list
*cluster
)
189 if (cluster
->refcnt
== 0)
191 hash_release (cluster_hash
, cluster
);
192 cluster_free (cluster
);
199 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
203 cluster_finish (void)
205 hash_free (cluster_hash
);
209 /* Unknown transit attribute. */
210 static struct hash
*transit_hash
;
213 transit_free (struct transit
*transit
)
216 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
217 XFREE (MTYPE_TRANSIT
, transit
);
220 static struct transit
*
221 transit_dup (struct transit
*transit
)
225 new = XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
226 new->length
= transit
->length
;
229 new->val
= XMALLOC (MTYPE_TRANSIT_VAL
, transit
->length
);
230 memcpy (new->val
, transit
->val
, transit
->length
);
239 transit_hash_alloc (void *p
)
241 /* Transit structure is already allocated. */
245 static struct transit
*
246 transit_intern (struct transit
*transit
)
248 struct transit
*find
;
250 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
252 transit_free (transit
);
259 transit_unintern (struct transit
*transit
)
264 if (transit
->refcnt
== 0)
266 hash_release (transit_hash
, transit
);
267 transit_free (transit
);
272 transit_hash_key_make (void *p
)
274 const struct transit
* transit
= p
;
276 return jhash(transit
->val
, transit
->length
, 0);
280 transit_hash_cmp (const void *p1
, const void *p2
)
282 const struct transit
* transit1
= p1
;
283 const struct transit
* transit2
= p2
;
285 return (transit1
->length
== transit2
->length
&&
286 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
292 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
296 transit_finish (void)
298 hash_free (transit_hash
);
302 /* Attribute hash routines. */
303 static struct hash
*attrhash
;
305 static struct attr_extra
*
306 bgp_attr_extra_new (void)
308 return XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
312 bgp_attr_extra_free (struct attr
*attr
)
316 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
322 bgp_attr_extra_get (struct attr
*attr
)
325 attr
->extra
= bgp_attr_extra_new();
329 /* Shallow copy of an attribute
330 * Though, not so shallow that it doesn't copy the contents
331 * of the attr_extra pointed to by 'extra'
334 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
336 struct attr_extra
*extra
= new->extra
;
339 /* if caller provided attr_extra space, use it in any case.
341 * This is neccesary even if orig->extra equals NULL, because otherwise
342 * memory may be later allocated on the heap by bgp_attr_extra_get.
344 * That memory would eventually be leaked, because the caller must not
345 * call bgp_attr_extra_free if he provided attr_extra on the stack.
350 memset(new->extra
, 0, sizeof(struct attr_extra
));
352 *new->extra
= *orig
->extra
;
354 else if (orig
->extra
)
356 new->extra
= bgp_attr_extra_new();
357 *new->extra
= *orig
->extra
;
362 bgp_attr_deep_dup (struct attr
*new, struct attr
*orig
)
365 new->aspath
= aspath_dup(orig
->aspath
);
368 new->community
= community_dup(orig
->community
);
372 if (orig
->extra
->ecommunity
)
373 new->extra
->ecommunity
= ecommunity_dup(orig
->extra
->ecommunity
);
374 if (orig
->extra
->cluster
)
375 new->extra
->cluster
= cluster_dup(orig
->extra
->cluster
);
376 if (orig
->extra
->transit
)
377 new->extra
->transit
= transit_dup(orig
->extra
->transit
);
382 bgp_attr_deep_free (struct attr
*attr
)
385 aspath_free(attr
->aspath
);
388 community_free(attr
->community
);
392 if (attr
->extra
->ecommunity
)
393 ecommunity_free(&attr
->extra
->ecommunity
);
394 if (attr
->extra
->cluster
)
395 cluster_free(attr
->extra
->cluster
);
396 if (attr
->extra
->transit
)
397 transit_free(attr
->extra
->transit
);
404 return attrhash
->count
;
408 attr_unknown_count (void)
410 return transit_hash
->count
;
414 attrhash_key_make (void *p
)
416 const struct attr
*attr
= (struct attr
*) p
;
417 const struct attr_extra
*extra
= attr
->extra
;
419 #define MIX(val) key = jhash_1word(val, key)
422 MIX(attr
->nexthop
.s_addr
);
424 MIX(attr
->local_pref
);
427 key
+= attr
->nexthop
.s_addr
;
429 key
+= attr
->local_pref
;
433 MIX(extra
->aggregator_as
);
434 MIX(extra
->aggregator_addr
.s_addr
);
436 MIX(extra
->mp_nexthop_global_in
.s_addr
);
437 MIX(extra
->originator_id
.s_addr
);
442 MIX(aspath_key_make (attr
->aspath
));
444 MIX(community_hash_make (attr
->community
));
448 if (extra
->ecommunity
)
449 MIX(ecommunity_hash_make (extra
->ecommunity
));
451 MIX(cluster_hash_key_make (extra
->cluster
));
453 MIX(transit_hash_key_make (extra
->transit
));
456 MIX(extra
->mp_nexthop_len
);
457 key
= jhash(extra
->mp_nexthop_global
.s6_addr
, 16, key
);
458 key
= jhash(extra
->mp_nexthop_local
.s6_addr
, 16, key
);
459 #endif /* HAVE_IPV6 */
466 attrhash_cmp (const void *p1
, const void *p2
)
468 const struct attr
* attr1
= p1
;
469 const struct attr
* attr2
= p2
;
471 if (attr1
->flag
== attr2
->flag
472 && attr1
->origin
== attr2
->origin
473 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
474 && attr1
->aspath
== attr2
->aspath
475 && attr1
->community
== attr2
->community
476 && attr1
->med
== attr2
->med
477 && attr1
->local_pref
== attr2
->local_pref
)
479 const struct attr_extra
*ae1
= attr1
->extra
;
480 const struct attr_extra
*ae2
= attr2
->extra
;
483 && ae1
->aggregator_as
== ae2
->aggregator_as
484 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
485 && ae1
->weight
== ae2
->weight
486 && ae1
->tag
== ae2
->tag
488 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
489 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
490 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
491 #endif /* HAVE_IPV6 */
492 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
493 && ae1
->ecommunity
== ae2
->ecommunity
494 && ae1
->cluster
== ae2
->cluster
495 && ae1
->transit
== ae2
->transit
496 && IPV4_ADDR_SAME (&ae1
->originator_id
, &ae2
->originator_id
))
500 /* neither attribute has extra attributes, so they're same */
510 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
514 attrhash_finish (void)
516 hash_free (attrhash
);
521 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
523 struct attr
*attr
= backet
->data
;
525 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
526 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
530 attr_show_all (struct vty
*vty
)
532 hash_iterate (attrhash
,
533 (void (*)(struct hash_backet
*, void *))
534 attr_show_all_iterator
,
539 bgp_attr_hash_alloc (void *p
)
541 struct attr
* val
= (struct attr
*) p
;
544 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
548 attr
->extra
= bgp_attr_extra_new ();
549 *attr
->extra
= *val
->extra
;
555 /* Internet argument attribute. */
557 bgp_attr_intern (struct attr
*attr
)
561 /* Intern referenced strucutre. */
564 if (! attr
->aspath
->refcnt
)
565 attr
->aspath
= aspath_intern (attr
->aspath
);
567 attr
->aspath
->refcnt
++;
571 if (! attr
->community
->refcnt
)
572 attr
->community
= community_intern (attr
->community
);
574 attr
->community
->refcnt
++;
578 struct attr_extra
*attre
= attr
->extra
;
580 if (attre
->ecommunity
)
582 if (! attre
->ecommunity
->refcnt
)
583 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
585 attre
->ecommunity
->refcnt
++;
590 if (! attre
->cluster
->refcnt
)
591 attre
->cluster
= cluster_intern (attre
->cluster
);
593 attre
->cluster
->refcnt
++;
597 if (! attre
->transit
->refcnt
)
598 attre
->transit
= transit_intern (attre
->transit
);
600 attre
->transit
->refcnt
++;
604 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
611 /* Make network statement's attribute. */
613 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
615 memset (attr
, 0, sizeof (struct attr
));
616 bgp_attr_extra_get (attr
);
618 attr
->origin
= origin
;
619 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
620 attr
->aspath
= aspath_empty ();
621 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
622 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
623 attr
->extra
->tag
= 0;
624 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
626 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
633 /* Make network statement's attribute. */
635 bgp_attr_default_intern (u_char origin
)
640 bgp_attr_default_set(&attr
, origin
);
642 new = bgp_attr_intern (&attr
);
643 bgp_attr_extra_free (&attr
);
645 aspath_unintern (&new->aspath
);
649 /* Create the attributes for an aggregate */
651 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
652 struct aspath
*aspath
,
653 struct community
*community
, int as_set
,
654 u_char atomic_aggregate
)
658 struct attr_extra attre
;
660 memset (&attr
, 0, sizeof (struct attr
));
661 memset (&attre
, 0, sizeof (struct attr_extra
));
664 /* Origin attribute. */
665 attr
.origin
= origin
;
666 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
668 /* AS path attribute. */
670 attr
.aspath
= aspath_intern (aspath
);
672 attr
.aspath
= aspath_empty ();
673 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
675 /* Next hop attribute. */
676 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
680 attr
.community
= community
;
681 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
684 attre
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
686 attre
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
688 if (! as_set
|| atomic_aggregate
)
689 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
690 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
691 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
692 attre
.aggregator_as
= bgp
->confed_id
;
694 attre
.aggregator_as
= bgp
->as
;
695 attre
.aggregator_addr
= bgp
->router_id
;
697 new = bgp_attr_intern (&attr
);
699 aspath_unintern (&new->aspath
);
703 /* Unintern just the sub-components of the attr, but not the attr */
705 bgp_attr_unintern_sub (struct attr
*attr
)
707 /* aspath refcount shoud be decrement. */
709 aspath_unintern (&attr
->aspath
);
710 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
));
713 community_unintern (&attr
->community
);
714 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
));
718 if (attr
->extra
->ecommunity
)
719 ecommunity_unintern (&attr
->extra
->ecommunity
);
720 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
));
722 if (attr
->extra
->cluster
)
723 cluster_unintern (attr
->extra
->cluster
);
724 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
));
726 if (attr
->extra
->transit
)
727 transit_unintern (attr
->extra
->transit
);
731 /* Free bgp attribute and aspath. */
733 bgp_attr_unintern (struct attr
**pattr
)
735 struct attr
*attr
= *pattr
;
738 struct attr_extra tmp_extra
;
740 /* Decrement attribute reference. */
747 tmp
.extra
= &tmp_extra
;
748 memcpy (tmp
.extra
, attr
->extra
, sizeof (struct attr_extra
));
751 /* If reference becomes zero then free attribute object. */
752 if (attr
->refcnt
== 0)
754 ret
= hash_release (attrhash
, attr
);
755 assert (ret
!= NULL
);
756 bgp_attr_extra_free (attr
);
757 XFREE (MTYPE_ATTR
, attr
);
761 bgp_attr_unintern_sub (&tmp
);
765 bgp_attr_flush (struct attr
*attr
)
767 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
768 aspath_free (attr
->aspath
);
769 if (attr
->community
&& ! attr
->community
->refcnt
)
770 community_free (attr
->community
);
773 struct attr_extra
*attre
= attr
->extra
;
775 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
776 ecommunity_free (&attre
->ecommunity
);
777 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
778 cluster_free (attre
->cluster
);
779 if (attre
->transit
&& ! attre
->transit
->refcnt
)
780 transit_free (attre
->transit
);
784 /* Implement draft-scudder-idr-optional-transitive behaviour and
785 * avoid resetting sessions for malformed attributes which are
786 * are partial/optional and hence where the error likely was not
787 * introduced by the sending neighbour.
789 static bgp_attr_parse_ret_t
790 bgp_attr_malformed (struct bgp_attr_parser_args
*args
, u_char subcode
,
793 struct peer
*const peer
= args
->peer
;
794 const u_int8_t flags
= args
->flags
;
795 /* startp and length must be special-cased, as whether or not to
796 * send the attribute data with the NOTIFY depends on the error,
797 * the caller therefore signals this with the seperate length argument
799 u_char
*notify_datap
= (length
> 0 ? args
->startp
: NULL
);
801 /* Only relax error handling for eBGP peers */
802 if (peer
->sort
!= BGP_PEER_EBGP
)
804 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
805 notify_datap
, length
);
806 return BGP_ATTR_PARSE_ERROR
;
810 /* Adjust the stream getp to the end of the attribute, in case we can
811 * still proceed but the caller hasn't read all the attribute.
813 stream_set_getp (BGP_INPUT (peer
),
814 (args
->startp
- STREAM_DATA (BGP_INPUT (peer
)))
817 switch (args
->type
) {
818 /* where an attribute is relatively inconsequential, e.g. it does not
819 * affect route selection, and can be safely ignored, then any such
820 * attributes which are malformed should just be ignored and the route
821 * processed as normal.
823 case BGP_ATTR_AS4_AGGREGATOR
:
824 case BGP_ATTR_AGGREGATOR
:
825 case BGP_ATTR_ATOMIC_AGGREGATE
:
826 return BGP_ATTR_PARSE_PROCEED
;
828 /* Core attributes, particularly ones which may influence route
829 * selection, should always cause session resets
831 case BGP_ATTR_ORIGIN
:
832 case BGP_ATTR_AS_PATH
:
833 case BGP_ATTR_NEXT_HOP
:
834 case BGP_ATTR_MULTI_EXIT_DISC
:
835 case BGP_ATTR_LOCAL_PREF
:
836 case BGP_ATTR_COMMUNITIES
:
837 case BGP_ATTR_ORIGINATOR_ID
:
838 case BGP_ATTR_CLUSTER_LIST
:
839 case BGP_ATTR_MP_REACH_NLRI
:
840 case BGP_ATTR_MP_UNREACH_NLRI
:
841 case BGP_ATTR_EXT_COMMUNITIES
:
842 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
843 notify_datap
, length
);
844 return BGP_ATTR_PARSE_ERROR
;
847 /* Partial optional attributes that are malformed should not cause
848 * the whole session to be reset. Instead treat it as a withdrawal
849 * of the routes, if possible.
851 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
)
852 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
853 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
854 return BGP_ATTR_PARSE_WITHDRAW
;
856 /* default to reset */
857 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
860 /* Find out what is wrong with the path attribute flag bits and log the error.
861 "Flag bits" here stand for Optional, Transitive and Partial, but not for
862 Extended Length. Checking O/T/P bits at once implies, that the attribute
863 being diagnosed is defined by RFC as either a "well-known" or an "optional,
864 non-transitive" attribute. */
866 bgp_attr_flags_diagnose (struct bgp_attr_parser_args
*args
,
867 u_int8_t desired_flags
/* how RFC says it must be */
871 u_char real_flags
= args
->flags
;
872 const u_int8_t attr_code
= args
->type
;
874 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
875 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
876 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
879 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) !=
880 CHECK_FLAG (real_flags
, attr_flag_str
[i
].key
)
883 zlog_err ("%s attribute must%s be flagged as \"%s\"",
884 LOOKUP (attr_str
, attr_code
),
885 CHECK_FLAG (desired_flags
, attr_flag_str
[i
].key
) ? "" : " not",
886 attr_flag_str
[i
].str
);
891 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
892 " (real flags 0x%x, desired 0x%x)",
893 __func__
, LOOKUP (attr_str
, attr_code
),
894 real_flags
, desired_flags
);
898 /* Required flags for attributes. EXTLEN will be masked off when testing,
899 * as will PARTIAL for optional+transitive attributes.
901 const u_int8_t attr_flags_values
[] = {
902 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
903 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
904 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
905 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
906 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
907 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
908 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
909 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
910 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
911 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
912 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
913 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
914 [BGP_ATTR_EXT_COMMUNITIES
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
915 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
916 [BGP_ATTR_AS4_AGGREGATOR
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
918 static const size_t attr_flags_values_max
=
919 sizeof (attr_flags_values
) / sizeof (attr_flags_values
[0]);
922 bgp_attr_flag_invalid (struct bgp_attr_parser_args
*args
)
924 u_int8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
925 const u_int8_t flags
= args
->flags
;
926 const u_int8_t attr_code
= args
->type
;
927 struct peer
*const peer
= args
->peer
;
929 /* there may be attributes we don't know about */
930 if (attr_code
> attr_flags_values_max
)
932 if (attr_flags_values
[attr_code
] == 0)
935 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
938 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL
, flags
)
939 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS
, flags
))
941 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
942 LOOKUP (attr_str
, attr_code
), flags
);
946 /* "For well-known attributes and for optional non-transitive attributes,
947 * the Partial bit MUST be set to 0."
949 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_PARTIAL
))
951 if (!CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
))
953 zlog_err ("%s well-known attribute "
954 "must NOT have the partial flag set (%x)",
955 LOOKUP (attr_str
, attr_code
), flags
);
958 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
959 && !CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
961 zlog_err ("%s optional + transitive attribute "
962 "must NOT have the partial flag set (%x)",
963 LOOKUP (attr_str
, attr_code
), flags
);
968 /* Optional transitive attributes may go through speakers that don't
969 * reocgnise them and set the Partial bit.
971 if (CHECK_FLAG (flags
, BGP_ATTR_FLAG_OPTIONAL
)
972 && CHECK_FLAG (flags
, BGP_ATTR_FLAG_TRANS
))
973 SET_FLAG (mask
, BGP_ATTR_FLAG_PARTIAL
);
976 == attr_flags_values
[attr_code
])
979 bgp_attr_flags_diagnose (args
, attr_flags_values
[attr_code
]);
983 /* Get origin attribute of the update message. */
984 static bgp_attr_parse_ret_t
985 bgp_attr_origin (struct bgp_attr_parser_args
*args
)
987 struct peer
*const peer
= args
->peer
;
988 struct attr
*const attr
= args
->attr
;
989 const bgp_size_t length
= args
->length
;
991 /* If any recognized attribute has Attribute Length that conflicts
992 with the expected length (based on the attribute type code), then
993 the Error Subcode is set to Attribute Length Error. The Data
994 field contains the erroneous attribute (type, length and
998 zlog_err ("Origin attribute length is not one %d", length
);
999 return bgp_attr_malformed (args
,
1000 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1004 /* Fetch origin attribute. */
1005 attr
->origin
= stream_getc (BGP_INPUT (peer
));
1007 /* If the ORIGIN attribute has an undefined value, then the Error
1008 Subcode is set to Invalid Origin Attribute. The Data field
1009 contains the unrecognized attribute (type, length and value). */
1010 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
1011 && (attr
->origin
!= BGP_ORIGIN_EGP
)
1012 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
1014 zlog_err ("Origin attribute value is invalid %d", attr
->origin
);
1015 return bgp_attr_malformed (args
,
1016 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1020 /* Set oring attribute flag. */
1021 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
1026 /* Parse AS path information. This function is wrapper of
1029 bgp_attr_aspath (struct bgp_attr_parser_args
*args
)
1031 struct attr
*const attr
= args
->attr
;
1032 struct peer
*const peer
= args
->peer
;
1033 const bgp_size_t length
= args
->length
;
1036 * peer with AS4 => will get 4Byte ASnums
1037 * otherwise, will get 16 Bit
1039 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
1040 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
1042 /* In case of IBGP, length will be zero. */
1045 zlog_err ("Malformed AS path from %s, length is %d", peer
->host
, length
);
1046 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
, 0);
1049 /* Set aspath attribute flag. */
1050 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
1052 return BGP_ATTR_PARSE_PROCEED
;
1055 static bgp_attr_parse_ret_t
1056 bgp_attr_aspath_check (struct peer
*const peer
, struct attr
*const attr
)
1058 /* These checks were part of bgp_attr_aspath, but with
1059 * as4 we should to check aspath things when
1060 * aspath synthesizing with as4_path has already taken place.
1061 * Otherwise we check ASPATH and use the synthesized thing, and that is
1063 * So do the checks later, i.e. here
1065 struct bgp
*bgp
= peer
->bgp
;
1066 struct aspath
*aspath
;
1068 /* Confederation sanity check. */
1069 if ((peer
->sort
== BGP_PEER_CONFED
&& ! aspath_left_confed_check (attr
->aspath
)) ||
1070 (peer
->sort
== BGP_PEER_EBGP
&& aspath_confed_check (attr
->aspath
)))
1072 zlog_err ("Malformed AS path from %s", peer
->host
);
1073 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1074 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1075 return BGP_ATTR_PARSE_ERROR
;
1078 /* First AS check for EBGP. */
1079 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
1081 if (peer
->sort
== BGP_PEER_EBGP
1082 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
1084 zlog_err ("%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
1085 bgp_notify_send (peer
, BGP_NOTIFY_UPDATE_ERR
,
1086 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1087 return BGP_ATTR_PARSE_ERROR
;
1091 /* local-as prepend */
1092 if (peer
->change_local_as
&&
1093 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
1095 aspath
= aspath_dup (attr
->aspath
);
1096 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1097 aspath_unintern (&attr
->aspath
);
1098 attr
->aspath
= aspath_intern (aspath
);
1101 return BGP_ATTR_PARSE_PROCEED
;
1104 /* Parse AS4 path information. This function is another wrapper of
1107 bgp_attr_as4_path (struct bgp_attr_parser_args
*args
, struct aspath
**as4_path
)
1109 struct peer
*const peer
= args
->peer
;
1110 struct attr
*const attr
= args
->attr
;
1111 const bgp_size_t length
= args
->length
;
1113 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
1115 /* In case of IBGP, length will be zero. */
1118 zlog_err ("Malformed AS4 path from %s, length is %d", peer
->host
, length
);
1119 return bgp_attr_malformed (args
,
1120 BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1124 /* Set aspath attribute flag. */
1126 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
1128 return BGP_ATTR_PARSE_PROCEED
;
1131 /* Nexthop attribute. */
1132 static bgp_attr_parse_ret_t
1133 bgp_attr_nexthop (struct bgp_attr_parser_args
*args
)
1135 struct peer
*const peer
= args
->peer
;
1136 struct attr
*const attr
= args
->attr
;
1137 const bgp_size_t length
= args
->length
;
1139 in_addr_t nexthop_h
, nexthop_n
;
1141 /* Check nexthop attribute length. */
1144 zlog_err ("Nexthop attribute length isn't four [%d]", length
);
1146 return bgp_attr_malformed (args
,
1147 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1151 nexthop_n
= stream_get_ipv4 (peer
->ibuf
);
1152 nexthop_h
= ntohl (nexthop_n
);
1153 if (!bgp_valid_host_address(nexthop_h
))
1155 char buf
[INET_ADDRSTRLEN
];
1156 inet_ntop (AF_INET
, &nexthop_n
, buf
, INET_ADDRSTRLEN
);
1157 zlog_err ("Martian nexthop %s", buf
);
1158 return bgp_attr_malformed (args
,
1159 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1163 attr
->nexthop
.s_addr
= nexthop_n
;
1164 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
1166 return BGP_ATTR_PARSE_PROCEED
;
1169 /* MED atrribute. */
1170 static bgp_attr_parse_ret_t
1171 bgp_attr_med (struct bgp_attr_parser_args
*args
)
1173 struct peer
*const peer
= args
->peer
;
1174 struct attr
*const attr
= args
->attr
;
1175 const bgp_size_t length
= args
->length
;
1180 zlog_err ("MED attribute length isn't four [%d]", length
);
1182 return bgp_attr_malformed (args
,
1183 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1187 attr
->med
= stream_getl (peer
->ibuf
);
1189 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
1191 return BGP_ATTR_PARSE_PROCEED
;
1194 /* Local preference attribute. */
1195 static bgp_attr_parse_ret_t
1196 bgp_attr_local_pref (struct bgp_attr_parser_args
*args
)
1198 struct peer
*const peer
= args
->peer
;
1199 struct attr
*const attr
= args
->attr
;
1200 const bgp_size_t length
= args
->length
;
1205 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length
);
1206 return bgp_attr_malformed (args
,
1207 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1211 /* If it is contained in an UPDATE message that is received from an
1212 external peer, then this attribute MUST be ignored by the
1213 receiving speaker. */
1214 if (peer
->sort
== BGP_PEER_EBGP
)
1216 stream_forward_getp (peer
->ibuf
, length
);
1217 return BGP_ATTR_PARSE_PROCEED
;
1220 attr
->local_pref
= stream_getl (peer
->ibuf
);
1222 /* Set atomic aggregate flag. */
1223 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
1225 return BGP_ATTR_PARSE_PROCEED
;
1228 /* Atomic aggregate. */
1230 bgp_attr_atomic (struct bgp_attr_parser_args
*args
)
1232 struct peer
*const peer
= args
->peer
;
1233 struct attr
*const attr
= args
->attr
;
1234 const bgp_size_t length
= args
->length
;
1239 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length
);
1240 return bgp_attr_malformed (args
,
1241 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1245 /* Set atomic aggregate flag. */
1246 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1248 return BGP_ATTR_PARSE_PROCEED
;
1251 /* Aggregator attribute */
1253 bgp_attr_aggregator (struct bgp_attr_parser_args
*args
)
1255 struct peer
*const peer
= args
->peer
;
1256 struct attr
*const attr
= args
->attr
;
1257 const bgp_size_t length
= args
->length
;
1260 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1262 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1263 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1266 if (length
!= wantedlen
)
1268 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen
, length
);
1269 return bgp_attr_malformed (args
,
1270 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1274 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1275 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1277 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1278 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1280 /* Set atomic aggregate flag. */
1281 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1283 return BGP_ATTR_PARSE_PROCEED
;
1286 /* New Aggregator attribute */
1287 static bgp_attr_parse_ret_t
1288 bgp_attr_as4_aggregator (struct bgp_attr_parser_args
*args
,
1289 as_t
*as4_aggregator_as
,
1290 struct in_addr
*as4_aggregator_addr
)
1292 struct peer
*const peer
= args
->peer
;
1293 struct attr
*const attr
= args
->attr
;
1294 const bgp_size_t length
= args
->length
;
1298 zlog_err ("New Aggregator length is not 8 [%d]", length
);
1299 return bgp_attr_malformed (args
,
1300 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1304 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1305 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1307 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1309 return BGP_ATTR_PARSE_PROCEED
;
1312 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1314 static bgp_attr_parse_ret_t
1315 bgp_attr_munge_as4_attrs (struct peer
*const peer
,
1316 struct attr
*const attr
,
1317 struct aspath
*as4_path
, as_t as4_aggregator
,
1318 struct in_addr
*as4_aggregator_addr
)
1320 int ignore_as4_path
= 0;
1321 struct aspath
*newpath
;
1322 struct attr_extra
*attre
= attr
->extra
;
1324 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
))
1326 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1328 * It is worth a warning though, because the peer really
1329 * should not send them
1331 if (BGP_DEBUG(as4
, AS4
))
1333 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1334 zlog_debug ("[AS4] %s %s AS4_PATH",
1335 peer
->host
, "AS4 capable peer, yet it sent");
1337 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1338 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1339 peer
->host
, "AS4 capable peer, yet it sent");
1342 return BGP_ATTR_PARSE_PROCEED
;
1345 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1346 * because that may override AS4_PATH
1348 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1350 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1355 * if the as_number in aggregator is not AS_TRANS,
1356 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1357 * and the Aggregator shall be taken as
1358 * info on the aggregating node, and the AS_PATH
1359 * shall be taken as the AS_PATH
1361 * the Aggregator shall be ignored and the
1362 * AS4_AGGREGATOR shall be taken as the
1363 * Aggregating node and the AS_PATH is to be
1364 * constructed "as in all other cases"
1366 if (attre
->aggregator_as
!= BGP_AS_TRANS
)
1369 if ( BGP_DEBUG(as4
, AS4
))
1370 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1371 " send AGGREGATOR != AS_TRANS and"
1372 " AS4_AGGREGATOR, so ignore"
1373 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1374 ignore_as4_path
= 1;
1378 /* "New_aggregator shall be taken as aggregator" */
1379 attre
->aggregator_as
= as4_aggregator
;
1380 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1385 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1386 * That is bogus - but reading the conditions
1387 * we have to handle AS4_AGGREGATOR as if it were
1388 * AGGREGATOR in that case
1390 if ( BGP_DEBUG(as4
, AS4
))
1391 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1392 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1393 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1394 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1395 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1396 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1400 /* need to reconcile NEW_AS_PATH and AS_PATH */
1401 if (!ignore_as4_path
&& (attr
->flag
& (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))))
1404 return BGP_ATTR_PARSE_PROCEED
;
1406 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1407 aspath_unintern (&attr
->aspath
);
1408 attr
->aspath
= aspath_intern (newpath
);
1410 return BGP_ATTR_PARSE_PROCEED
;
1413 /* Community attribute. */
1414 static bgp_attr_parse_ret_t
1415 bgp_attr_community (struct bgp_attr_parser_args
*args
)
1417 struct peer
*const peer
= args
->peer
;
1418 struct attr
*const attr
= args
->attr
;
1419 const bgp_size_t length
= args
->length
;
1423 attr
->community
= NULL
;
1424 return BGP_ATTR_PARSE_PROCEED
;
1428 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1430 /* XXX: fix community_parse to use stream API and remove this */
1431 stream_forward_getp (peer
->ibuf
, length
);
1433 if (!attr
->community
)
1434 return bgp_attr_malformed (args
,
1435 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1438 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1440 return BGP_ATTR_PARSE_PROCEED
;
1443 /* Originator ID attribute. */
1444 static bgp_attr_parse_ret_t
1445 bgp_attr_originator_id (struct bgp_attr_parser_args
*args
)
1447 struct peer
*const peer
= args
->peer
;
1448 struct attr
*const attr
= args
->attr
;
1449 const bgp_size_t length
= args
->length
;
1454 zlog_err ("Bad originator ID length %d", length
);
1456 return bgp_attr_malformed (args
,
1457 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1461 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1462 = stream_get_ipv4 (peer
->ibuf
);
1464 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1466 return BGP_ATTR_PARSE_PROCEED
;
1469 /* Cluster list attribute. */
1470 static bgp_attr_parse_ret_t
1471 bgp_attr_cluster_list (struct bgp_attr_parser_args
*args
)
1473 struct peer
*const peer
= args
->peer
;
1474 struct attr
*const attr
= args
->attr
;
1475 const bgp_size_t length
= args
->length
;
1480 zlog_err ("Bad cluster list length %d", length
);
1482 return bgp_attr_malformed (args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1486 (bgp_attr_extra_get (attr
))->cluster
1487 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1489 /* XXX: Fix cluster_parse to use stream API and then remove this */
1490 stream_forward_getp (peer
->ibuf
, length
);
1492 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1494 return BGP_ATTR_PARSE_PROCEED
;
1497 /* Multiprotocol reachability information parse. */
1499 bgp_mp_reach_parse (struct bgp_attr_parser_args
*args
,
1500 struct bgp_nlri
*mp_update
)
1504 bgp_size_t nlri_len
;
1509 struct peer
*const peer
= args
->peer
;
1510 struct attr
*const attr
= args
->attr
;
1511 const bgp_size_t length
= args
->length
;
1512 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1514 /* Set end of packet. */
1515 s
= BGP_INPUT(peer
);
1516 start
= stream_get_getp(s
);
1518 /* safe to read statically sized header? */
1519 #define BGP_MP_REACH_MIN_SIZE 5
1520 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1521 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1523 zlog_info ("%s: %s sent invalid length, %lu",
1524 __func__
, peer
->host
, (unsigned long)length
);
1525 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1528 /* Load AFI, SAFI. */
1529 afi
= stream_getw (s
);
1530 safi
= stream_getc (s
);
1532 /* Get nexthop length. */
1533 attre
->mp_nexthop_len
= stream_getc (s
);
1535 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1537 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1538 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1539 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1542 /* Nexthop length check. */
1543 switch (attre
->mp_nexthop_len
)
1546 stream_get (&attre
->mp_nexthop_global_in
, s
, 4);
1547 /* Probably needed for RFC 2283 */
1548 if (attr
->nexthop
.s_addr
== 0)
1549 memcpy(&attr
->nexthop
.s_addr
, &attre
->mp_nexthop_global_in
, 4);
1552 stream_getl (s
); /* RD high */
1553 stream_getl (s
); /* RD low */
1554 stream_get (&attre
->mp_nexthop_global_in
, s
, 4);
1558 stream_get (&attre
->mp_nexthop_global
, s
, 16);
1561 stream_get (&attre
->mp_nexthop_global
, s
, 16);
1562 stream_get (&attre
->mp_nexthop_local
, s
, 16);
1563 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1565 char buf1
[INET6_ADDRSTRLEN
];
1566 char buf2
[INET6_ADDRSTRLEN
];
1568 if (bgp_debug_update(peer
, NULL
, 1))
1569 zlog_debug ("%s sent two nexthops %s %s but second one is not a link-local nexthop", peer
->host
,
1570 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1571 buf1
, INET6_ADDRSTRLEN
),
1572 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1573 buf2
, INET6_ADDRSTRLEN
));
1575 attre
->mp_nexthop_len
= 16;
1578 #endif /* HAVE_IPV6 */
1580 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1581 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1582 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1587 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1588 __func__
, peer
->host
);
1589 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1594 if ((val
= stream_getc (s
)))
1595 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1599 /* must have nrli_len, what is left of the attribute */
1600 nlri_len
= LEN_LEFT
;
1601 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
1603 zlog_info ("%s: (%s) Failed to read NLRI",
1604 __func__
, peer
->host
);
1605 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1608 if (safi
!= SAFI_MPLS_LABELED_VPN
)
1610 ret
= bgp_nlri_sanity_check (peer
, afi
, safi
, stream_pnt (s
),
1611 nlri_len
, &num_mp_pfx
);
1614 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1615 __func__
, peer
->host
);
1616 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1620 mp_update
->afi
= afi
;
1621 mp_update
->safi
= safi
;
1622 mp_update
->nlri
= stream_pnt (s
);
1623 mp_update
->length
= nlri_len
;
1625 stream_forward_getp (s
, nlri_len
);
1627 return BGP_ATTR_PARSE_PROCEED
;
1631 /* Multiprotocol unreachable parse */
1633 bgp_mp_unreach_parse (struct bgp_attr_parser_args
*args
,
1634 struct bgp_nlri
*mp_withdraw
)
1639 u_int16_t withdraw_len
;
1642 struct peer
*const peer
= args
->peer
;
1643 const bgp_size_t length
= args
->length
;
1647 #define BGP_MP_UNREACH_MIN_SIZE 3
1648 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1649 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1651 afi
= stream_getw (s
);
1652 safi
= stream_getc (s
);
1654 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1656 if (safi
!= SAFI_MPLS_LABELED_VPN
)
1658 ret
= bgp_nlri_sanity_check (peer
, afi
, safi
, stream_pnt (s
),
1659 withdraw_len
, &num_mp_pfx
);
1661 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1664 mp_withdraw
->afi
= afi
;
1665 mp_withdraw
->safi
= safi
;
1666 mp_withdraw
->nlri
= stream_pnt (s
);
1667 mp_withdraw
->length
= withdraw_len
;
1669 stream_forward_getp (s
, withdraw_len
);
1671 return BGP_ATTR_PARSE_PROCEED
;
1674 /* Extended Community attribute. */
1675 static bgp_attr_parse_ret_t
1676 bgp_attr_ext_communities (struct bgp_attr_parser_args
*args
)
1678 struct peer
*const peer
= args
->peer
;
1679 struct attr
*const attr
= args
->attr
;
1680 const bgp_size_t length
= args
->length
;
1685 attr
->extra
->ecommunity
= NULL
;
1686 /* Empty extcomm doesn't seem to be invalid per se */
1687 return BGP_ATTR_PARSE_PROCEED
;
1690 (bgp_attr_extra_get (attr
))->ecommunity
=
1691 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
1692 /* XXX: fix ecommunity_parse to use stream API */
1693 stream_forward_getp (peer
->ibuf
, length
);
1695 if (!attr
->extra
->ecommunity
)
1696 return bgp_attr_malformed (args
,
1697 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1700 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
1702 return BGP_ATTR_PARSE_PROCEED
;
1705 /* BGP unknown attribute treatment. */
1706 static bgp_attr_parse_ret_t
1707 bgp_attr_unknown (struct bgp_attr_parser_args
*args
)
1709 bgp_size_t total
= args
->total
;
1710 struct transit
*transit
;
1711 struct attr_extra
*attre
;
1712 struct peer
*const peer
= args
->peer
;
1713 struct attr
*const attr
= args
->attr
;
1714 u_char
*const startp
= args
->startp
;
1715 const u_char type
= args
->type
;
1716 const u_char flag
= args
->flags
;
1717 const bgp_size_t length
= args
->length
;
1719 if (bgp_debug_update(peer
, NULL
, 1))
1720 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1721 peer
->host
, type
, length
);
1723 /* Forward read pointer of input stream. */
1724 stream_forward_getp (peer
->ibuf
, length
);
1726 /* If any of the mandatory well-known attributes are not recognized,
1727 then the Error Subcode is set to Unrecognized Well-known
1728 Attribute. The Data field contains the unrecognized attribute
1729 (type, length and value). */
1730 if (!CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
1732 return bgp_attr_malformed (args
,
1733 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
1737 /* Unrecognized non-transitive optional attributes must be quietly
1738 ignored and not passed along to other BGP peers. */
1739 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
1740 return BGP_ATTR_PARSE_PROCEED
;
1742 /* If a path with recognized transitive optional attribute is
1743 accepted and passed along to other BGP peers and the Partial bit
1744 in the Attribute Flags octet is set to 1 by some previous AS, it
1745 is not set back to 0 by the current AS. */
1746 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
1748 /* Store transitive attribute to the end of attr->transit. */
1749 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
1750 attre
->transit
= XCALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
1752 transit
= attre
->transit
;
1755 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
1756 transit
->length
+ total
);
1758 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
1760 memcpy (transit
->val
+ transit
->length
, startp
, total
);
1761 transit
->length
+= total
;
1763 return BGP_ATTR_PARSE_PROCEED
;
1766 /* Read attribute of update packet. This function is called from
1767 bgp_update_receive() in bgp_packet.c. */
1768 bgp_attr_parse_ret_t
1769 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
1770 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
1776 u_char
*startp
, *endp
;
1778 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
1779 /* we need the as4_path only until we have synthesized the as_path with it */
1780 /* same goes for as4_aggregator */
1781 struct aspath
*as4_path
= NULL
;
1782 as_t as4_aggregator
= 0;
1783 struct in_addr as4_aggregator_addr
= { 0 };
1785 /* Initialize bitmap. */
1786 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
1788 /* End pointer of BGP attribute. */
1789 endp
= BGP_INPUT_PNT (peer
) + size
;
1791 /* Get attributes to the end of attribute length. */
1792 while (BGP_INPUT_PNT (peer
) < endp
)
1794 /* Check remaining length check.*/
1795 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
1797 /* XXX warning: long int format, int arg (arg 5) */
1798 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
1800 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
1802 bgp_notify_send (peer
,
1803 BGP_NOTIFY_UPDATE_ERR
,
1804 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1805 return BGP_ATTR_PARSE_ERROR
;
1808 /* Fetch attribute flag and type. */
1809 startp
= BGP_INPUT_PNT (peer
);
1810 /* "The lower-order four bits of the Attribute Flags octet are
1811 unused. They MUST be zero when sent and MUST be ignored when
1813 flag
= 0xF0 & stream_getc (BGP_INPUT (peer
));
1814 type
= stream_getc (BGP_INPUT (peer
));
1816 /* Check whether Extended-Length applies and is in bounds */
1817 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
1818 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
1820 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
1822 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
1824 bgp_notify_send (peer
,
1825 BGP_NOTIFY_UPDATE_ERR
,
1826 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1827 return BGP_ATTR_PARSE_ERROR
;
1830 /* Check extended attribue length bit. */
1831 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
1832 length
= stream_getw (BGP_INPUT (peer
));
1834 length
= stream_getc (BGP_INPUT (peer
));
1836 /* If any attribute appears more than once in the UPDATE
1837 message, then the Error Subcode is set to Malformed Attribute
1840 if (CHECK_BITMAP (seen
, type
))
1842 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
1845 bgp_notify_send (peer
,
1846 BGP_NOTIFY_UPDATE_ERR
,
1847 BGP_NOTIFY_UPDATE_MAL_ATTR
);
1848 return BGP_ATTR_PARSE_ERROR
;
1851 /* Set type to bitmap to check duplicate attribute. `type' is
1852 unsigned char so it never overflow bitmap range. */
1854 SET_BITMAP (seen
, type
);
1856 /* Overflow check. */
1857 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
1859 if (attr_endp
> endp
)
1861 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
);
1862 bgp_notify_send_with_data (peer
,
1863 BGP_NOTIFY_UPDATE_ERR
,
1864 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1865 startp
, attr_endp
- startp
);
1866 return BGP_ATTR_PARSE_ERROR
;
1869 struct bgp_attr_parser_args attr_args
= {
1876 .total
= attr_endp
- startp
,
1880 /* If any recognized attribute has Attribute Flags that conflict
1881 with the Attribute Type Code, then the Error Subcode is set to
1882 Attribute Flags Error. The Data field contains the erroneous
1883 attribute (type, length and value). */
1884 if (bgp_attr_flag_invalid (&attr_args
))
1886 bgp_attr_parse_ret_t ret
;
1887 ret
= bgp_attr_malformed (&attr_args
,
1888 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
1890 if (ret
== BGP_ATTR_PARSE_PROCEED
)
1895 /* OK check attribute and store it's value. */
1898 case BGP_ATTR_ORIGIN
:
1899 ret
= bgp_attr_origin (&attr_args
);
1901 case BGP_ATTR_AS_PATH
:
1902 ret
= bgp_attr_aspath (&attr_args
);
1904 case BGP_ATTR_AS4_PATH
:
1905 ret
= bgp_attr_as4_path (&attr_args
, &as4_path
);
1907 case BGP_ATTR_NEXT_HOP
:
1908 ret
= bgp_attr_nexthop (&attr_args
);
1910 case BGP_ATTR_MULTI_EXIT_DISC
:
1911 ret
= bgp_attr_med (&attr_args
);
1913 case BGP_ATTR_LOCAL_PREF
:
1914 ret
= bgp_attr_local_pref (&attr_args
);
1916 case BGP_ATTR_ATOMIC_AGGREGATE
:
1917 ret
= bgp_attr_atomic (&attr_args
);
1919 case BGP_ATTR_AGGREGATOR
:
1920 ret
= bgp_attr_aggregator (&attr_args
);
1922 case BGP_ATTR_AS4_AGGREGATOR
:
1923 ret
= bgp_attr_as4_aggregator (&attr_args
,
1925 &as4_aggregator_addr
);
1927 case BGP_ATTR_COMMUNITIES
:
1928 ret
= bgp_attr_community (&attr_args
);
1930 case BGP_ATTR_ORIGINATOR_ID
:
1931 ret
= bgp_attr_originator_id (&attr_args
);
1933 case BGP_ATTR_CLUSTER_LIST
:
1934 ret
= bgp_attr_cluster_list (&attr_args
);
1936 case BGP_ATTR_MP_REACH_NLRI
:
1937 ret
= bgp_mp_reach_parse (&attr_args
, mp_update
);
1939 case BGP_ATTR_MP_UNREACH_NLRI
:
1940 ret
= bgp_mp_unreach_parse (&attr_args
, mp_withdraw
);
1942 case BGP_ATTR_EXT_COMMUNITIES
:
1943 ret
= bgp_attr_ext_communities (&attr_args
);
1946 ret
= bgp_attr_unknown (&attr_args
);
1950 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
)
1952 bgp_notify_send (peer
,
1953 BGP_NOTIFY_UPDATE_ERR
,
1954 BGP_NOTIFY_UPDATE_MAL_ATTR
);
1955 ret
= BGP_ATTR_PARSE_ERROR
;
1958 /* If hard error occured immediately return to the caller. */
1959 if (ret
== BGP_ATTR_PARSE_ERROR
)
1961 zlog_warn ("%s: Attribute %s, parse error",
1963 LOOKUP (attr_str
, type
));
1965 aspath_unintern (&as4_path
);
1968 if (ret
== BGP_ATTR_PARSE_WITHDRAW
)
1971 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
1973 LOOKUP (attr_str
, type
));
1975 aspath_unintern (&as4_path
);
1979 /* Check the fetched length. */
1980 if (BGP_INPUT_PNT (peer
) != attr_endp
)
1982 zlog_warn ("%s: BGP attribute %s, fetch error",
1983 peer
->host
, LOOKUP (attr_str
, type
));
1984 bgp_notify_send (peer
,
1985 BGP_NOTIFY_UPDATE_ERR
,
1986 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1988 aspath_unintern (&as4_path
);
1989 return BGP_ATTR_PARSE_ERROR
;
1993 /* Check final read pointer is same as end pointer. */
1994 if (BGP_INPUT_PNT (peer
) != endp
)
1996 zlog_warn ("%s: BGP attribute %s, length mismatch",
1997 peer
->host
, LOOKUP (attr_str
, type
));
1998 bgp_notify_send (peer
,
1999 BGP_NOTIFY_UPDATE_ERR
,
2000 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2002 aspath_unintern (&as4_path
);
2003 return BGP_ATTR_PARSE_ERROR
;
2007 * At this place we can see whether we got AS4_PATH and/or
2008 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2009 * We can not do this before we've read all attributes because
2010 * the as4 handling does not say whether AS4_PATH has to be sent
2011 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2012 * in relationship to AGGREGATOR.
2013 * So, to be defensive, we are not relying on any order and read
2014 * all attributes first, including these 32bit ones, and now,
2015 * afterwards, we look what and if something is to be done for as4.
2017 /* actually... this doesn't ever return failure currently, but
2018 * better safe than sorry */
2019 if (bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
2020 as4_aggregator
, &as4_aggregator_addr
))
2022 bgp_notify_send (peer
,
2023 BGP_NOTIFY_UPDATE_ERR
,
2024 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2026 aspath_unintern (&as4_path
);
2027 return BGP_ATTR_PARSE_ERROR
;
2030 /* At this stage, we have done all fiddling with as4, and the
2031 * resulting info is in attr->aggregator resp. attr->aspath
2032 * so we can chuck as4_aggregator and as4_path alltogether in
2033 * order to save memory
2037 aspath_unintern (&as4_path
); /* unintern - it is in the hash */
2038 /* The flag that we got this is still there, but that does not
2043 * The "rest" of the code does nothing with as4_aggregator.
2044 * there is no memory attached specifically which is not part
2046 * so ignoring just means do nothing.
2049 * Finally do the checks on the aspath we did not do yet
2050 * because we waited for a potentially synthesized aspath.
2052 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2054 ret
= bgp_attr_aspath_check (peer
, attr
);
2055 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2059 /* Finally intern unknown attribute. */
2060 if (attr
->extra
&& attr
->extra
->transit
)
2061 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
2063 return BGP_ATTR_PARSE_PROCEED
;
2066 /* Well-known attribute check. */
2068 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
2072 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
2073 type
= BGP_ATTR_ORIGIN
;
2075 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
2076 type
= BGP_ATTR_AS_PATH
;
2078 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
)))
2079 type
= BGP_ATTR_NEXT_HOP
;
2081 if (peer
->sort
== BGP_PEER_IBGP
2082 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
2083 type
= BGP_ATTR_LOCAL_PREF
;
2087 zlog_warn ("%s Missing well-known attribute %d.", peer
->host
, type
);
2088 bgp_notify_send_with_data (peer
,
2089 BGP_NOTIFY_UPDATE_ERR
,
2090 BGP_NOTIFY_UPDATE_MISS_ATTR
,
2092 return BGP_ATTR_PARSE_ERROR
;
2094 return BGP_ATTR_PARSE_PROCEED
;
2097 int stream_put_prefix (struct stream
*, struct prefix
*);
2100 bgp_packet_mpattr_start (struct stream
*s
, afi_t afi
, safi_t safi
,
2105 /* Set extended bit always to encode the attribute length as 2 bytes */
2106 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2107 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2108 sizep
= stream_get_endp (s
);
2109 stream_putw (s
, 0); /* Marker: Attribute length. */
2110 stream_putw (s
, afi
); /* AFI */
2111 stream_putc (s
, safi
); /* SAFI */
2120 case SAFI_MULTICAST
:
2122 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2125 stream_putc (s
, 12);
2128 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2139 case SAFI_MULTICAST
:
2141 unsigned long sizep
;
2142 struct attr_extra
*attre
= attr
->extra
;
2144 assert (attr
->extra
);
2145 stream_putc (s
, attre
->mp_nexthop_len
);
2146 stream_put (s
, &attre
->mp_nexthop_global
, 16);
2147 if (attre
->mp_nexthop_len
== 32)
2148 stream_put (s
, &attre
->mp_nexthop_local
, 16);
2154 #endif /*HAVE_IPV6*/
2165 bgp_packet_mpattr_prefix (struct stream
*s
, afi_t afi
, safi_t safi
,
2166 struct prefix
*p
, struct prefix_rd
*prd
,
2172 /* Tag, RD, Prefix write. */
2173 stream_putc (s
, p
->prefixlen
+ 88);
2174 stream_put (s
, tag
, 3);
2175 stream_put (s
, prd
->val
, 8);
2176 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2180 stream_put_prefix (s
, p
);
2186 bgp_packet_mpattr_end (struct stream
*s
, size_t sizep
)
2188 /* Set MP attribute length. Don't count the (2) bytes used to encode
2190 stream_putw_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 2);
2193 /* Make attribute packet. */
2195 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
2196 struct stream
*s
, struct attr
*attr
,
2197 struct prefix
*p
, afi_t afi
, safi_t safi
,
2198 struct peer
*from
, struct prefix_rd
*prd
, u_char
*tag
)
2201 size_t aspath_sizep
;
2202 struct aspath
*aspath
;
2203 int send_as4_path
= 0;
2204 int send_as4_aggregator
= 0;
2205 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
2206 size_t mpattrlen_pos
= 0;
2209 bgp
= bgp_get_default ();
2211 /* Remember current pointer. */
2212 cp
= stream_get_endp (s
);
2214 if (p
&& !(afi
== AFI_IP
&& safi
== SAFI_UNICAST
))
2216 mpattrlen_pos
= bgp_packet_mpattr_start(s
, afi
, safi
, attr
);
2217 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, tag
);
2218 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
2221 /* Origin attribute. */
2222 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2223 stream_putc (s
, BGP_ATTR_ORIGIN
);
2225 stream_putc (s
, attr
->origin
);
2227 /* AS path attribute. */
2229 /* If remote-peer is EBGP */
2230 if (peer
->sort
== BGP_PEER_EBGP
2231 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
2232 || attr
->aspath
->segments
== NULL
)
2233 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
2235 aspath
= aspath_dup (attr
->aspath
);
2237 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
2239 /* Strip the confed info, and then stuff our path CONFED_ID
2241 aspath
= aspath_delete_confed_seq (aspath
);
2242 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
2246 if (peer
->change_local_as
) {
2247 /* If replace-as is specified, we only use the change_local_as when
2248 advertising routes. */
2249 if( ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_REPLACE_AS
) ) {
2250 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2252 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
2254 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
2258 else if (peer
->sort
== BGP_PEER_CONFED
)
2260 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2261 aspath
= aspath_dup (attr
->aspath
);
2262 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
2265 aspath
= attr
->aspath
;
2267 /* If peer is not AS4 capable, then:
2268 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2269 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2270 * types are in it (i.e. exclude them if they are there)
2271 * AND do this only if there is at least one asnum > 65535 in the path!
2272 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2273 * all ASnums > 65535 to BGP_AS_TRANS
2276 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2277 stream_putc (s
, BGP_ATTR_AS_PATH
);
2278 aspath_sizep
= stream_get_endp (s
);
2280 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
2282 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2285 if (!use32bit
&& aspath_has_as4 (aspath
))
2286 send_as4_path
= 1; /* we'll do this later, at the correct place */
2288 /* Nexthop attribute. */
2289 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
) && afi
== AFI_IP
)
2291 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2292 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2294 if (safi
== SAFI_MPLS_VPN
)
2296 if (attr
->nexthop
.s_addr
== 0)
2297 stream_put_ipv4 (s
, peer
->nexthop
.v4
.s_addr
);
2299 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2302 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2305 /* MED attribute. */
2306 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
) ||
2309 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2310 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
2312 stream_putl (s
, (bgp
->maxmed_active
? bgp
->maxmed_value
: attr
->med
));
2315 /* Local preference. */
2316 if (peer
->sort
== BGP_PEER_IBGP
||
2317 peer
->sort
== BGP_PEER_CONFED
)
2319 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2320 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
2322 stream_putl (s
, attr
->local_pref
);
2325 /* Atomic aggregate. */
2326 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
2328 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2329 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
2334 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
2336 assert (attr
->extra
);
2338 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
2339 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2340 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
2344 /* AS4 capable peer */
2346 stream_putl (s
, attr
->extra
->aggregator_as
);
2350 /* 2-byte AS peer */
2353 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2354 if ( attr
->extra
->aggregator_as
> 65535 )
2356 stream_putw (s
, BGP_AS_TRANS
);
2358 /* we have to send AS4_AGGREGATOR, too.
2359 * we'll do that later in order to send attributes in ascending
2362 send_as4_aggregator
= 1;
2365 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
2367 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
2370 /* Community attribute. */
2371 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
2372 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
2374 if (attr
->community
->size
* 4 > 255)
2376 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2377 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2378 stream_putw (s
, attr
->community
->size
* 4);
2382 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2383 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2384 stream_putc (s
, attr
->community
->size
* 4);
2386 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
2389 /* Route Reflector. */
2390 if (peer
->sort
== BGP_PEER_IBGP
2392 && from
->sort
== BGP_PEER_IBGP
)
2394 /* Originator ID. */
2395 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2396 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
2399 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
2400 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
2402 stream_put_in_addr (s
, &from
->remote_id
);
2405 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2406 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
2408 if (attr
->extra
&& attr
->extra
->cluster
)
2410 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
2411 /* If this peer configuration's parent BGP has cluster_id. */
2412 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
2413 stream_put_in_addr (s
, &bgp
->cluster_id
);
2415 stream_put_in_addr (s
, &bgp
->router_id
);
2416 stream_put (s
, attr
->extra
->cluster
->list
,
2417 attr
->extra
->cluster
->length
);
2422 /* If this peer configuration's parent BGP has cluster_id. */
2423 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
2424 stream_put_in_addr (s
, &bgp
->cluster_id
);
2426 stream_put_in_addr (s
, &bgp
->router_id
);
2430 /* Extended Communities attribute. */
2431 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
2432 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
2434 struct attr_extra
*attre
= attr
->extra
;
2438 if (peer
->sort
== BGP_PEER_IBGP
2439 || peer
->sort
== BGP_PEER_CONFED
)
2441 if (attre
->ecommunity
->size
* 8 > 255)
2443 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2444 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2445 stream_putw (s
, attre
->ecommunity
->size
* 8);
2449 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2450 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2451 stream_putc (s
, attre
->ecommunity
->size
* 8);
2453 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
2459 int ecom_tr_size
= 0;
2462 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
2464 pnt
= attre
->ecommunity
->val
+ (i
* 8);
2467 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
2475 if (ecom_tr_size
* 8 > 255)
2477 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2478 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2479 stream_putw (s
, ecom_tr_size
* 8);
2483 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2484 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2485 stream_putc (s
, ecom_tr_size
* 8);
2488 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
2490 pnt
= attre
->ecommunity
->val
+ (i
* 8);
2493 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
2496 stream_put (s
, pnt
, 8);
2502 if ( send_as4_path
)
2504 /* If the peer is NOT As4 capable, AND */
2505 /* there are ASnums > 65535 in path THEN
2506 * give out AS4_PATH */
2508 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2510 * Hm, I wonder... confederation things *should* only be at
2511 * the beginning of an aspath, right? Then we should use
2512 * aspath_delete_confed_seq for this, because it is already
2514 * Folks, talk to me: what is reasonable here!?
2516 aspath
= aspath_delete_confed_seq (aspath
);
2518 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2519 stream_putc (s
, BGP_ATTR_AS4_PATH
);
2520 aspath_sizep
= stream_get_endp (s
);
2522 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
2525 if (aspath
!= attr
->aspath
)
2526 aspath_free (aspath
);
2528 if ( send_as4_aggregator
)
2530 assert (attr
->extra
);
2532 /* send AS4_AGGREGATOR, at this place */
2533 /* this section of code moved here in order to ensure the correct
2534 * *ascending* order of attributes
2536 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2537 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
2539 stream_putl (s
, attr
->extra
->aggregator_as
);
2540 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
2543 /* Unknown transit attribute. */
2544 if (attr
->extra
&& attr
->extra
->transit
)
2545 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
2547 /* Return total size of attribute. */
2548 return stream_get_endp (s
) - cp
;
2552 bgp_packet_mpunreach_start (struct stream
*s
, afi_t afi
, safi_t safi
)
2554 unsigned long attrlen_pnt
;
2556 /* Set extended bit always to encode the attribute length as 2 bytes */
2557 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2558 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
2560 attrlen_pnt
= stream_get_endp (s
);
2561 stream_putw (s
, 0); /* Length of this attribute. */
2563 stream_putw (s
, afi
);
2564 safi
= (safi
== SAFI_MPLS_VPN
) ? SAFI_MPLS_LABELED_VPN
: safi
;
2565 stream_putc (s
, safi
);
2570 bgp_packet_mpunreach_prefix (struct stream
*s
, struct prefix
*p
,
2571 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
2574 if (safi
== SAFI_MPLS_VPN
)
2576 stream_putc (s
, p
->prefixlen
+ 88);
2577 stream_put (s
, tag
, 3);
2578 stream_put (s
, prd
->val
, 8);
2579 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2582 stream_put_prefix (s
, p
);
2586 bgp_packet_mpunreach_end (struct stream
*s
, size_t attrlen_pnt
)
2590 /* Set MP attribute length. Don't count the (2) bytes used to encode
2592 size
= stream_get_endp (s
) - attrlen_pnt
- 2;
2593 stream_putw_at (s
, attrlen_pnt
, size
);
2596 /* Initialization of attribute. */
2598 bgp_attr_init (void)
2609 bgp_attr_finish (void)
2613 community_finish ();
2614 ecommunity_finish ();
2619 /* Make attribute packet. */
2621 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
2622 struct prefix
*prefix
)
2627 struct aspath
*aspath
;
2629 /* Remember current pointer. */
2630 cp
= stream_get_endp (s
);
2632 /* Place holder of length. */
2635 /* Origin attribute. */
2636 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2637 stream_putc (s
, BGP_ATTR_ORIGIN
);
2639 stream_putc (s
, attr
->origin
);
2641 aspath
= attr
->aspath
;
2643 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2644 stream_putc (s
, BGP_ATTR_AS_PATH
);
2645 aspath_lenp
= stream_get_endp (s
);
2648 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
2650 /* Nexthop attribute. */
2651 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2654 && prefix
->family
!= AF_INET6
2655 #endif /* HAVE_IPV6 */
2658 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2659 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2661 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2664 /* MED attribute. */
2665 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
2667 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2668 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
2670 stream_putl (s
, attr
->med
);
2673 /* Local preference. */
2674 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
2676 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2677 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
2679 stream_putl (s
, attr
->local_pref
);
2682 /* Atomic aggregate. */
2683 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
2685 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2686 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
2691 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
2693 assert (attr
->extra
);
2694 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2695 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
2697 stream_putl (s
, attr
->extra
->aggregator_as
);
2698 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
2701 /* Community attribute. */
2702 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
2704 if (attr
->community
->size
* 4 > 255)
2706 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2707 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2708 stream_putw (s
, attr
->community
->size
* 4);
2712 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2713 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2714 stream_putc (s
, attr
->community
->size
* 4);
2716 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
2720 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
2721 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
2722 (attr
->extra
->mp_nexthop_len
== 16 || attr
->extra
->mp_nexthop_len
== 32) )
2725 struct attr_extra
*attre
= attr
->extra
;
2727 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
2728 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2729 sizep
= stream_get_endp (s
);
2732 stream_putc (s
, 0); /* Marker: Attribute length. */
2733 stream_putw(s
, AFI_IP6
); /* AFI */
2734 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
2737 stream_putc(s
, attre
->mp_nexthop_len
);
2738 stream_put(s
, &attre
->mp_nexthop_global
, 16);
2739 if (attre
->mp_nexthop_len
== 32)
2740 stream_put(s
, &attre
->mp_nexthop_local
, 16);
2746 stream_put_prefix(s
, prefix
);
2748 /* Set MP attribute length. */
2749 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
2751 #endif /* HAVE_IPV6 */
2753 /* Return total size of attribute. */
2754 len
= stream_get_endp (s
) - cp
- 2;
2755 stream_putw_at (s
, cp
, len
);