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
34 #include "bgpd/bgpd.h"
35 #include "bgpd/bgp_attr.h"
36 #include "bgpd/bgp_route.h"
37 #include "bgpd/bgp_aspath.h"
38 #include "bgpd/bgp_community.h"
39 #include "bgpd/bgp_debug.h"
40 #include "bgpd/bgp_packet.h"
41 #include "bgpd/bgp_ecommunity.h"
42 #include "bgpd/bgp_lcommunity.h"
44 #include "bgp_encap_types.h"
46 /* Attribute strings for logging. */
47 static const struct message attr_str [] =
49 { BGP_ATTR_ORIGIN, "ORIGIN" },
50 { BGP_ATTR_AS_PATH, "AS_PATH" },
51 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
52 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
53 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
54 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
55 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
56 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
57 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
58 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
59 { BGP_ATTR_DPA, "DPA" },
60 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
61 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
62 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
63 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
64 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
65 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
66 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
67 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
68 { BGP_ATTR_ENCAP, "ENCAP" },
80 { BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" }
82 static const int attr_str_max = array_size(attr_str);
84 static const struct message attr_flag_str[] =
86 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
87 { BGP_ATTR_FLAG_TRANS, "Transitive" },
88 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
89 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
90 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
93 static struct hash *cluster_hash;
96 cluster_hash_alloc (void *p)
98 struct cluster_list * val = (struct cluster_list *) p;
99 struct cluster_list *cluster;
101 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
102 cluster->length = val->length;
106 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
107 memcpy (cluster->list, val->list, val->length);
110 cluster->list = NULL;
117 /* Cluster list related functions. */
118 static struct cluster_list *
119 cluster_parse (struct in_addr * pnt, int length)
121 struct cluster_list tmp;
122 struct cluster_list *cluster;
127 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
133 cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
137 for (i = 0; i < cluster->length / 4; i++)
138 if (cluster->list[i].s_addr == originator.s_addr)
144 cluster_hash_key_make (void *p)
146 const struct cluster_list *cluster = p;
148 return jhash(cluster->list, cluster->length, 0);
152 cluster_hash_cmp (const void *p1, const void *p2)
154 const struct cluster_list * cluster1 = p1;
155 const struct cluster_list * cluster2 = p2;
157 return (cluster1->length == cluster2->length &&
158 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
162 cluster_free (struct cluster_list *cluster)
165 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
166 XFREE (MTYPE_CLUSTER, cluster);
170 static struct cluster_list *
171 cluster_dup (struct cluster_list *cluster)
173 struct cluster_list *new;
175 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
176 new->length = cluster->length;
180 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
181 memcpy (new->list, cluster->list, cluster->length);
190 static struct cluster_list *
191 cluster_intern (struct cluster_list *cluster)
193 struct cluster_list *find;
195 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
202 cluster_unintern (struct cluster_list *cluster)
207 if (cluster->refcnt == 0)
209 hash_release (cluster_hash, cluster);
210 cluster_free (cluster);
217 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
221 cluster_finish (void)
223 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
224 hash_free (cluster_hash);
228 struct bgp_attr_encap_subtlv *
229 encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
231 struct bgp_attr_encap_subtlv *new;
232 struct bgp_attr_encap_subtlv *tail;
233 struct bgp_attr_encap_subtlv *p;
235 for (p = orig, tail = new = NULL; p; p = p->next) {
236 int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length;
238 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
241 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
244 memcpy(tail, p, size);
252 encap_free(struct bgp_attr_encap_subtlv *p)
254 struct bgp_attr_encap_subtlv *next;
258 XFREE(MTYPE_ENCAP_TLV, p);
264 bgp_attr_flush_encap(struct attr *attr)
266 if (!attr || !attr->extra)
269 if (attr->extra->encap_subtlvs) {
270 encap_free(attr->extra->encap_subtlvs);
271 attr->extra->encap_subtlvs = NULL;
276 * Compare encap sub-tlv chains
281 * This algorithm could be made faster if needed
284 encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
286 struct bgp_attr_encap_subtlv *p;
287 struct bgp_attr_encap_subtlv *q;
298 for (p = h1; p; p = p->next) {
299 for (q = h2; q; q = q->next) {
300 if ((p->type == q->type) &&
301 (p->length == q->length) &&
302 !memcmp(p->value, q->value, p->length)) {
311 for (p = h2; p; p = p->next) {
312 for (q = h1; q; q = q->next) {
313 if ((p->type == q->type) &&
314 (p->length == q->length) &&
315 !memcmp(p->value, q->value, p->length)) {
327 /* Unknown transit attribute. */
328 static struct hash *transit_hash;
331 transit_free (struct transit *transit)
334 XFREE (MTYPE_TRANSIT_VAL, transit->val);
335 XFREE (MTYPE_TRANSIT, transit);
340 transit_hash_alloc (void *p)
342 /* Transit structure is already allocated. */
346 static struct transit *
347 transit_intern (struct transit *transit)
349 struct transit *find;
351 find = hash_get (transit_hash, transit, transit_hash_alloc);
353 transit_free (transit);
360 transit_unintern (struct transit *transit)
365 if (transit->refcnt == 0)
367 hash_release (transit_hash, transit);
368 transit_free (transit);
373 transit_hash_key_make (void *p)
375 const struct transit * transit = p;
377 return jhash(transit->val, transit->length, 0);
381 transit_hash_cmp (const void *p1, const void *p2)
383 const struct transit * transit1 = p1;
384 const struct transit * transit2 = p2;
386 return (transit1->length == transit2->length &&
387 memcmp (transit1->val, transit2->val, transit1->length) == 0);
393 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
397 transit_finish (void)
399 hash_clean (transit_hash, (void (*)(void *))transit_free);
400 hash_free (transit_hash);
404 /* Attribute hash routines. */
405 static struct hash *attrhash;
407 static struct attr_extra *
408 bgp_attr_extra_new (void)
410 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
414 bgp_attr_extra_free (struct attr *attr)
418 if (attr->extra->encap_subtlvs) {
419 encap_free(attr->extra->encap_subtlvs);
420 attr->extra->encap_subtlvs = NULL;
422 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
428 bgp_attr_extra_get (struct attr *attr)
431 attr->extra = bgp_attr_extra_new();
435 /* Shallow copy of an attribute
436 * Though, not so shallow that it doesn't copy the contents
437 * of the attr_extra pointed to by 'extra'
440 bgp_attr_dup (struct attr *new, struct attr *orig)
442 struct attr_extra *extra = new->extra;
445 /* if caller provided attr_extra space, use it in any case.
447 * This is neccesary even if orig->extra equals NULL, because otherwise
448 * memory may be later allocated on the heap by bgp_attr_extra_get.
450 * That memory would eventually be leaked, because the caller must not
451 * call bgp_attr_extra_free if he provided attr_extra on the stack.
456 memset(new->extra, 0, sizeof(struct attr_extra));
458 *new->extra = *orig->extra;
459 if (orig->extra->encap_subtlvs) {
460 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
464 else if (orig->extra)
466 new->extra = bgp_attr_extra_new();
467 *new->extra = *orig->extra;
468 if (orig->extra->encap_subtlvs) {
469 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
477 return attrhash->count;
481 attr_unknown_count (void)
483 return transit_hash->count;
487 attrhash_key_make (void *p)
489 const struct attr *attr = (struct attr *) p;
490 const struct attr_extra *extra = attr->extra;
492 #define MIX(val) key = jhash_1word(val, key)
495 MIX(attr->nexthop.s_addr);
497 MIX(attr->local_pref);
500 key += attr->nexthop.s_addr;
502 key += attr->local_pref;
506 MIX(extra->aggregator_as);
507 MIX(extra->aggregator_addr.s_addr);
509 MIX(extra->mp_nexthop_global_in.s_addr);
510 MIX(extra->originator_id.s_addr);
515 MIX(aspath_key_make (attr->aspath));
517 MIX(community_hash_make (attr->community));
521 if (extra->lcommunity)
522 MIX(lcommunity_hash_make (extra->lcommunity));
523 if (extra->ecommunity)
524 MIX(ecommunity_hash_make (extra->ecommunity));
526 MIX(cluster_hash_key_make (extra->cluster));
528 MIX(transit_hash_key_make (extra->transit));
530 MIX(extra->mp_nexthop_len);
531 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
532 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
539 attrhash_cmp (const void *p1, const void *p2)
541 const struct attr * attr1 = p1;
542 const struct attr * attr2 = p2;
544 if (attr1->flag == attr2->flag
545 && attr1->origin == attr2->origin
546 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
547 && attr1->aspath == attr2->aspath
548 && attr1->community == attr2->community
549 && attr1->med == attr2->med
550 && attr1->local_pref == attr2->local_pref)
552 const struct attr_extra *ae1 = attr1->extra;
553 const struct attr_extra *ae2 = attr2->extra;
556 && ae1->aggregator_as == ae2->aggregator_as
557 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
558 && ae1->weight == ae2->weight
559 && ae1->tag == ae2->tag
560 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
561 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
562 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
563 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
564 && ae1->ecommunity == ae2->ecommunity
565 && ae1->lcommunity == ae2->lcommunity
566 && ae1->cluster == ae2->cluster
567 && ae1->transit == ae2->transit
568 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
569 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
570 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
574 /* neither attribute has extra attributes, so they're same */
584 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
588 * special for hash_clean below
591 attr_vfree (void *attr)
593 bgp_attr_extra_free ((struct attr *)attr);
594 XFREE (MTYPE_ATTR, attr);
598 attrhash_finish (void)
600 hash_clean(attrhash, attr_vfree);
601 hash_free (attrhash);
606 attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
608 struct attr *attr = backet->data;
610 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
611 inet_ntoa (attr->nexthop), VTY_NEWLINE);
615 attr_show_all (struct vty *vty)
617 hash_iterate (attrhash,
618 (void (*)(struct hash_backet *, void *))
619 attr_show_all_iterator,
624 bgp_attr_hash_alloc (void *p)
626 struct attr * val = (struct attr *) p;
629 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
633 attr->extra = bgp_attr_extra_new ();
634 *attr->extra = *val->extra;
636 if (attr->extra->encap_subtlvs) {
637 attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
644 /* Internet argument attribute. */
646 bgp_attr_intern (struct attr *attr)
650 /* Intern referenced strucutre. */
653 if (! attr->aspath->refcnt)
654 attr->aspath = aspath_intern (attr->aspath);
656 attr->aspath->refcnt++;
660 if (! attr->community->refcnt)
661 attr->community = community_intern (attr->community);
663 attr->community->refcnt++;
667 struct attr_extra *attre = attr->extra;
669 if (attre->ecommunity)
671 if (! attre->ecommunity->refcnt)
672 attre->ecommunity = ecommunity_intern (attre->ecommunity);
674 attre->ecommunity->refcnt++;
677 if (attre->lcommunity)
679 if (! attre->lcommunity->refcnt)
680 attre->lcommunity = lcommunity_intern (attre->lcommunity);
682 attre->lcommunity->refcnt++;
686 if (! attre->cluster->refcnt)
687 attre->cluster = cluster_intern (attre->cluster);
689 attre->cluster->refcnt++;
693 if (! attre->transit->refcnt)
694 attre->transit = transit_intern (attre->transit);
696 attre->transit->refcnt++;
700 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
707 /* Make network statement's attribute. */
709 bgp_attr_default_set (struct attr *attr, u_char origin)
711 memset (attr, 0, sizeof (struct attr));
712 bgp_attr_extra_get (attr);
714 attr->origin = origin;
715 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
716 attr->aspath = aspath_empty ();
717 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
718 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
719 attr->extra->tag = 0;
720 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
721 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
727 /* Make network statement's attribute. */
729 bgp_attr_default_intern (u_char origin)
734 memset (&attr, 0, sizeof (struct attr));
735 bgp_attr_extra_get (&attr);
737 bgp_attr_default_set(&attr, origin);
739 new = bgp_attr_intern (&attr);
740 bgp_attr_extra_free (&attr);
742 aspath_unintern (&new->aspath);
746 /* Create the attributes for an aggregate */
748 bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
749 struct aspath *aspath,
750 struct community *community, int as_set,
751 u_char atomic_aggregate)
755 struct attr_extra attre;
757 memset (&attr, 0, sizeof (struct attr));
758 memset (&attre, 0, sizeof (struct attr_extra));
761 /* Origin attribute. */
762 attr.origin = origin;
763 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
765 /* AS path attribute. */
767 attr.aspath = aspath_intern (aspath);
769 attr.aspath = aspath_empty ();
770 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
772 /* Next hop attribute. */
773 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
777 attr.community = community;
778 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
781 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
782 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
784 if (! as_set || atomic_aggregate)
785 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
786 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
787 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
788 attre.aggregator_as = bgp->confed_id;
790 attre.aggregator_as = bgp->as;
791 attre.aggregator_addr = bgp->router_id;
793 new = bgp_attr_intern (&attr);
795 aspath_unintern (&new->aspath);
799 /* Unintern just the sub-components of the attr, but not the attr */
801 bgp_attr_unintern_sub (struct attr *attr)
803 /* aspath refcount shoud be decrement. */
805 aspath_unintern (&attr->aspath);
806 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
809 community_unintern (&attr->community);
810 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
814 if (attr->extra->ecommunity)
815 ecommunity_unintern (&attr->extra->ecommunity);
816 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
818 if (attr->extra->lcommunity)
819 lcommunity_unintern (&attr->extra->lcommunity);
820 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
822 if (attr->extra->cluster)
823 cluster_unintern (attr->extra->cluster);
824 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
826 if (attr->extra->transit)
827 transit_unintern (attr->extra->transit);
831 /* Free bgp attribute and aspath. */
833 bgp_attr_unintern (struct attr **pattr)
835 struct attr *attr = *pattr;
838 struct attr_extra tmp_extra;
840 /* Decrement attribute reference. */
847 tmp.extra = &tmp_extra;
848 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
851 /* If reference becomes zero then free attribute object. */
852 if (attr->refcnt == 0)
854 ret = hash_release (attrhash, attr);
855 assert (ret != NULL);
856 bgp_attr_extra_free (attr);
857 XFREE (MTYPE_ATTR, attr);
861 bgp_attr_unintern_sub (&tmp);
865 bgp_attr_flush (struct attr *attr)
867 if (attr->aspath && ! attr->aspath->refcnt)
869 aspath_free (attr->aspath);
872 if (attr->community && ! attr->community->refcnt)
874 community_free (attr->community);
875 attr->community = NULL;
879 struct attr_extra *attre = attr->extra;
881 if (attre->ecommunity && ! attre->ecommunity->refcnt)
882 ecommunity_free (&attre->ecommunity);
883 if (attre->lcommunity && ! attre->lcommunity->refcnt)
884 lcommunity_free (&attre->lcommunity);
885 if (attre->cluster && ! attre->cluster->refcnt)
887 cluster_free (attre->cluster);
888 attre->cluster = NULL;
890 if (attre->transit && ! attre->transit->refcnt)
892 transit_free (attre->transit);
893 attre->transit = NULL;
895 encap_free(attre->encap_subtlvs);
896 attre->encap_subtlvs = NULL;
900 /* Implement draft-scudder-idr-optional-transitive behaviour and
901 * avoid resetting sessions for malformed attributes which are
902 * are partial/optional and hence where the error likely was not
903 * introduced by the sending neighbour.
905 static bgp_attr_parse_ret_t
906 bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
909 struct peer *const peer = args->peer;
910 const u_int8_t flags = args->flags;
911 /* startp and length must be special-cased, as whether or not to
912 * send the attribute data with the NOTIFY depends on the error,
913 * the caller therefore signals this with the seperate length argument
915 u_char *notify_datap = (length > 0 ? args->startp : NULL);
917 /* Only relax error handling for eBGP peers */
918 if (peer->sort != BGP_PEER_EBGP)
920 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
921 notify_datap, length);
922 return BGP_ATTR_PARSE_ERROR;
926 /* Adjust the stream getp to the end of the attribute, in case we can
927 * still proceed but the caller hasn't read all the attribute.
929 stream_set_getp (BGP_INPUT (peer),
930 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
933 switch (args->type) {
934 /* where an attribute is relatively inconsequential, e.g. it does not
935 * affect route selection, and can be safely ignored, then any such
936 * attributes which are malformed should just be ignored and the route
937 * processed as normal.
939 case BGP_ATTR_AS4_AGGREGATOR:
940 case BGP_ATTR_AGGREGATOR:
941 case BGP_ATTR_ATOMIC_AGGREGATE:
942 return BGP_ATTR_PARSE_PROCEED;
944 /* Core attributes, particularly ones which may influence route
945 * selection, should always cause session resets
947 case BGP_ATTR_ORIGIN:
948 case BGP_ATTR_AS_PATH:
949 case BGP_ATTR_NEXT_HOP:
950 case BGP_ATTR_MULTI_EXIT_DISC:
951 case BGP_ATTR_LOCAL_PREF:
952 case BGP_ATTR_COMMUNITIES:
953 case BGP_ATTR_ORIGINATOR_ID:
954 case BGP_ATTR_CLUSTER_LIST:
955 case BGP_ATTR_MP_REACH_NLRI:
956 case BGP_ATTR_MP_UNREACH_NLRI:
957 case BGP_ATTR_EXT_COMMUNITIES:
958 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
959 notify_datap, length);
960 return BGP_ATTR_PARSE_ERROR;
963 /* Partial optional attributes that are malformed should not cause
964 * the whole session to be reset. Instead treat it as a withdrawal
965 * of the routes, if possible.
967 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
968 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
969 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
970 return BGP_ATTR_PARSE_WITHDRAW;
972 /* default to reset */
973 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
976 /* Find out what is wrong with the path attribute flag bits and log the error.
977 "Flag bits" here stand for Optional, Transitive and Partial, but not for
978 Extended Length. Checking O/T/P bits at once implies, that the attribute
979 being diagnosed is defined by RFC as either a "well-known" or an "optional,
980 non-transitive" attribute. */
982 bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
983 u_int8_t desired_flags /* how RFC says it must be */
987 u_char real_flags = args->flags;
988 const u_int8_t attr_code = args->type;
990 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
991 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
992 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
995 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
996 CHECK_FLAG (real_flags, attr_flag_str[i].key)
999 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
1000 LOOKUP (attr_str, attr_code),
1001 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
1002 attr_flag_str[i].str);
1007 zlog (args->peer->log, LOG_DEBUG,
1008 "Strange, %s called for attr %s, but no problem found with flags"
1009 " (real flags 0x%x, desired 0x%x)",
1010 __func__, LOOKUP (attr_str, attr_code),
1011 real_flags, desired_flags);
1015 /* Required flags for attributes. EXTLEN will be masked off when testing,
1016 * as will PARTIAL for optional+transitive attributes.
1018 const u_int8_t attr_flags_values [] = {
1019 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
1020 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
1021 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
1022 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
1023 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
1024 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
1025 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1026 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1027 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
1028 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1029 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1030 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1031 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1032 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1033 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1034 [BGP_ATTR_LARGE_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
1036 static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
1039 bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
1041 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
1042 const u_int8_t flags = args->flags;
1043 const u_int8_t attr_code = args->type;
1044 struct peer *const peer = args->peer;
1046 /* there may be attributes we don't know about */
1047 if (attr_code > attr_flags_values_max)
1049 if (attr_flags_values[attr_code] == 0)
1052 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1055 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1056 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1058 zlog (peer->log, LOG_ERR,
1059 "%s well-known attributes must have transitive flag set (%x)",
1060 LOOKUP (attr_str, attr_code), flags);
1064 /* "For well-known attributes and for optional non-transitive attributes,
1065 * the Partial bit MUST be set to 0."
1067 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1069 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1071 zlog (peer->log, LOG_ERR,
1072 "%s well-known attribute "
1073 "must NOT have the partial flag set (%x)",
1074 LOOKUP (attr_str, attr_code), flags);
1077 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1078 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1080 zlog (peer->log, LOG_ERR,
1081 "%s optional + transitive attribute "
1082 "must NOT have the partial flag set (%x)",
1083 LOOKUP (attr_str, attr_code), flags);
1088 /* Optional transitive attributes may go through speakers that don't
1089 * reocgnise them and set the Partial bit.
1091 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1092 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1093 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1096 == attr_flags_values[attr_code])
1099 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
1103 /* Get origin attribute of the update message. */
1104 static bgp_attr_parse_ret_t
1105 bgp_attr_origin (struct bgp_attr_parser_args *args)
1107 struct peer *const peer = args->peer;
1108 struct attr *const attr = args->attr;
1109 const bgp_size_t length = args->length;
1111 /* If any recognized attribute has Attribute Length that conflicts
1112 with the expected length (based on the attribute type code), then
1113 the Error Subcode is set to Attribute Length Error. The Data
1114 field contains the erroneous attribute (type, length and
1118 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1120 return bgp_attr_malformed (args,
1121 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1125 /* Fetch origin attribute. */
1126 attr->origin = stream_getc (BGP_INPUT (peer));
1128 /* If the ORIGIN attribute has an undefined value, then the Error
1129 Subcode is set to Invalid Origin Attribute. The Data field
1130 contains the unrecognized attribute (type, length and value). */
1131 if ((attr->origin != BGP_ORIGIN_IGP)
1132 && (attr->origin != BGP_ORIGIN_EGP)
1133 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1135 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1137 return bgp_attr_malformed (args,
1138 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1142 /* Set oring attribute flag. */
1143 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1148 /* Parse AS path information. This function is wrapper of
1151 bgp_attr_aspath (struct bgp_attr_parser_args *args)
1153 struct attr *const attr = args->attr;
1154 struct peer *const peer = args->peer;
1155 const bgp_size_t length = args->length;
1158 * peer with AS4 => will get 4Byte ASnums
1159 * otherwise, will get 16 Bit
1161 attr->aspath = aspath_parse (peer->ibuf, length,
1162 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1164 /* In case of IBGP, length will be zero. */
1167 zlog (peer->log, LOG_ERR,
1168 "Malformed AS path from %s, length is %d",
1169 peer->host, length);
1170 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
1173 /* Set aspath attribute flag. */
1174 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
1176 return BGP_ATTR_PARSE_PROCEED;
1179 static bgp_attr_parse_ret_t
1180 bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
1182 /* These checks were part of bgp_attr_aspath, but with
1183 * as4 we should to check aspath things when
1184 * aspath synthesizing with as4_path has already taken place.
1185 * Otherwise we check ASPATH and use the synthesized thing, and that is
1187 * So do the checks later, i.e. here
1189 struct bgp *bgp = peer->bgp;
1190 struct aspath *aspath;
1192 /* Confederation sanity check. */
1193 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1194 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
1196 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
1197 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1198 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1199 return BGP_ATTR_PARSE_ERROR;
1202 /* First AS check for EBGP. */
1203 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1205 if (peer->sort == BGP_PEER_EBGP
1206 && ! aspath_firstas_check (attr->aspath, peer->as))
1208 zlog (peer->log, LOG_ERR,
1209 "%s incorrect first AS (must be %u)", peer->host, peer->as);
1210 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1211 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1212 return BGP_ATTR_PARSE_ERROR;
1216 /* local-as prepend */
1217 if (peer->change_local_as &&
1218 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1220 aspath = aspath_dup (attr->aspath);
1221 aspath = aspath_add_seq (aspath, peer->change_local_as);
1222 aspath_unintern (&attr->aspath);
1223 attr->aspath = aspath_intern (aspath);
1226 return BGP_ATTR_PARSE_PROCEED;
1229 /* Parse AS4 path information. This function is another wrapper of
1232 bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
1234 struct peer *const peer = args->peer;
1235 struct attr *const attr = args->attr;
1236 const bgp_size_t length = args->length;
1238 *as4_path = aspath_parse (peer->ibuf, length, 1);
1240 /* In case of IBGP, length will be zero. */
1243 zlog (peer->log, LOG_ERR,
1244 "Malformed AS4 path from %s, length is %d",
1245 peer->host, length);
1246 return bgp_attr_malformed (args,
1247 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1251 /* Set aspath attribute flag. */
1253 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1255 return BGP_ATTR_PARSE_PROCEED;
1258 /* Nexthop attribute. */
1259 static bgp_attr_parse_ret_t
1260 bgp_attr_nexthop (struct bgp_attr_parser_args *args)
1262 struct peer *const peer = args->peer;
1263 struct attr *const attr = args->attr;
1264 const bgp_size_t length = args->length;
1266 in_addr_t nexthop_h, nexthop_n;
1268 /* Check nexthop attribute length. */
1271 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1274 return bgp_attr_malformed (args,
1275 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1279 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1280 attribute must result in a NOTIFICATION message (this is implemented below).
1281 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1282 logged locally (this is implemented somewhere else). The UPDATE message
1283 gets ignored in any of these cases. */
1284 nexthop_n = stream_get_ipv4 (peer->ibuf);
1285 nexthop_h = ntohl (nexthop_n);
1286 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1287 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
1289 char buf[INET_ADDRSTRLEN];
1290 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
1291 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
1292 return bgp_attr_malformed (args,
1293 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
1297 attr->nexthop.s_addr = nexthop_n;
1298 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1300 return BGP_ATTR_PARSE_PROCEED;
1303 /* MED atrribute. */
1304 static bgp_attr_parse_ret_t
1305 bgp_attr_med (struct bgp_attr_parser_args *args)
1307 struct peer *const peer = args->peer;
1308 struct attr *const attr = args->attr;
1309 const bgp_size_t length = args->length;
1314 zlog (peer->log, LOG_ERR,
1315 "MED attribute length isn't four [%d]", length);
1317 return bgp_attr_malformed (args,
1318 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1322 attr->med = stream_getl (peer->ibuf);
1324 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1326 return BGP_ATTR_PARSE_PROCEED;
1329 /* Local preference attribute. */
1330 static bgp_attr_parse_ret_t
1331 bgp_attr_local_pref (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;
1340 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1342 return bgp_attr_malformed (args,
1343 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1347 /* If it is contained in an UPDATE message that is received from an
1348 external peer, then this attribute MUST be ignored by the
1349 receiving speaker. */
1350 if (peer->sort == BGP_PEER_EBGP)
1352 stream_forward_getp (peer->ibuf, length);
1353 return BGP_ATTR_PARSE_PROCEED;
1356 attr->local_pref = stream_getl (peer->ibuf);
1358 /* Set atomic aggregate flag. */
1359 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1361 return BGP_ATTR_PARSE_PROCEED;
1364 /* Atomic aggregate. */
1366 bgp_attr_atomic (struct bgp_attr_parser_args *args)
1368 struct peer *const peer = args->peer;
1369 struct attr *const attr = args->attr;
1370 const bgp_size_t length = args->length;
1375 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1377 return bgp_attr_malformed (args,
1378 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1382 /* Set atomic aggregate flag. */
1383 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1385 return BGP_ATTR_PARSE_PROCEED;
1388 /* Aggregator attribute */
1390 bgp_attr_aggregator (struct bgp_attr_parser_args *args)
1392 struct peer *const peer = args->peer;
1393 struct attr *const attr = args->attr;
1394 const bgp_size_t length = args->length;
1397 struct attr_extra *attre = bgp_attr_extra_get (attr);
1399 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1400 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1403 if (length != wantedlen)
1405 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1407 return bgp_attr_malformed (args,
1408 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1412 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1413 attre->aggregator_as = stream_getl (peer->ibuf);
1415 attre->aggregator_as = stream_getw (peer->ibuf);
1416 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
1418 /* Set atomic aggregate flag. */
1419 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1421 return BGP_ATTR_PARSE_PROCEED;
1424 /* New Aggregator attribute */
1425 static bgp_attr_parse_ret_t
1426 bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1427 as_t *as4_aggregator_as,
1428 struct in_addr *as4_aggregator_addr)
1430 struct peer *const peer = args->peer;
1431 struct attr *const attr = args->attr;
1432 const bgp_size_t length = args->length;
1436 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1438 return bgp_attr_malformed (args,
1439 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1443 *as4_aggregator_as = stream_getl (peer->ibuf);
1444 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1446 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1448 return BGP_ATTR_PARSE_PROCEED;
1451 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1453 static bgp_attr_parse_ret_t
1454 bgp_attr_munge_as4_attrs (struct peer *const peer,
1455 struct attr *const attr,
1456 struct aspath *as4_path, as_t as4_aggregator,
1457 struct in_addr *as4_aggregator_addr)
1459 int ignore_as4_path = 0;
1460 struct aspath *newpath;
1461 struct attr_extra *attre = attr->extra;
1465 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1466 * checked that all well-known, mandatory attributes were present.
1468 * Can only be a problem with peer itself - hard error
1470 return BGP_ATTR_PARSE_ERROR;
1473 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1475 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1477 * It is worth a warning though, because the peer really
1478 * should not send them
1480 if (BGP_DEBUG(as4, AS4))
1482 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1483 zlog_debug ("[AS4] %s %s AS4_PATH",
1484 peer->host, "AS4 capable peer, yet it sent");
1486 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1487 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1488 peer->host, "AS4 capable peer, yet it sent");
1491 return BGP_ATTR_PARSE_PROCEED;
1494 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1495 * because that may override AS4_PATH
1497 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1499 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
1504 * if the as_number in aggregator is not AS_TRANS,
1505 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1506 * and the Aggregator shall be taken as
1507 * info on the aggregating node, and the AS_PATH
1508 * shall be taken as the AS_PATH
1510 * the Aggregator shall be ignored and the
1511 * AS4_AGGREGATOR shall be taken as the
1512 * Aggregating node and the AS_PATH is to be
1513 * constructed "as in all other cases"
1515 if (attre->aggregator_as != BGP_AS_TRANS)
1518 if ( BGP_DEBUG(as4, AS4))
1519 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1520 " send AGGREGATOR != AS_TRANS and"
1521 " AS4_AGGREGATOR, so ignore"
1522 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1523 ignore_as4_path = 1;
1527 /* "New_aggregator shall be taken as aggregator" */
1528 attre->aggregator_as = as4_aggregator;
1529 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1534 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1535 * That is bogus - but reading the conditions
1536 * we have to handle AS4_AGGREGATOR as if it were
1537 * AGGREGATOR in that case
1539 if ( BGP_DEBUG(as4, AS4))
1540 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1541 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1542 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
1543 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
1544 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1545 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1549 /* need to reconcile NEW_AS_PATH and AS_PATH */
1550 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
1552 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1553 aspath_unintern (&attr->aspath);
1554 attr->aspath = aspath_intern (newpath);
1556 return BGP_ATTR_PARSE_PROCEED;
1559 /* Community attribute. */
1560 static bgp_attr_parse_ret_t
1561 bgp_attr_community (struct bgp_attr_parser_args *args)
1563 struct peer *const peer = args->peer;
1564 struct attr *const attr = args->attr;
1565 const bgp_size_t length = args->length;
1569 attr->community = NULL;
1570 return BGP_ATTR_PARSE_PROCEED;
1574 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1576 /* XXX: fix community_parse to use stream API and remove this */
1577 stream_forward_getp (peer->ibuf, length);
1579 if (!attr->community)
1580 return bgp_attr_malformed (args,
1581 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1584 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1586 return BGP_ATTR_PARSE_PROCEED;
1589 /* Originator ID attribute. */
1590 static bgp_attr_parse_ret_t
1591 bgp_attr_originator_id (struct bgp_attr_parser_args *args)
1593 struct peer *const peer = args->peer;
1594 struct attr *const attr = args->attr;
1595 const bgp_size_t length = args->length;
1600 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1602 return bgp_attr_malformed (args,
1603 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1607 (bgp_attr_extra_get (attr))->originator_id.s_addr
1608 = stream_get_ipv4 (peer->ibuf);
1610 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1612 return BGP_ATTR_PARSE_PROCEED;
1615 /* Cluster list attribute. */
1616 static bgp_attr_parse_ret_t
1617 bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
1619 struct peer *const peer = args->peer;
1620 struct attr *const attr = args->attr;
1621 const bgp_size_t length = args->length;
1626 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1628 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1632 (bgp_attr_extra_get (attr))->cluster
1633 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
1635 /* XXX: Fix cluster_parse to use stream API and then remove this */
1636 stream_forward_getp (peer->ibuf, length);
1638 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1640 return BGP_ATTR_PARSE_PROCEED;
1643 /* Multiprotocol reachability information parse. */
1645 bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1646 struct bgp_nlri *mp_update)
1650 bgp_size_t nlri_len;
1653 struct peer *const peer = args->peer;
1654 struct attr *const attr = args->attr;
1655 const bgp_size_t length = args->length;
1656 struct attr_extra *attre = bgp_attr_extra_get(attr);
1658 /* Set end of packet. */
1659 s = BGP_INPUT(peer);
1660 start = stream_get_getp(s);
1662 /* safe to read statically sized header? */
1663 #define BGP_MP_REACH_MIN_SIZE 5
1664 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1665 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
1667 zlog_info ("%s: %s sent invalid length, %lu",
1668 __func__, peer->host, (unsigned long)length);
1669 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1672 /* Load AFI, SAFI. */
1673 afi = stream_getw (s);
1674 safi = stream_getc (s);
1676 /* Get nexthop length. */
1677 attre->mp_nexthop_len = stream_getc (s);
1679 if (LEN_LEFT < attre->mp_nexthop_len)
1681 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1682 __func__, peer->host, attre->mp_nexthop_len);
1683 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1686 /* Nexthop length check. */
1687 switch (attre->mp_nexthop_len)
1690 stream_get (&attre->mp_nexthop_global_in, s, 4);
1691 /* Probably needed for RFC 2283 */
1692 if (attr->nexthop.s_addr == 0)
1693 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
1696 stream_getl (s); /* RD high */
1697 stream_getl (s); /* RD low */
1698 stream_get (&attre->mp_nexthop_global_in, s, 4);
1702 u_int32_t rd_high __attribute__((unused));
1703 u_int32_t rd_low __attribute__((unused));
1705 rd_high = stream_getl (s);
1706 rd_low = stream_getl (s);
1710 stream_get (&attre->mp_nexthop_global, s, 16);
1714 if (attre->mp_nexthop_len == 48) {
1715 u_int32_t rd_high __attribute__((unused));
1716 u_int32_t rd_low __attribute__((unused));
1718 rd_high = stream_getl (s);
1719 rd_low = stream_getl (s);
1721 stream_get (&attre->mp_nexthop_global, s, 16);
1723 if (attre->mp_nexthop_len == 48) {
1724 u_int32_t rd_high __attribute__((unused));
1725 u_int32_t rd_low __attribute__((unused));
1727 rd_high = stream_getl (s);
1728 rd_low = stream_getl (s);
1730 stream_get (&attre->mp_nexthop_local, s, 16);
1731 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
1733 char buf1[INET6_ADDRSTRLEN];
1734 char buf2[INET6_ADDRSTRLEN];
1736 if (BGP_DEBUG (update, UPDATE_IN))
1737 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
1738 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
1739 buf1, INET6_ADDRSTRLEN),
1740 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
1741 buf2, INET6_ADDRSTRLEN));
1743 attre->mp_nexthop_len = 16;
1747 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1748 __func__, peer->host, attre->mp_nexthop_len);
1749 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1754 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1755 __func__, peer->host);
1756 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1761 if ((val = stream_getc (s)))
1762 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1766 /* must have nrli_len, what is left of the attribute */
1767 nlri_len = LEN_LEFT;
1768 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
1770 zlog_info ("%s: (%s) Failed to read NLRI",
1771 __func__, peer->host);
1772 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1775 mp_update->afi = afi;
1776 mp_update->safi = safi;
1777 mp_update->nlri = stream_pnt (s);
1778 mp_update->length = nlri_len;
1780 stream_forward_getp (s, nlri_len);
1782 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1784 return BGP_ATTR_PARSE_PROCEED;
1788 /* Multiprotocol unreachable parse */
1790 bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
1791 struct bgp_nlri *mp_withdraw)
1796 u_int16_t withdraw_len;
1797 struct peer *const peer = args->peer;
1798 struct attr *const attr = args->attr;
1799 const bgp_size_t length = args->length;
1803 #define BGP_MP_UNREACH_MIN_SIZE 3
1804 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
1805 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1807 afi = stream_getw (s);
1808 safi = stream_getc (s);
1810 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
1812 mp_withdraw->afi = afi;
1813 mp_withdraw->safi = safi;
1814 mp_withdraw->nlri = stream_pnt (s);
1815 mp_withdraw->length = withdraw_len;
1817 stream_forward_getp (s, withdraw_len);
1819 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1821 return BGP_ATTR_PARSE_PROCEED;
1824 /* Large Community attribute. */
1825 static bgp_attr_parse_ret_t
1826 bgp_attr_large_community (struct bgp_attr_parser_args *args)
1828 struct peer *const peer = args->peer;
1829 struct attr *const attr = args->attr;
1830 const bgp_size_t length = args->length;
1835 attr->extra->lcommunity = NULL;
1836 /* Empty extcomm doesn't seem to be invalid per se */
1837 return BGP_ATTR_PARSE_PROCEED;
1840 (bgp_attr_extra_get (attr))->lcommunity =
1841 lcommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1842 /* XXX: fix ecommunity_parse to use stream API */
1843 stream_forward_getp (peer->ibuf, length);
1845 if (attr->extra && !attr->extra->lcommunity)
1846 return bgp_attr_malformed (args,
1847 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1850 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
1852 return BGP_ATTR_PARSE_PROCEED;
1855 /* Extended Community attribute. */
1856 static bgp_attr_parse_ret_t
1857 bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
1859 struct peer *const peer = args->peer;
1860 struct attr *const attr = args->attr;
1861 const bgp_size_t length = args->length;
1866 attr->extra->ecommunity = NULL;
1867 /* Empty extcomm doesn't seem to be invalid per se */
1868 return BGP_ATTR_PARSE_PROCEED;
1871 (bgp_attr_extra_get (attr))->ecommunity =
1872 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1873 /* XXX: fix ecommunity_parse to use stream API */
1874 stream_forward_getp (peer->ibuf, length);
1876 if (attr->extra && !attr->extra->ecommunity)
1877 return bgp_attr_malformed (args,
1878 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1881 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1883 return BGP_ATTR_PARSE_PROCEED;
1886 /* Parse Tunnel Encap attribute in an UPDATE */
1890 struct peer *peer, /* IN */
1891 bgp_size_t length, /* IN: attr's length field */
1892 struct attr *attr, /* IN: caller already allocated */
1893 u_char flag, /* IN: attr's flags field */
1897 struct attr_extra *attre = NULL;
1898 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1899 uint16_t tunneltype;
1901 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1903 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1904 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1906 zlog (peer->log, LOG_ERR,
1907 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1908 bgp_notify_send_with_data (peer,
1909 BGP_NOTIFY_UPDATE_ERR,
1910 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1915 if (BGP_ATTR_ENCAP == type) {
1916 /* read outer TLV type and length */
1917 uint16_t tlv_length;
1920 zlog (peer->log, LOG_ERR,
1921 "Tunnel Encap attribute not long enough to contain outer T,L");
1922 bgp_notify_send_with_data(peer,
1923 BGP_NOTIFY_UPDATE_ERR,
1924 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1928 tunneltype = stream_getw (BGP_INPUT (peer));
1929 tlv_length = stream_getw (BGP_INPUT (peer));
1932 if (tlv_length != length) {
1933 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1934 __func__, tlv_length, length);
1938 while (length >= 4) {
1939 uint16_t subtype = 0;
1940 uint16_t sublength = 0;
1941 struct bgp_attr_encap_subtlv *tlv;
1943 if (BGP_ATTR_ENCAP == type) {
1944 subtype = stream_getc (BGP_INPUT (peer));
1945 sublength = stream_getc (BGP_INPUT (peer));
1949 if (sublength > length) {
1950 zlog (peer->log, LOG_ERR,
1951 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1953 bgp_notify_send_with_data (peer,
1954 BGP_NOTIFY_UPDATE_ERR,
1955 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1960 /* alloc and copy sub-tlv */
1961 /* TBD make sure these are freed when attributes are released */
1962 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1963 tlv->type = subtype;
1964 tlv->length = sublength;
1965 stream_get(tlv->value, peer->ibuf, sublength);
1966 length -= sublength;
1968 /* attach tlv to encap chain */
1970 attre = bgp_attr_extra_get(attr);
1971 if (BGP_ATTR_ENCAP == type) {
1972 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1973 stlv_last = stlv_last->next);
1975 stlv_last->next = tlv;
1977 attre->encap_subtlvs = tlv;
1981 stlv_last->next = tlv;
1986 if (attre && (BGP_ATTR_ENCAP == type)) {
1987 attre->encap_tunneltype = tunneltype;
1991 /* spurious leftover data */
1992 zlog (peer->log, LOG_ERR,
1993 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1994 bgp_notify_send_with_data (peer,
1995 BGP_NOTIFY_UPDATE_ERR,
1996 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2004 /* BGP unknown attribute treatment. */
2005 static bgp_attr_parse_ret_t
2006 bgp_attr_unknown (struct bgp_attr_parser_args *args)
2008 bgp_size_t total = args->total;
2009 struct transit *transit;
2010 struct attr_extra *attre;
2011 struct peer *const peer = args->peer;
2012 struct attr *const attr = args->attr;
2013 u_char *const startp = args->startp;
2014 const u_char type = args->type;
2015 const u_char flag = args->flags;
2016 const bgp_size_t length = args->length;
2019 if (BGP_DEBUG (normal, NORMAL))
2020 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2021 peer->host, type, length);
2023 if (BGP_DEBUG (events, EVENTS))
2024 zlog (peer->log, LOG_DEBUG,
2025 "Unknown attribute type %d length %d is received", type, length);
2027 /* Forward read pointer of input stream. */
2028 stream_forward_getp (peer->ibuf, length);
2030 /* If any of the mandatory well-known attributes are not recognized,
2031 then the Error Subcode is set to Unrecognized Well-known
2032 Attribute. The Data field contains the unrecognized attribute
2033 (type, length and value). */
2034 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
2036 return bgp_attr_malformed (args,
2037 BGP_NOTIFY_UPDATE_UNREC_ATTR,
2041 /* Unrecognized non-transitive optional attributes must be quietly
2042 ignored and not passed along to other BGP peers. */
2043 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
2044 return BGP_ATTR_PARSE_PROCEED;
2046 /* If a path with recognized transitive optional attribute is
2047 accepted and passed along to other BGP peers and the Partial bit
2048 in the Attribute Flags octet is set to 1 by some previous AS, it
2049 is not set back to 0 by the current AS. */
2050 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
2052 /* Store transitive attribute to the end of attr->transit. */
2053 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
2054 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
2056 transit = attre->transit;
2059 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
2060 transit->length + total);
2062 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2064 memcpy (transit->val + transit->length, startp, total);
2065 transit->length += total;
2067 return BGP_ATTR_PARSE_PROCEED;
2070 /* Well-known attribute check. */
2072 bgp_attr_check (struct peer *peer, struct attr *attr)
2076 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2078 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2079 return BGP_ATTR_PARSE_PROCEED;
2081 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2082 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2083 are present, it should. Check for any other attribute being present
2086 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2087 return BGP_ATTR_PARSE_PROCEED;
2089 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2090 type = BGP_ATTR_ORIGIN;
2092 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2093 type = BGP_ATTR_AS_PATH;
2095 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2096 * NLRI is empty. We can't easily check NLRI empty here though.
2098 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2099 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
2100 type = BGP_ATTR_NEXT_HOP;
2102 if (peer->sort == BGP_PEER_IBGP
2103 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2104 type = BGP_ATTR_LOCAL_PREF;
2108 zlog (peer->log, LOG_WARNING,
2109 "%s Missing well-known attribute %d / %s",
2110 peer->host, type, LOOKUP (attr_str, type));
2111 bgp_notify_send_with_data (peer,
2112 BGP_NOTIFY_UPDATE_ERR,
2113 BGP_NOTIFY_UPDATE_MISS_ATTR,
2115 return BGP_ATTR_PARSE_ERROR;
2117 return BGP_ATTR_PARSE_PROCEED;
2120 /* Read attribute of update packet. This function is called from
2121 bgp_update_receive() in bgp_packet.c. */
2122 bgp_attr_parse_ret_t
2123 bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2124 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2130 u_char *startp, *endp;
2132 u_char seen[BGP_ATTR_BITMAP_SIZE];
2133 /* we need the as4_path only until we have synthesized the as_path with it */
2134 /* same goes for as4_aggregator */
2135 struct aspath *as4_path = NULL;
2136 as_t as4_aggregator = 0;
2137 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
2139 /* Initialize bitmap. */
2140 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2142 /* End pointer of BGP attribute. */
2143 endp = BGP_INPUT_PNT (peer) + size;
2145 /* Get attributes to the end of attribute length. */
2146 while (BGP_INPUT_PNT (peer) < endp)
2148 /* Check remaining length check.*/
2149 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2151 /* XXX warning: long int format, int arg (arg 5) */
2152 zlog (peer->log, LOG_WARNING,
2153 "%s: error BGP attribute length %lu is smaller than min len",
2155 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2157 bgp_notify_send (peer,
2158 BGP_NOTIFY_UPDATE_ERR,
2159 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2160 return BGP_ATTR_PARSE_ERROR;
2163 /* Fetch attribute flag and type. */
2164 startp = BGP_INPUT_PNT (peer);
2165 /* "The lower-order four bits of the Attribute Flags octet are
2166 unused. They MUST be zero when sent and MUST be ignored when
2168 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
2169 type = stream_getc (BGP_INPUT (peer));
2171 /* Check whether Extended-Length applies and is in bounds */
2172 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2173 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2175 zlog (peer->log, LOG_WARNING,
2176 "%s: Extended length set, but just %lu bytes of attr header",
2178 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2180 bgp_notify_send (peer,
2181 BGP_NOTIFY_UPDATE_ERR,
2182 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2183 return BGP_ATTR_PARSE_ERROR;
2186 /* Check extended attribue length bit. */
2187 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2188 length = stream_getw (BGP_INPUT (peer));
2190 length = stream_getc (BGP_INPUT (peer));
2192 /* If any attribute appears more than once in the UPDATE
2193 message, then the Error Subcode is set to Malformed Attribute
2196 if (CHECK_BITMAP (seen, type))
2198 zlog (peer->log, LOG_WARNING,
2199 "%s: error BGP attribute type %d appears twice in a message",
2202 bgp_notify_send (peer,
2203 BGP_NOTIFY_UPDATE_ERR,
2204 BGP_NOTIFY_UPDATE_MAL_ATTR);
2205 return BGP_ATTR_PARSE_ERROR;
2208 /* Set type to bitmap to check duplicate attribute. `type' is
2209 unsigned char so it never overflow bitmap range. */
2211 SET_BITMAP (seen, type);
2213 /* Overflow check. */
2214 attr_endp = BGP_INPUT_PNT (peer) + length;
2216 if (attr_endp > endp)
2218 zlog (peer->log, LOG_WARNING,
2219 "%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);
2220 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);
2221 bgp_notify_send_with_data (peer,
2222 BGP_NOTIFY_UPDATE_ERR,
2223 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2224 startp, attr_endp - startp);
2225 return BGP_ATTR_PARSE_ERROR;
2228 struct bgp_attr_parser_args attr_args = {
2235 .total = attr_endp - startp,
2239 /* If any recognized attribute has Attribute Flags that conflict
2240 with the Attribute Type Code, then the Error Subcode is set to
2241 Attribute Flags Error. The Data field contains the erroneous
2242 attribute (type, length and value). */
2243 if (bgp_attr_flag_invalid (&attr_args))
2245 bgp_attr_parse_ret_t ret;
2246 ret = bgp_attr_malformed (&attr_args,
2247 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2249 if (ret == BGP_ATTR_PARSE_PROCEED)
2254 /* OK check attribute and store it's value. */
2257 case BGP_ATTR_ORIGIN:
2258 ret = bgp_attr_origin (&attr_args);
2260 case BGP_ATTR_AS_PATH:
2261 ret = bgp_attr_aspath (&attr_args);
2263 case BGP_ATTR_AS4_PATH:
2264 ret = bgp_attr_as4_path (&attr_args, &as4_path);
2266 case BGP_ATTR_NEXT_HOP:
2267 ret = bgp_attr_nexthop (&attr_args);
2269 case BGP_ATTR_MULTI_EXIT_DISC:
2270 ret = bgp_attr_med (&attr_args);
2272 case BGP_ATTR_LOCAL_PREF:
2273 ret = bgp_attr_local_pref (&attr_args);
2275 case BGP_ATTR_ATOMIC_AGGREGATE:
2276 ret = bgp_attr_atomic (&attr_args);
2278 case BGP_ATTR_AGGREGATOR:
2279 ret = bgp_attr_aggregator (&attr_args);
2281 case BGP_ATTR_AS4_AGGREGATOR:
2282 ret = bgp_attr_as4_aggregator (&attr_args,
2284 &as4_aggregator_addr);
2286 case BGP_ATTR_COMMUNITIES:
2287 ret = bgp_attr_community (&attr_args);
2289 case BGP_ATTR_LARGE_COMMUNITIES:
2290 ret = bgp_attr_large_community (&attr_args);
2292 case BGP_ATTR_ORIGINATOR_ID:
2293 ret = bgp_attr_originator_id (&attr_args);
2295 case BGP_ATTR_CLUSTER_LIST:
2296 ret = bgp_attr_cluster_list (&attr_args);
2298 case BGP_ATTR_MP_REACH_NLRI:
2299 ret = bgp_mp_reach_parse (&attr_args, mp_update);
2301 case BGP_ATTR_MP_UNREACH_NLRI:
2302 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
2304 case BGP_ATTR_EXT_COMMUNITIES:
2305 ret = bgp_attr_ext_communities (&attr_args);
2307 case BGP_ATTR_ENCAP:
2308 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2311 ret = bgp_attr_unknown (&attr_args);
2315 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2317 bgp_notify_send (peer,
2318 BGP_NOTIFY_UPDATE_ERR,
2319 BGP_NOTIFY_UPDATE_MAL_ATTR);
2320 ret = BGP_ATTR_PARSE_ERROR;
2323 /* If hard error occured immediately return to the caller. */
2324 if (ret == BGP_ATTR_PARSE_ERROR)
2326 zlog (peer->log, LOG_WARNING,
2327 "%s: Attribute %s, parse error",
2329 LOOKUP (attr_str, type));
2331 aspath_unintern (&as4_path);
2334 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2337 zlog (peer->log, LOG_WARNING,
2338 "%s: Attribute %s, parse error - treating as withdrawal",
2340 LOOKUP (attr_str, type));
2342 aspath_unintern (&as4_path);
2346 /* Check the fetched length. */
2347 if (BGP_INPUT_PNT (peer) != attr_endp)
2349 zlog (peer->log, LOG_WARNING,
2350 "%s: BGP attribute %s, fetch error",
2351 peer->host, LOOKUP (attr_str, type));
2352 bgp_notify_send (peer,
2353 BGP_NOTIFY_UPDATE_ERR,
2354 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2356 aspath_unintern (&as4_path);
2357 return BGP_ATTR_PARSE_ERROR;
2360 /* Check final read pointer is same as end pointer. */
2361 if (BGP_INPUT_PNT (peer) != endp)
2363 zlog (peer->log, LOG_WARNING,
2364 "%s: BGP attribute %s, length mismatch",
2365 peer->host, LOOKUP (attr_str, type));
2366 bgp_notify_send (peer,
2367 BGP_NOTIFY_UPDATE_ERR,
2368 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2370 aspath_unintern (&as4_path);
2371 return BGP_ATTR_PARSE_ERROR;
2374 /* Check all mandatory well-known attributes are present */
2376 bgp_attr_parse_ret_t ret;
2377 if ((ret = bgp_attr_check (peer, attr)) < 0)
2380 aspath_unintern (&as4_path);
2386 * At this place we can see whether we got AS4_PATH and/or
2387 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2388 * We can not do this before we've read all attributes because
2389 * the as4 handling does not say whether AS4_PATH has to be sent
2390 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2391 * in relationship to AGGREGATOR.
2392 * So, to be defensive, we are not relying on any order and read
2393 * all attributes first, including these 32bit ones, and now,
2394 * afterwards, we look what and if something is to be done for as4.
2396 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2399 /* actually... this doesn't ever return failure currently, but
2400 * better safe than sorry */
2401 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2402 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
2403 as4_aggregator, &as4_aggregator_addr))
2405 bgp_notify_send (peer,
2406 BGP_NOTIFY_UPDATE_ERR,
2407 BGP_NOTIFY_UPDATE_MAL_ATTR);
2409 aspath_unintern (&as4_path);
2410 return BGP_ATTR_PARSE_ERROR;
2413 /* At this stage, we have done all fiddling with as4, and the
2414 * resulting info is in attr->aggregator resp. attr->aspath
2415 * so we can chuck as4_aggregator and as4_path alltogether in
2416 * order to save memory
2420 aspath_unintern (&as4_path); /* unintern - it is in the hash */
2421 /* The flag that we got this is still there, but that does not
2426 * The "rest" of the code does nothing with as4_aggregator.
2427 * there is no memory attached specifically which is not part
2429 * so ignoring just means do nothing.
2432 * Finally do the checks on the aspath we did not do yet
2433 * because we waited for a potentially synthesized aspath.
2435 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
2437 ret = bgp_attr_aspath_check (peer, attr);
2438 if (ret != BGP_ATTR_PARSE_PROCEED)
2442 /* Finally intern unknown attribute. */
2443 if (attr->extra && attr->extra->transit)
2444 attr->extra->transit = transit_intern (attr->extra->transit);
2446 return BGP_ATTR_PARSE_PROCEED;
2449 int stream_put_prefix (struct stream *, struct prefix *);
2452 bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2457 /* Set extended bit always to encode the attribute length as 2 bytes */
2458 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2459 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2460 sizep = stream_get_endp (s);
2461 stream_putw (s, 0); /* Marker: Attribute length. */
2463 stream_putw (s, afi);
2464 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
2472 case SAFI_MULTICAST:
2474 stream_put_ipv4 (s, attr->nexthop.s_addr);
2477 stream_putc (s, 12);
2478 stream_putl (s, 0); /* RD = 0, per RFC */
2480 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2484 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2486 case SAFI_UNICAST: /* invalid for IPv4 */
2495 case SAFI_MULTICAST:
2497 struct attr_extra *attre = attr->extra;
2499 assert (attr->extra);
2500 stream_putc (s, attre->mp_nexthop_len);
2501 stream_put (s, &attre->mp_nexthop_global, 16);
2502 if (attre->mp_nexthop_len == 32)
2503 stream_put (s, &attre->mp_nexthop_local, 16);
2508 struct attr_extra *attre = attr->extra;
2510 assert (attr->extra);
2511 if (attre->mp_nexthop_len == 16) {
2512 stream_putc (s, 24);
2513 stream_putl (s, 0); /* RD = 0, per RFC */
2515 stream_put (s, &attre->mp_nexthop_global, 16);
2516 } else if (attre->mp_nexthop_len == 32) {
2517 stream_putc (s, 48);
2518 stream_putl (s, 0); /* RD = 0, per RFC */
2520 stream_put (s, &attre->mp_nexthop_global, 16);
2521 stream_putl (s, 0); /* RD = 0, per RFC */
2523 stream_put (s, &attre->mp_nexthop_local, 16);
2528 assert (attr->extra);
2529 stream_putc (s, 16);
2530 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2546 bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2547 struct prefix *p, struct prefix_rd *prd,
2550 if (safi == SAFI_MPLS_VPN)
2552 /* Tag, RD, Prefix write. */
2553 stream_putc (s, p->prefixlen + 88);
2554 stream_put (s, tag, 3);
2555 stream_put (s, prd->val, 8);
2556 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2559 stream_put_prefix (s, p);
2563 bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2565 int size = PSIZE (p->prefixlen);
2566 if (safi == SAFI_MPLS_VPN)
2572 * Encodes the tunnel encapsulation attribute
2575 bgp_packet_mpattr_tea(
2582 unsigned int attrlenfield = 0;
2583 unsigned int attrhdrlen = 0;
2584 struct bgp_attr_encap_subtlv *subtlvs;
2585 struct bgp_attr_encap_subtlv *st;
2586 const char *attrname;
2588 if (!attr || !attr->extra)
2592 case BGP_ATTR_ENCAP:
2593 attrname = "Tunnel Encap";
2594 subtlvs = attr->extra->encap_subtlvs;
2597 * The tunnel encap attr has an "outer" tlv.
2599 * L = total length of subtlvs,
2600 * V = concatenated subtlvs.
2602 attrlenfield = 2 + 2; /* T + L */
2603 attrhdrlen = 1 + 1; /* subTLV T + L */
2611 /* if no tlvs, don't make attr */
2612 if (subtlvs == NULL)
2615 /* compute attr length */
2616 for (st = subtlvs; st; st = st->next) {
2617 attrlenfield += (attrhdrlen + st->length);
2620 if (attrlenfield > 0xffff) {
2621 zlog (peer->log, LOG_ERR,
2622 "%s attribute is too long (length=%d), can't send it",
2628 if (attrlenfield > 0xff) {
2629 /* 2-octet length field */
2631 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2632 stream_putc (s, attrtype);
2633 stream_putw (s, attrlenfield & 0xffff);
2635 /* 1-octet length field */
2636 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2637 stream_putc (s, attrtype);
2638 stream_putc (s, attrlenfield & 0xff);
2641 if (attrtype == BGP_ATTR_ENCAP) {
2642 /* write outer T+L */
2643 stream_putw(s, attr->extra->encap_tunneltype);
2644 stream_putw(s, attrlenfield - 4);
2647 /* write each sub-tlv */
2648 for (st = subtlvs; st; st = st->next) {
2649 if (attrtype == BGP_ATTR_ENCAP) {
2650 stream_putc (s, st->type);
2651 stream_putc (s, st->length);
2653 stream_put (s, st->value, st->length);
2658 bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2660 /* Set MP attribute length. Don't count the (2) bytes used to encode
2662 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2665 /* Make attribute packet. */
2667 bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
2668 struct stream *s, struct attr *attr,
2669 struct prefix *p, afi_t afi, safi_t safi,
2670 struct peer *from, struct prefix_rd *prd, u_char *tag)
2673 size_t aspath_sizep;
2674 struct aspath *aspath;
2675 int send_as4_path = 0;
2676 int send_as4_aggregator = 0;
2677 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
2680 bgp = bgp_get_default ();
2682 /* Remember current pointer. */
2683 cp = stream_get_endp (s);
2685 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2687 size_t mpattrlen_pos = 0;
2688 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2689 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2690 bgp_packet_mpattr_end(s, mpattrlen_pos);
2693 /* Origin attribute. */
2694 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2695 stream_putc (s, BGP_ATTR_ORIGIN);
2697 stream_putc (s, attr->origin);
2699 /* AS path attribute. */
2701 /* If remote-peer is EBGP */
2702 if (peer->sort == BGP_PEER_EBGP
2703 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
2704 || attr->aspath->segments == NULL)
2705 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
2707 aspath = aspath_dup (attr->aspath);
2709 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2711 /* Strip the confed info, and then stuff our path CONFED_ID
2713 aspath = aspath_delete_confed_seq (aspath);
2714 aspath = aspath_add_seq (aspath, bgp->confed_id);
2718 if (peer->change_local_as) {
2719 /* If replace-as is specified, we only use the change_local_as when
2720 advertising routes. */
2721 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2722 aspath = aspath_add_seq (aspath, peer->local_as);
2724 aspath = aspath_add_seq (aspath, peer->change_local_as);
2726 aspath = aspath_add_seq (aspath, peer->local_as);
2730 else if (peer->sort == BGP_PEER_CONFED)
2732 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2733 aspath = aspath_dup (attr->aspath);
2734 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2737 aspath = attr->aspath;
2739 /* If peer is not AS4 capable, then:
2740 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2741 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2742 * types are in it (i.e. exclude them if they are there)
2743 * AND do this only if there is at least one asnum > 65535 in the path!
2744 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2745 * all ASnums > 65535 to BGP_AS_TRANS
2748 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2749 stream_putc (s, BGP_ATTR_AS_PATH);
2750 aspath_sizep = stream_get_endp (s);
2752 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2754 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2757 if (!use32bit && aspath_has_as4 (aspath))
2758 send_as4_path = 1; /* we'll do this later, at the correct place */
2760 /* Nexthop attribute. */
2761 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2762 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
2764 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2765 stream_putc (s, BGP_ATTR_NEXT_HOP);
2767 if (safi == SAFI_MPLS_VPN)
2769 if (attr->nexthop.s_addr == 0)
2770 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2772 stream_put_ipv4 (s, attr->nexthop.s_addr);
2775 stream_put_ipv4 (s, attr->nexthop.s_addr);
2778 /* MED attribute. */
2779 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2781 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2782 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2784 stream_putl (s, attr->med);
2787 /* Local preference. */
2788 if (peer->sort == BGP_PEER_IBGP ||
2789 peer->sort == BGP_PEER_CONFED)
2791 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2792 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2794 stream_putl (s, attr->local_pref);
2797 /* Atomic aggregate. */
2798 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2800 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2801 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2806 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2808 assert (attr->extra);
2810 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
2811 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2812 stream_putc (s, BGP_ATTR_AGGREGATOR);
2816 /* AS4 capable peer */
2818 stream_putl (s, attr->extra->aggregator_as);
2822 /* 2-byte AS peer */
2825 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2826 if ( attr->extra->aggregator_as > 65535 )
2828 stream_putw (s, BGP_AS_TRANS);
2830 /* we have to send AS4_AGGREGATOR, too.
2831 * we'll do that later in order to send attributes in ascending
2834 send_as4_aggregator = 1;
2837 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2839 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2842 /* Community attribute. */
2843 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2844 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2846 if (attr->community->size * 4 > 255)
2848 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2849 stream_putc (s, BGP_ATTR_COMMUNITIES);
2850 stream_putw (s, attr->community->size * 4);
2854 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2855 stream_putc (s, BGP_ATTR_COMMUNITIES);
2856 stream_putc (s, attr->community->size * 4);
2858 stream_put (s, attr->community->val, attr->community->size * 4);
2862 * Large Community attribute.
2865 CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)
2866 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)))
2868 if (attr->extra->lcommunity->size * 12 > 255)
2870 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2871 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
2872 stream_putw (s, attr->extra->lcommunity->size * 12);
2876 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2877 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
2878 stream_putc (s, attr->extra->lcommunity->size * 12);
2880 stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
2883 /* Route Reflector. */
2884 if (peer->sort == BGP_PEER_IBGP
2886 && from->sort == BGP_PEER_IBGP)
2888 /* Originator ID. */
2889 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2890 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2893 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
2894 stream_put_in_addr (s, &attr->extra->originator_id);
2896 stream_put_in_addr (s, &from->remote_id);
2899 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2900 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2902 if (attr->extra && attr->extra->cluster)
2904 stream_putc (s, attr->extra->cluster->length + 4);
2905 /* If this peer configuration's parent BGP has cluster_id. */
2906 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2907 stream_put_in_addr (s, &bgp->cluster_id);
2909 stream_put_in_addr (s, &bgp->router_id);
2910 stream_put (s, attr->extra->cluster->list,
2911 attr->extra->cluster->length);
2916 /* If this peer configuration's parent BGP has cluster_id. */
2917 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2918 stream_put_in_addr (s, &bgp->cluster_id);
2920 stream_put_in_addr (s, &bgp->router_id);
2924 /* Extended Communities attribute. */
2925 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2926 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2928 struct attr_extra *attre = attr->extra;
2932 if (peer->sort == BGP_PEER_IBGP
2933 || peer->sort == BGP_PEER_CONFED)
2935 if (attre->ecommunity->size * 8 > 255)
2937 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2938 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2939 stream_putw (s, attre->ecommunity->size * 8);
2943 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2944 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2945 stream_putc (s, attre->ecommunity->size * 8);
2947 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
2953 int ecom_tr_size = 0;
2956 for (i = 0; i < attre->ecommunity->size; i++)
2958 pnt = attre->ecommunity->val + (i * 8);
2961 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2969 if (ecom_tr_size * 8 > 255)
2971 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2972 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2973 stream_putw (s, ecom_tr_size * 8);
2977 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2978 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2979 stream_putc (s, ecom_tr_size * 8);
2982 for (i = 0; i < attre->ecommunity->size; i++)
2984 pnt = attre->ecommunity->val + (i * 8);
2987 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2990 stream_put (s, pnt, 8);
2996 if ( send_as4_path )
2998 /* If the peer is NOT As4 capable, AND */
2999 /* there are ASnums > 65535 in path THEN
3000 * give out AS4_PATH */
3002 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3004 * Hm, I wonder... confederation things *should* only be at
3005 * the beginning of an aspath, right? Then we should use
3006 * aspath_delete_confed_seq for this, because it is already
3008 * Folks, talk to me: what is reasonable here!?
3010 aspath = aspath_delete_confed_seq (aspath);
3012 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
3013 stream_putc (s, BGP_ATTR_AS4_PATH);
3014 aspath_sizep = stream_get_endp (s);
3016 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
3019 if (aspath != attr->aspath)
3020 aspath_free (aspath);
3022 if ( send_as4_aggregator )
3024 assert (attr->extra);
3026 /* send AS4_AGGREGATOR, at this place */
3027 /* this section of code moved here in order to ensure the correct
3028 * *ascending* order of attributes
3030 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3031 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
3033 stream_putl (s, attr->extra->aggregator_as);
3034 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
3037 if ((afi == AFI_IP || afi == AFI_IP6) &&
3038 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
3040 /* Tunnel Encap attribute */
3041 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
3044 /* Unknown transit attribute. */
3045 if (attr->extra && attr->extra->transit)
3046 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
3048 /* Return total size of attribute. */
3049 return stream_get_endp (s) - cp;
3053 bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
3055 unsigned long attrlen_pnt;
3057 /* Set extended bit always to encode the attribute length as 2 bytes */
3058 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
3059 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
3061 attrlen_pnt = stream_get_endp (s);
3062 stream_putw (s, 0); /* Length of this attribute. */
3064 stream_putw (s, afi);
3065 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
3070 bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
3071 afi_t afi, safi_t safi, struct prefix_rd *prd,
3074 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
3078 bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
3080 bgp_packet_mpattr_end (s, attrlen_pnt);
3083 /* Initialization of attribute. */
3085 bgp_attr_init (void)
3097 bgp_attr_finish (void)
3101 community_finish ();
3102 ecommunity_finish ();
3103 lcommunity_finish ();
3108 /* Make attribute packet. */
3110 bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3111 struct prefix *prefix)
3116 struct aspath *aspath;
3118 /* Remember current pointer. */
3119 cp = stream_get_endp (s);
3121 /* Place holder of length. */
3124 /* Origin attribute. */
3125 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3126 stream_putc (s, BGP_ATTR_ORIGIN);
3128 stream_putc (s, attr->origin);
3130 aspath = attr->aspath;
3132 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3133 stream_putc (s, BGP_ATTR_AS_PATH);
3134 aspath_lenp = stream_get_endp (s);
3137 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
3139 /* Nexthop attribute. */
3140 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3142 && prefix->family != AF_INET6
3145 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3146 stream_putc (s, BGP_ATTR_NEXT_HOP);
3148 stream_put_ipv4 (s, attr->nexthop.s_addr);
3151 /* MED attribute. */
3152 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3154 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3155 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3157 stream_putl (s, attr->med);
3160 /* Local preference. */
3161 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3163 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3164 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3166 stream_putl (s, attr->local_pref);
3169 /* Atomic aggregate. */
3170 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3172 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3173 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3178 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3180 assert (attr->extra);
3181 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3182 stream_putc (s, BGP_ATTR_AGGREGATOR);
3184 stream_putl (s, attr->extra->aggregator_as);
3185 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
3188 /* Community attribute. */
3189 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3191 if (attr->community->size * 4 > 255)
3193 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3194 stream_putc (s, BGP_ATTR_COMMUNITIES);
3195 stream_putw (s, attr->community->size * 4);
3199 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3200 stream_putc (s, BGP_ATTR_COMMUNITIES);
3201 stream_putc (s, attr->community->size * 4);
3203 stream_put (s, attr->community->val, attr->community->size * 4);
3206 /* Large Community attribute. */
3207 if (attr->extra && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES))
3209 if (attr->extra->lcommunity->size * 12 > 255)
3211 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3212 stream_putc (s, BGP_ATTR_COMMUNITIES);
3213 stream_putw (s, attr->extra->lcommunity->size * 12);
3217 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3218 stream_putc (s, BGP_ATTR_COMMUNITIES);
3219 stream_putc (s, attr->extra->lcommunity->size * 12);
3222 stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
3225 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3226 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3227 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
3230 struct attr_extra *attre = attr->extra;
3232 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3233 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
3234 sizep = stream_get_endp (s);
3237 stream_putc (s, 0); /* Marker: Attribute length. */
3238 stream_putw(s, AFI_IP6); /* AFI */
3239 stream_putc(s, SAFI_UNICAST); /* SAFI */
3242 stream_putc(s, attre->mp_nexthop_len);
3243 stream_put(s, &attre->mp_nexthop_global, 16);
3244 if (attre->mp_nexthop_len == 32)
3245 stream_put(s, &attre->mp_nexthop_local, 16);
3251 stream_put_prefix(s, prefix);
3253 /* Set MP attribute length. */
3254 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
3257 /* Return total size of attribute. */
3258 len = stream_get_endp (s) - cp - 2;
3259 stream_putw_at (s, cp, len);