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)
204 struct cluster_list *c = *cluster;
210 hash_release (cluster_hash, c);
219 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
223 cluster_finish (void)
225 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
226 hash_free (cluster_hash);
230 struct bgp_attr_encap_subtlv *
231 encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
233 struct bgp_attr_encap_subtlv *new;
234 struct bgp_attr_encap_subtlv *tail;
235 struct bgp_attr_encap_subtlv *p;
237 for (p = orig, tail = new = NULL; p; p = p->next) {
238 int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length;
240 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
243 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
246 memcpy(tail, p, size);
254 encap_free(struct bgp_attr_encap_subtlv *p)
256 struct bgp_attr_encap_subtlv *next;
260 XFREE(MTYPE_ENCAP_TLV, p);
266 bgp_attr_flush_encap(struct attr *attr)
268 if (!attr || !attr->extra)
271 if (attr->extra->encap_subtlvs) {
272 encap_free(attr->extra->encap_subtlvs);
273 attr->extra->encap_subtlvs = NULL;
278 * Compare encap sub-tlv chains
283 * This algorithm could be made faster if needed
286 encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
288 struct bgp_attr_encap_subtlv *p;
289 struct bgp_attr_encap_subtlv *q;
300 for (p = h1; p; p = p->next) {
301 for (q = h2; q; q = q->next) {
302 if ((p->type == q->type) &&
303 (p->length == q->length) &&
304 !memcmp(p->value, q->value, p->length)) {
313 for (p = h2; p; p = p->next) {
314 for (q = h1; q; q = q->next) {
315 if ((p->type == q->type) &&
316 (p->length == q->length) &&
317 !memcmp(p->value, q->value, p->length)) {
329 /* Unknown transit attribute. */
330 static struct hash *transit_hash;
333 transit_free (struct transit *transit)
336 XFREE (MTYPE_TRANSIT_VAL, transit->val);
337 XFREE (MTYPE_TRANSIT, transit);
342 transit_hash_alloc (void *p)
344 /* Transit structure is already allocated. */
348 static struct transit *
349 transit_intern (struct transit *transit)
351 struct transit *find;
353 find = hash_get (transit_hash, transit, transit_hash_alloc);
355 transit_free (transit);
362 transit_unintern (struct transit **transit)
364 struct transit *t = *transit;
371 hash_release (transit_hash, t);
378 transit_hash_key_make (void *p)
380 const struct transit * transit = p;
382 return jhash(transit->val, transit->length, 0);
386 transit_hash_cmp (const void *p1, const void *p2)
388 const struct transit * transit1 = p1;
389 const struct transit * transit2 = p2;
391 return (transit1->length == transit2->length &&
392 memcmp (transit1->val, transit2->val, transit1->length) == 0);
398 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
402 transit_finish (void)
404 hash_clean (transit_hash, (void (*)(void *))transit_free);
405 hash_free (transit_hash);
409 /* Attribute hash routines. */
410 static struct hash *attrhash;
412 static struct attr_extra *
413 bgp_attr_extra_new (void)
415 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
419 bgp_attr_extra_free (struct attr *attr)
423 if (attr->extra->encap_subtlvs) {
424 encap_free(attr->extra->encap_subtlvs);
425 attr->extra->encap_subtlvs = NULL;
427 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
433 bgp_attr_extra_get (struct attr *attr)
436 attr->extra = bgp_attr_extra_new();
440 /* Shallow copy of an attribute
441 * Though, not so shallow that it doesn't copy the contents
442 * of the attr_extra pointed to by 'extra'
445 bgp_attr_dup (struct attr *new, struct attr *orig)
447 struct attr_extra *extra = new->extra;
450 /* if caller provided attr_extra space, use it in any case.
452 * This is neccesary even if orig->extra equals NULL, because otherwise
453 * memory may be later allocated on the heap by bgp_attr_extra_get.
455 * That memory would eventually be leaked, because the caller must not
456 * call bgp_attr_extra_free if he provided attr_extra on the stack.
461 memset(new->extra, 0, sizeof(struct attr_extra));
463 *new->extra = *orig->extra;
464 if (orig->extra->encap_subtlvs) {
465 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
469 else if (orig->extra)
471 new->extra = bgp_attr_extra_new();
472 *new->extra = *orig->extra;
473 if (orig->extra->encap_subtlvs) {
474 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
482 return attrhash->count;
486 attr_unknown_count (void)
488 return transit_hash->count;
492 attrhash_key_make (void *p)
494 const struct attr *attr = (struct attr *) p;
495 const struct attr_extra *extra = attr->extra;
497 #define MIX(val) key = jhash_1word(val, key)
500 MIX(attr->nexthop.s_addr);
502 MIX(attr->local_pref);
505 key += attr->nexthop.s_addr;
507 key += attr->local_pref;
511 MIX(extra->aggregator_as);
512 MIX(extra->aggregator_addr.s_addr);
514 MIX(extra->mp_nexthop_global_in.s_addr);
515 MIX(extra->originator_id.s_addr);
520 MIX(aspath_key_make (attr->aspath));
522 MIX(community_hash_make (attr->community));
526 if (extra->lcommunity)
527 MIX(lcommunity_hash_make (extra->lcommunity));
528 if (extra->ecommunity)
529 MIX(ecommunity_hash_make (extra->ecommunity));
531 MIX(cluster_hash_key_make (extra->cluster));
533 MIX(transit_hash_key_make (extra->transit));
535 MIX(extra->mp_nexthop_len);
536 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
537 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
544 attrhash_cmp (const void *p1, const void *p2)
546 const struct attr * attr1 = p1;
547 const struct attr * attr2 = p2;
549 if (attr1->flag == attr2->flag
550 && attr1->origin == attr2->origin
551 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
552 && attr1->aspath == attr2->aspath
553 && attr1->community == attr2->community
554 && attr1->med == attr2->med
555 && attr1->local_pref == attr2->local_pref)
557 const struct attr_extra *ae1 = attr1->extra;
558 const struct attr_extra *ae2 = attr2->extra;
561 && ae1->aggregator_as == ae2->aggregator_as
562 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
563 && ae1->weight == ae2->weight
564 && ae1->tag == ae2->tag
565 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
566 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
567 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
568 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
569 && ae1->ecommunity == ae2->ecommunity
570 && ae1->lcommunity == ae2->lcommunity
571 && ae1->cluster == ae2->cluster
572 && ae1->transit == ae2->transit
573 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
574 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
575 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
579 /* neither attribute has extra attributes, so they're same */
589 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
593 * special for hash_clean below
596 attr_vfree (void *attr)
598 bgp_attr_extra_free ((struct attr *)attr);
599 XFREE (MTYPE_ATTR, attr);
603 attrhash_finish (void)
605 hash_clean(attrhash, attr_vfree);
606 hash_free (attrhash);
611 attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
613 struct attr *attr = backet->data;
615 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
616 inet_ntoa (attr->nexthop), VTY_NEWLINE);
620 attr_show_all (struct vty *vty)
622 hash_iterate (attrhash,
623 (void (*)(struct hash_backet *, void *))
624 attr_show_all_iterator,
629 bgp_attr_hash_alloc (void *p)
631 struct attr * val = (struct attr *) p;
634 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
638 attr->extra = bgp_attr_extra_new ();
639 *attr->extra = *val->extra;
641 if (attr->extra->encap_subtlvs) {
642 attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
649 /* Internet argument attribute. */
651 bgp_attr_intern (struct attr *attr)
655 /* Intern referenced strucutre. */
658 if (! attr->aspath->refcnt)
659 attr->aspath = aspath_intern (attr->aspath);
661 attr->aspath->refcnt++;
665 if (! attr->community->refcnt)
666 attr->community = community_intern (attr->community);
668 attr->community->refcnt++;
672 struct attr_extra *attre = attr->extra;
674 if (attre->ecommunity)
676 if (! attre->ecommunity->refcnt)
677 attre->ecommunity = ecommunity_intern (attre->ecommunity);
679 attre->ecommunity->refcnt++;
682 if (attre->lcommunity)
684 if (! attre->lcommunity->refcnt)
685 attre->lcommunity = lcommunity_intern (attre->lcommunity);
687 attre->lcommunity->refcnt++;
691 if (! attre->cluster->refcnt)
692 attre->cluster = cluster_intern (attre->cluster);
694 attre->cluster->refcnt++;
698 if (! attre->transit->refcnt)
699 attre->transit = transit_intern (attre->transit);
701 attre->transit->refcnt++;
705 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
712 /* Make network statement's attribute. */
714 bgp_attr_default_set (struct attr *attr, u_char origin)
716 memset (attr, 0, sizeof (struct attr));
717 bgp_attr_extra_get (attr);
719 attr->origin = origin;
720 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
721 attr->aspath = aspath_empty ();
722 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
723 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
724 attr->extra->tag = 0;
725 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
726 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
732 /* Make network statement's attribute. */
734 bgp_attr_default_intern (u_char origin)
739 memset (&attr, 0, sizeof (struct attr));
740 bgp_attr_extra_get (&attr);
742 bgp_attr_default_set(&attr, origin);
744 new = bgp_attr_intern (&attr);
745 bgp_attr_extra_free (&attr);
747 aspath_unintern (&new->aspath);
751 /* Create the attributes for an aggregate */
753 bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
754 struct aspath *aspath,
755 struct community *community, int as_set,
756 u_char atomic_aggregate)
760 struct attr_extra attre;
762 memset (&attr, 0, sizeof (struct attr));
763 memset (&attre, 0, sizeof (struct attr_extra));
766 /* Origin attribute. */
767 attr.origin = origin;
768 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
770 /* AS path attribute. */
772 attr.aspath = aspath_intern (aspath);
774 attr.aspath = aspath_empty ();
775 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
777 /* Next hop attribute. */
778 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
782 attr.community = community;
783 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
786 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
787 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
789 if (! as_set || atomic_aggregate)
790 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
791 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
792 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
793 attre.aggregator_as = bgp->confed_id;
795 attre.aggregator_as = bgp->as;
796 attre.aggregator_addr = bgp->router_id;
798 new = bgp_attr_intern (&attr);
800 aspath_unintern (&new->aspath);
804 /* Unintern just the sub-components of the attr, but not the attr */
806 bgp_attr_unintern_sub (struct attr *attr)
808 /* aspath refcount shoud be decrement. */
810 aspath_unintern (&attr->aspath);
811 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
814 community_unintern (&attr->community);
815 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
819 if (attr->extra->ecommunity)
820 ecommunity_unintern (&attr->extra->ecommunity);
821 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
823 if (attr->extra->lcommunity)
824 lcommunity_unintern (&attr->extra->lcommunity);
825 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
827 if (attr->extra->cluster)
828 cluster_unintern (&attr->extra->cluster);
829 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
831 if (attr->extra->transit)
832 transit_unintern (&attr->extra->transit);
836 /* Free bgp attribute and aspath. */
838 bgp_attr_unintern (struct attr **pattr)
840 struct attr *attr = *pattr;
843 struct attr_extra tmp_extra;
845 /* Decrement attribute reference. */
852 tmp.extra = &tmp_extra;
853 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
856 /* If reference becomes zero then free attribute object. */
857 if (attr->refcnt == 0)
859 ret = hash_release (attrhash, attr);
860 assert (ret != NULL);
861 bgp_attr_extra_free (attr);
862 XFREE (MTYPE_ATTR, attr);
866 bgp_attr_unintern_sub (&tmp);
870 bgp_attr_flush (struct attr *attr)
872 if (attr->aspath && ! attr->aspath->refcnt)
874 aspath_free (attr->aspath);
877 if (attr->community && ! attr->community->refcnt)
879 community_free (attr->community);
880 attr->community = NULL;
884 struct attr_extra *attre = attr->extra;
886 if (attre->ecommunity && ! attre->ecommunity->refcnt)
887 ecommunity_free (&attre->ecommunity);
888 if (attre->lcommunity && ! attre->lcommunity->refcnt)
889 lcommunity_free (&attre->lcommunity);
890 if (attre->cluster && ! attre->cluster->refcnt)
892 cluster_free (attre->cluster);
893 attre->cluster = NULL;
895 if (attre->transit && ! attre->transit->refcnt)
897 transit_free (attre->transit);
898 attre->transit = NULL;
900 encap_free(attre->encap_subtlvs);
901 attre->encap_subtlvs = NULL;
905 /* Implement some draft-ietf-idr-error-handling behaviour and
906 * avoid resetting sessions for malformed attributes which are
907 * are partial/optional and hence where the error likely was not
908 * introduced by the sending neighbour.
910 static bgp_attr_parse_ret_t
911 bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
914 struct peer *const peer = args->peer;
915 const u_int8_t flags = args->flags;
916 /* startp and length must be special-cased, as whether or not to
917 * send the attribute data with the NOTIFY depends on the error,
918 * the caller therefore signals this with the seperate length argument
920 u_char *notify_datap = (length > 0 ? args->startp : NULL);
922 /* The malformed attribute shouldn't be passed on, should
923 * we decide to proceed with parsing the UPDATE
925 UNSET_FLAG (args->attr->flag, ATTR_FLAG_BIT (args->type));
927 /* Only relax error handling for eBGP peers */
928 if (peer->sort != BGP_PEER_EBGP)
930 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
931 notify_datap, length);
932 return BGP_ATTR_PARSE_ERROR;
936 /* Adjust the stream getp to the end of the attribute, in case we can
937 * still proceed but the caller hasn't read all the attribute.
939 stream_set_getp (BGP_INPUT (peer),
940 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
943 switch (args->type) {
944 /* where an attribute is relatively inconsequential, e.g. it does not
945 * affect route selection, and can be safely ignored, then any such
946 * attributes which are malformed should just be ignored and the route
947 * processed as normal.
949 case BGP_ATTR_AS4_AGGREGATOR:
950 case BGP_ATTR_AGGREGATOR:
951 case BGP_ATTR_ATOMIC_AGGREGATE:
952 return BGP_ATTR_PARSE_PROCEED;
954 /* Core attributes, particularly ones which may influence route
955 * selection, should always cause session resets
957 case BGP_ATTR_ORIGIN:
958 case BGP_ATTR_AS_PATH:
959 case BGP_ATTR_NEXT_HOP:
960 case BGP_ATTR_MULTI_EXIT_DISC:
961 case BGP_ATTR_LOCAL_PREF:
962 case BGP_ATTR_COMMUNITIES:
963 case BGP_ATTR_ORIGINATOR_ID:
964 case BGP_ATTR_CLUSTER_LIST:
965 case BGP_ATTR_MP_REACH_NLRI:
966 case BGP_ATTR_MP_UNREACH_NLRI:
967 case BGP_ATTR_EXT_COMMUNITIES:
968 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
969 notify_datap, length);
970 return BGP_ATTR_PARSE_ERROR;
973 /* Partial optional attributes that are malformed should not cause
974 * the whole session to be reset. Instead treat it as a withdrawal
975 * of the routes, if possible.
977 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
978 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
979 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
980 return BGP_ATTR_PARSE_WITHDRAW;
982 /* default to reset */
983 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
984 notify_datap, length);
985 return BGP_ATTR_PARSE_ERROR;
988 /* Find out what is wrong with the path attribute flag bits and log the error.
989 "Flag bits" here stand for Optional, Transitive and Partial, but not for
990 Extended Length. Checking O/T/P bits at once implies, that the attribute
991 being diagnosed is defined by RFC as either a "well-known" or an "optional,
992 non-transitive" attribute. */
994 bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
995 u_int8_t desired_flags /* how RFC says it must be */
999 u_char real_flags = args->flags;
1000 const u_int8_t attr_code = args->type;
1002 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1003 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1004 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
1007 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
1008 CHECK_FLAG (real_flags, attr_flag_str[i].key)
1011 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
1012 LOOKUP (attr_str, attr_code),
1013 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
1014 attr_flag_str[i].str);
1019 zlog (args->peer->log, LOG_DEBUG,
1020 "Strange, %s called for attr %s, but no problem found with flags"
1021 " (real flags 0x%x, desired 0x%x)",
1022 __func__, LOOKUP (attr_str, attr_code),
1023 real_flags, desired_flags);
1027 /* Required flags for attributes. EXTLEN will be masked off when testing,
1028 * as will PARTIAL for optional+transitive attributes.
1030 const u_int8_t attr_flags_values [] = {
1031 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
1032 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
1033 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
1034 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
1035 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
1036 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
1037 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1038 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1039 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
1040 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1041 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1042 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1043 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1044 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1045 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1046 [BGP_ATTR_LARGE_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
1048 static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
1051 bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
1053 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
1054 const u_int8_t flags = args->flags;
1055 const u_int8_t attr_code = args->type;
1056 struct peer *const peer = args->peer;
1058 /* there may be attributes we don't know about */
1059 if (attr_code > attr_flags_values_max)
1061 if (attr_flags_values[attr_code] == 0)
1064 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1067 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1068 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1070 zlog (peer->log, LOG_ERR,
1071 "%s well-known attributes must have transitive flag set (%x)",
1072 LOOKUP (attr_str, attr_code), flags);
1076 /* "For well-known attributes and for optional non-transitive attributes,
1077 * the Partial bit MUST be set to 0."
1079 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1081 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1083 zlog (peer->log, LOG_ERR,
1084 "%s well-known attribute "
1085 "must NOT have the partial flag set (%x)",
1086 LOOKUP (attr_str, attr_code), flags);
1089 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1090 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1092 zlog (peer->log, LOG_ERR,
1093 "%s optional + transitive attribute "
1094 "must NOT have the partial flag set (%x)",
1095 LOOKUP (attr_str, attr_code), flags);
1100 /* Optional transitive attributes may go through speakers that don't
1101 * reocgnise them and set the Partial bit.
1103 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1104 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1105 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1108 == attr_flags_values[attr_code])
1111 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
1115 /* Get origin attribute of the update message. */
1116 static bgp_attr_parse_ret_t
1117 bgp_attr_origin (struct bgp_attr_parser_args *args)
1119 struct peer *const peer = args->peer;
1120 struct attr *const attr = args->attr;
1121 const bgp_size_t length = args->length;
1123 /* If any recognized attribute has Attribute Length that conflicts
1124 with the expected length (based on the attribute type code), then
1125 the Error Subcode is set to Attribute Length Error. The Data
1126 field contains the erroneous attribute (type, length and
1130 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1132 return bgp_attr_malformed (args,
1133 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1137 /* Fetch origin attribute. */
1138 attr->origin = stream_getc (BGP_INPUT (peer));
1140 /* If the ORIGIN attribute has an undefined value, then the Error
1141 Subcode is set to Invalid Origin Attribute. The Data field
1142 contains the unrecognized attribute (type, length and value). */
1143 if ((attr->origin != BGP_ORIGIN_IGP)
1144 && (attr->origin != BGP_ORIGIN_EGP)
1145 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1147 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1149 return bgp_attr_malformed (args,
1150 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1154 /* Set oring attribute flag. */
1155 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1160 /* Parse AS path information. This function is wrapper of
1163 bgp_attr_aspath (struct bgp_attr_parser_args *args)
1165 struct attr *const attr = args->attr;
1166 struct peer *const peer = args->peer;
1167 const bgp_size_t length = args->length;
1170 * peer with AS4 => will get 4Byte ASnums
1171 * otherwise, will get 16 Bit
1173 attr->aspath = aspath_parse (peer->ibuf, length,
1174 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1176 /* In case of IBGP, length will be zero. */
1179 zlog (peer->log, LOG_ERR,
1180 "Malformed AS path from %s, length is %d",
1181 peer->host, length);
1182 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
1185 /* Set aspath attribute flag. */
1186 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
1188 return BGP_ATTR_PARSE_PROCEED;
1191 static bgp_attr_parse_ret_t
1192 bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
1194 /* These checks were part of bgp_attr_aspath, but with
1195 * as4 we should to check aspath things when
1196 * aspath synthesizing with as4_path has already taken place.
1197 * Otherwise we check ASPATH and use the synthesized thing, and that is
1199 * So do the checks later, i.e. here
1201 struct bgp *bgp = peer->bgp;
1202 struct aspath *aspath;
1204 /* Confederation sanity check. */
1205 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1206 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
1208 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
1209 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1210 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1211 return BGP_ATTR_PARSE_ERROR;
1214 /* First AS check for EBGP. */
1215 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1217 if (peer->sort == BGP_PEER_EBGP
1218 && ! aspath_firstas_check (attr->aspath, peer->as))
1220 zlog (peer->log, LOG_ERR,
1221 "%s incorrect first AS (must be %u)", peer->host, peer->as);
1222 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1223 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1224 return BGP_ATTR_PARSE_ERROR;
1228 /* local-as prepend */
1229 if (peer->change_local_as &&
1230 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1232 aspath = aspath_dup (attr->aspath);
1233 aspath = aspath_add_seq (aspath, peer->change_local_as);
1234 aspath_unintern (&attr->aspath);
1235 attr->aspath = aspath_intern (aspath);
1238 return BGP_ATTR_PARSE_PROCEED;
1241 /* Parse AS4 path information. This function is another wrapper of
1244 bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
1246 struct peer *const peer = args->peer;
1247 struct attr *const attr = args->attr;
1248 const bgp_size_t length = args->length;
1250 *as4_path = aspath_parse (peer->ibuf, length, 1);
1252 /* In case of IBGP, length will be zero. */
1255 zlog (peer->log, LOG_ERR,
1256 "Malformed AS4 path from %s, length is %d",
1257 peer->host, length);
1258 return bgp_attr_malformed (args,
1259 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1263 /* Set aspath attribute flag. */
1265 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1267 return BGP_ATTR_PARSE_PROCEED;
1270 /* Nexthop attribute. */
1271 static bgp_attr_parse_ret_t
1272 bgp_attr_nexthop (struct bgp_attr_parser_args *args)
1274 struct peer *const peer = args->peer;
1275 struct attr *const attr = args->attr;
1276 const bgp_size_t length = args->length;
1278 in_addr_t nexthop_h, nexthop_n;
1280 /* Check nexthop attribute length. */
1283 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1286 return bgp_attr_malformed (args,
1287 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1291 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1292 attribute must result in a NOTIFICATION message (this is implemented below).
1293 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1294 logged locally (this is implemented somewhere else). The UPDATE message
1295 gets ignored in any of these cases. */
1296 nexthop_n = stream_get_ipv4 (peer->ibuf);
1297 nexthop_h = ntohl (nexthop_n);
1298 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1299 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
1301 char buf[INET_ADDRSTRLEN];
1302 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
1303 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
1304 return bgp_attr_malformed (args,
1305 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
1309 attr->nexthop.s_addr = nexthop_n;
1310 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1312 return BGP_ATTR_PARSE_PROCEED;
1315 /* MED atrribute. */
1316 static bgp_attr_parse_ret_t
1317 bgp_attr_med (struct bgp_attr_parser_args *args)
1319 struct peer *const peer = args->peer;
1320 struct attr *const attr = args->attr;
1321 const bgp_size_t length = args->length;
1326 zlog (peer->log, LOG_ERR,
1327 "MED attribute length isn't four [%d]", length);
1329 return bgp_attr_malformed (args,
1330 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1334 attr->med = stream_getl (peer->ibuf);
1336 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1338 return BGP_ATTR_PARSE_PROCEED;
1341 /* Local preference attribute. */
1342 static bgp_attr_parse_ret_t
1343 bgp_attr_local_pref (struct bgp_attr_parser_args *args)
1345 struct peer *const peer = args->peer;
1346 struct attr *const attr = args->attr;
1347 const bgp_size_t length = args->length;
1352 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1354 return bgp_attr_malformed (args,
1355 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1359 /* If it is contained in an UPDATE message that is received from an
1360 external peer, then this attribute MUST be ignored by the
1361 receiving speaker. */
1362 if (peer->sort == BGP_PEER_EBGP)
1364 stream_forward_getp (peer->ibuf, length);
1365 return BGP_ATTR_PARSE_PROCEED;
1368 attr->local_pref = stream_getl (peer->ibuf);
1370 /* Set atomic aggregate flag. */
1371 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1373 return BGP_ATTR_PARSE_PROCEED;
1376 /* Atomic aggregate. */
1378 bgp_attr_atomic (struct bgp_attr_parser_args *args)
1380 struct peer *const peer = args->peer;
1381 struct attr *const attr = args->attr;
1382 const bgp_size_t length = args->length;
1387 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1389 return bgp_attr_malformed (args,
1390 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1394 /* Set atomic aggregate flag. */
1395 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1397 return BGP_ATTR_PARSE_PROCEED;
1400 /* Aggregator attribute */
1402 bgp_attr_aggregator (struct bgp_attr_parser_args *args)
1404 struct peer *const peer = args->peer;
1405 struct attr *const attr = args->attr;
1406 const bgp_size_t length = args->length;
1409 struct attr_extra *attre = bgp_attr_extra_get (attr);
1411 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1412 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1415 if (length != wantedlen)
1417 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1419 return bgp_attr_malformed (args,
1420 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1424 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1425 attre->aggregator_as = stream_getl (peer->ibuf);
1427 attre->aggregator_as = stream_getw (peer->ibuf);
1428 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
1430 /* Set atomic aggregate flag. */
1431 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1433 return BGP_ATTR_PARSE_PROCEED;
1436 /* New Aggregator attribute */
1437 static bgp_attr_parse_ret_t
1438 bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1439 as_t *as4_aggregator_as,
1440 struct in_addr *as4_aggregator_addr)
1442 struct peer *const peer = args->peer;
1443 struct attr *const attr = args->attr;
1444 const bgp_size_t length = args->length;
1448 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1450 return bgp_attr_malformed (args,
1451 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1455 *as4_aggregator_as = stream_getl (peer->ibuf);
1456 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1458 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1460 return BGP_ATTR_PARSE_PROCEED;
1463 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1465 static bgp_attr_parse_ret_t
1466 bgp_attr_munge_as4_attrs (struct peer *const peer,
1467 struct attr *const attr,
1468 struct aspath *as4_path, as_t as4_aggregator,
1469 struct in_addr *as4_aggregator_addr)
1471 int ignore_as4_path = 0;
1472 struct aspath *newpath;
1473 struct attr_extra *attre = attr->extra;
1477 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1478 * checked that all well-known, mandatory attributes were present.
1480 * Can only be a problem with peer itself - hard error
1482 return BGP_ATTR_PARSE_ERROR;
1485 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1487 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1489 * It is worth a warning though, because the peer really
1490 * should not send them
1492 if (BGP_DEBUG(as4, AS4))
1494 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1495 zlog_debug ("[AS4] %s %s AS4_PATH",
1496 peer->host, "AS4 capable peer, yet it sent");
1498 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1499 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1500 peer->host, "AS4 capable peer, yet it sent");
1503 return BGP_ATTR_PARSE_PROCEED;
1506 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1507 * because that may override AS4_PATH
1509 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1511 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
1516 * if the as_number in aggregator is not AS_TRANS,
1517 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1518 * and the Aggregator shall be taken as
1519 * info on the aggregating node, and the AS_PATH
1520 * shall be taken as the AS_PATH
1522 * the Aggregator shall be ignored and the
1523 * AS4_AGGREGATOR shall be taken as the
1524 * Aggregating node and the AS_PATH is to be
1525 * constructed "as in all other cases"
1527 if (attre->aggregator_as != BGP_AS_TRANS)
1530 if ( BGP_DEBUG(as4, AS4))
1531 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1532 " send AGGREGATOR != AS_TRANS and"
1533 " AS4_AGGREGATOR, so ignore"
1534 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1535 ignore_as4_path = 1;
1539 /* "New_aggregator shall be taken as aggregator" */
1540 attre->aggregator_as = as4_aggregator;
1541 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1546 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1547 * That is bogus - but reading the conditions
1548 * we have to handle AS4_AGGREGATOR as if it were
1549 * AGGREGATOR in that case
1551 if ( BGP_DEBUG(as4, AS4))
1552 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1553 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1554 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
1555 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
1556 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1557 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1561 /* need to reconcile NEW_AS_PATH and AS_PATH */
1562 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
1564 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1565 aspath_unintern (&attr->aspath);
1566 attr->aspath = aspath_intern (newpath);
1568 return BGP_ATTR_PARSE_PROCEED;
1571 /* Community attribute. */
1572 static bgp_attr_parse_ret_t
1573 bgp_attr_community (struct bgp_attr_parser_args *args)
1575 struct peer *const peer = args->peer;
1576 struct attr *const attr = args->attr;
1577 const bgp_size_t length = args->length;
1581 attr->community = NULL;
1582 return BGP_ATTR_PARSE_PROCEED;
1586 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1588 /* XXX: fix community_parse to use stream API and remove this */
1589 stream_forward_getp (peer->ibuf, length);
1591 if (!attr->community)
1592 return bgp_attr_malformed (args,
1593 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1596 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1598 return BGP_ATTR_PARSE_PROCEED;
1601 /* Originator ID attribute. */
1602 static bgp_attr_parse_ret_t
1603 bgp_attr_originator_id (struct bgp_attr_parser_args *args)
1605 struct peer *const peer = args->peer;
1606 struct attr *const attr = args->attr;
1607 const bgp_size_t length = args->length;
1612 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1614 return bgp_attr_malformed (args,
1615 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1619 (bgp_attr_extra_get (attr))->originator_id.s_addr
1620 = stream_get_ipv4 (peer->ibuf);
1622 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1624 return BGP_ATTR_PARSE_PROCEED;
1627 /* Cluster list attribute. */
1628 static bgp_attr_parse_ret_t
1629 bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
1631 struct peer *const peer = args->peer;
1632 struct attr *const attr = args->attr;
1633 const bgp_size_t length = args->length;
1638 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1640 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1644 (bgp_attr_extra_get (attr))->cluster
1645 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
1647 /* XXX: Fix cluster_parse to use stream API and then remove this */
1648 stream_forward_getp (peer->ibuf, length);
1650 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1652 return BGP_ATTR_PARSE_PROCEED;
1655 /* Multiprotocol reachability information parse. */
1657 bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1658 struct bgp_nlri *mp_update)
1662 bgp_size_t nlri_len;
1665 struct peer *const peer = args->peer;
1666 struct attr *const attr = args->attr;
1667 const bgp_size_t length = args->length;
1668 struct attr_extra *attre = bgp_attr_extra_get(attr);
1670 /* Set end of packet. */
1671 s = BGP_INPUT(peer);
1672 start = stream_get_getp(s);
1674 /* safe to read statically sized header? */
1675 #define BGP_MP_REACH_MIN_SIZE 5
1676 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1677 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
1679 zlog_info ("%s: %s sent invalid length, %lu",
1680 __func__, peer->host, (unsigned long)length);
1681 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1684 /* Load AFI, SAFI. */
1685 afi = stream_getw (s);
1686 safi = stream_getc (s);
1688 /* Get nexthop length. */
1689 attre->mp_nexthop_len = stream_getc (s);
1691 if (LEN_LEFT < attre->mp_nexthop_len)
1693 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1694 __func__, peer->host, attre->mp_nexthop_len);
1695 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1698 /* Nexthop length check. */
1699 switch (attre->mp_nexthop_len)
1702 stream_get (&attre->mp_nexthop_global_in, s, 4);
1703 /* Probably needed for RFC 2283 */
1704 if (attr->nexthop.s_addr == 0)
1705 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
1708 stream_getl (s); /* RD high */
1709 stream_getl (s); /* RD low */
1710 stream_get (&attre->mp_nexthop_global_in, s, 4);
1714 u_int32_t rd_high __attribute__((unused));
1715 u_int32_t rd_low __attribute__((unused));
1717 rd_high = stream_getl (s);
1718 rd_low = stream_getl (s);
1722 stream_get (&attre->mp_nexthop_global, s, 16);
1726 if (attre->mp_nexthop_len == 48) {
1727 u_int32_t rd_high __attribute__((unused));
1728 u_int32_t rd_low __attribute__((unused));
1730 rd_high = stream_getl (s);
1731 rd_low = stream_getl (s);
1733 stream_get (&attre->mp_nexthop_global, s, 16);
1735 if (attre->mp_nexthop_len == 48) {
1736 u_int32_t rd_high __attribute__((unused));
1737 u_int32_t rd_low __attribute__((unused));
1739 rd_high = stream_getl (s);
1740 rd_low = stream_getl (s);
1742 stream_get (&attre->mp_nexthop_local, s, 16);
1743 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
1745 char buf1[INET6_ADDRSTRLEN];
1746 char buf2[INET6_ADDRSTRLEN];
1748 if (BGP_DEBUG (update, UPDATE_IN))
1749 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
1750 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
1751 buf1, INET6_ADDRSTRLEN),
1752 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
1753 buf2, INET6_ADDRSTRLEN));
1755 attre->mp_nexthop_len = 16;
1759 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1760 __func__, peer->host, attre->mp_nexthop_len);
1761 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1766 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1767 __func__, peer->host);
1768 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1773 if ((val = stream_getc (s)))
1774 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1778 /* must have nrli_len, what is left of the attribute */
1779 nlri_len = LEN_LEFT;
1780 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
1782 zlog_info ("%s: (%s) Failed to read NLRI",
1783 __func__, peer->host);
1784 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1787 mp_update->afi = afi;
1788 mp_update->safi = safi;
1789 mp_update->nlri = stream_pnt (s);
1790 mp_update->length = nlri_len;
1792 stream_forward_getp (s, nlri_len);
1794 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1796 return BGP_ATTR_PARSE_PROCEED;
1800 /* Multiprotocol unreachable parse */
1802 bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
1803 struct bgp_nlri *mp_withdraw)
1808 u_int16_t withdraw_len;
1809 struct peer *const peer = args->peer;
1810 struct attr *const attr = args->attr;
1811 const bgp_size_t length = args->length;
1815 #define BGP_MP_UNREACH_MIN_SIZE 3
1816 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
1817 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1819 afi = stream_getw (s);
1820 safi = stream_getc (s);
1822 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
1824 mp_withdraw->afi = afi;
1825 mp_withdraw->safi = safi;
1826 mp_withdraw->nlri = stream_pnt (s);
1827 mp_withdraw->length = withdraw_len;
1829 stream_forward_getp (s, withdraw_len);
1831 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1833 return BGP_ATTR_PARSE_PROCEED;
1836 /* Large Community attribute. */
1837 static bgp_attr_parse_ret_t
1838 bgp_attr_large_community (struct bgp_attr_parser_args *args)
1840 struct peer *const peer = args->peer;
1841 struct attr *const attr = args->attr;
1842 const bgp_size_t length = args->length;
1847 attr->extra->lcommunity = NULL;
1848 /* Empty extcomm doesn't seem to be invalid per se */
1849 return BGP_ATTR_PARSE_PROCEED;
1852 (bgp_attr_extra_get (attr))->lcommunity =
1853 lcommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1854 /* XXX: fix ecommunity_parse to use stream API */
1855 stream_forward_getp (peer->ibuf, length);
1857 if (attr->extra && !attr->extra->lcommunity)
1858 return bgp_attr_malformed (args,
1859 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1862 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
1864 return BGP_ATTR_PARSE_PROCEED;
1867 /* Extended Community attribute. */
1868 static bgp_attr_parse_ret_t
1869 bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
1871 struct peer *const peer = args->peer;
1872 struct attr *const attr = args->attr;
1873 const bgp_size_t length = args->length;
1878 attr->extra->ecommunity = NULL;
1879 /* Empty extcomm doesn't seem to be invalid per se */
1880 return BGP_ATTR_PARSE_PROCEED;
1883 (bgp_attr_extra_get (attr))->ecommunity =
1884 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1885 /* XXX: fix ecommunity_parse to use stream API */
1886 stream_forward_getp (peer->ibuf, length);
1888 if (attr->extra && !attr->extra->ecommunity)
1889 return bgp_attr_malformed (args,
1890 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1893 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1895 return BGP_ATTR_PARSE_PROCEED;
1898 /* Parse Tunnel Encap attribute in an UPDATE */
1902 struct peer *peer, /* IN */
1903 bgp_size_t length, /* IN: attr's length field */
1904 struct attr *attr, /* IN: caller already allocated */
1905 u_char flag, /* IN: attr's flags field */
1909 struct attr_extra *attre = NULL;
1910 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1911 uint16_t tunneltype;
1913 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1915 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1916 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1918 zlog (peer->log, LOG_ERR,
1919 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1920 bgp_notify_send_with_data (peer,
1921 BGP_NOTIFY_UPDATE_ERR,
1922 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1927 if (BGP_ATTR_ENCAP == type) {
1928 /* read outer TLV type and length */
1929 uint16_t tlv_length;
1932 zlog (peer->log, LOG_ERR,
1933 "Tunnel Encap attribute not long enough to contain outer T,L");
1934 bgp_notify_send_with_data(peer,
1935 BGP_NOTIFY_UPDATE_ERR,
1936 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1940 tunneltype = stream_getw (BGP_INPUT (peer));
1941 tlv_length = stream_getw (BGP_INPUT (peer));
1944 if (tlv_length != length) {
1945 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1946 __func__, tlv_length, length);
1950 while (length >= 4) {
1951 uint16_t subtype = 0;
1952 uint16_t sublength = 0;
1953 struct bgp_attr_encap_subtlv *tlv;
1955 if (BGP_ATTR_ENCAP == type) {
1956 subtype = stream_getc (BGP_INPUT (peer));
1957 sublength = stream_getc (BGP_INPUT (peer));
1961 if (sublength > length) {
1962 zlog (peer->log, LOG_ERR,
1963 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1965 bgp_notify_send_with_data (peer,
1966 BGP_NOTIFY_UPDATE_ERR,
1967 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1972 /* alloc and copy sub-tlv */
1973 /* TBD make sure these are freed when attributes are released */
1974 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1975 tlv->type = subtype;
1976 tlv->length = sublength;
1977 stream_get(tlv->value, peer->ibuf, sublength);
1978 length -= sublength;
1980 /* attach tlv to encap chain */
1982 attre = bgp_attr_extra_get(attr);
1983 if (BGP_ATTR_ENCAP == type) {
1984 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1985 stlv_last = stlv_last->next);
1987 stlv_last->next = tlv;
1989 attre->encap_subtlvs = tlv;
1993 stlv_last->next = tlv;
1998 if (attre && (BGP_ATTR_ENCAP == type)) {
1999 attre->encap_tunneltype = tunneltype;
2003 /* spurious leftover data */
2004 zlog (peer->log, LOG_ERR,
2005 "Tunnel Encap attribute length is bad: %d leftover octets", length);
2006 bgp_notify_send_with_data (peer,
2007 BGP_NOTIFY_UPDATE_ERR,
2008 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2016 /* BGP unknown attribute treatment. */
2017 static bgp_attr_parse_ret_t
2018 bgp_attr_unknown (struct bgp_attr_parser_args *args)
2020 bgp_size_t total = args->total;
2021 struct transit *transit;
2022 struct attr_extra *attre;
2023 struct peer *const peer = args->peer;
2024 struct attr *const attr = args->attr;
2025 u_char *const startp = args->startp;
2026 const u_char type = args->type;
2027 const u_char flag = args->flags;
2028 const bgp_size_t length = args->length;
2031 if (BGP_DEBUG (normal, NORMAL))
2032 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2033 peer->host, type, length);
2035 if (BGP_DEBUG (events, EVENTS))
2036 zlog (peer->log, LOG_DEBUG,
2037 "Unknown attribute type %d length %d is received", type, length);
2039 /* Forward read pointer of input stream. */
2040 stream_forward_getp (peer->ibuf, length);
2042 /* If any of the mandatory well-known attributes are not recognized,
2043 then the Error Subcode is set to Unrecognized Well-known
2044 Attribute. The Data field contains the unrecognized attribute
2045 (type, length and value). */
2046 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
2048 return bgp_attr_malformed (args,
2049 BGP_NOTIFY_UPDATE_UNREC_ATTR,
2053 /* Unrecognized non-transitive optional attributes must be quietly
2054 ignored and not passed along to other BGP peers. */
2055 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
2056 return BGP_ATTR_PARSE_PROCEED;
2058 /* If a path with recognized transitive optional attribute is
2059 accepted and passed along to other BGP peers and the Partial bit
2060 in the Attribute Flags octet is set to 1 by some previous AS, it
2061 is not set back to 0 by the current AS. */
2062 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
2064 /* Store transitive attribute to the end of attr->transit. */
2065 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
2066 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
2068 transit = attre->transit;
2071 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
2072 transit->length + total);
2074 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2076 memcpy (transit->val + transit->length, startp, total);
2077 transit->length += total;
2079 return BGP_ATTR_PARSE_PROCEED;
2082 /* Well-known attribute check. */
2084 bgp_attr_check (struct peer *peer, struct attr *attr)
2088 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2090 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2091 return BGP_ATTR_PARSE_PROCEED;
2093 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2094 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2095 are present, it should. Check for any other attribute being present
2098 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2099 return BGP_ATTR_PARSE_PROCEED;
2101 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2102 type = BGP_ATTR_ORIGIN;
2104 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2105 type = BGP_ATTR_AS_PATH;
2107 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2108 * NLRI is empty. We can't easily check NLRI empty here though.
2110 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2111 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
2112 type = BGP_ATTR_NEXT_HOP;
2114 if (peer->sort == BGP_PEER_IBGP
2115 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2116 type = BGP_ATTR_LOCAL_PREF;
2120 zlog (peer->log, LOG_WARNING,
2121 "%s Missing well-known attribute %d / %s",
2122 peer->host, type, LOOKUP (attr_str, type));
2123 bgp_notify_send_with_data (peer,
2124 BGP_NOTIFY_UPDATE_ERR,
2125 BGP_NOTIFY_UPDATE_MISS_ATTR,
2127 return BGP_ATTR_PARSE_ERROR;
2129 return BGP_ATTR_PARSE_PROCEED;
2132 /* Read attribute of update packet. This function is called from
2133 bgp_update_receive() in bgp_packet.c. */
2134 bgp_attr_parse_ret_t
2135 bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2136 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2142 u_char *startp, *endp;
2144 u_char seen[BGP_ATTR_BITMAP_SIZE];
2145 /* we need the as4_path only until we have synthesized the as_path with it */
2146 /* same goes for as4_aggregator */
2147 struct aspath *as4_path = NULL;
2148 as_t as4_aggregator = 0;
2149 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
2151 /* Initialize bitmap. */
2152 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2154 /* End pointer of BGP attribute. */
2155 assert (size <= stream_get_size (BGP_INPUT (peer)));
2156 assert (size <= stream_get_endp (BGP_INPUT (peer)));
2157 endp = BGP_INPUT_PNT (peer) + size;
2159 /* Get attributes to the end of attribute length. */
2160 while (BGP_INPUT_PNT (peer) < endp)
2162 /* Check remaining length check.*/
2163 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2165 /* XXX warning: long int format, int arg (arg 5) */
2166 zlog (peer->log, LOG_WARNING,
2167 "%s: error BGP attribute length %lu is smaller than min len",
2169 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2171 bgp_notify_send (peer,
2172 BGP_NOTIFY_UPDATE_ERR,
2173 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2174 return BGP_ATTR_PARSE_ERROR;
2177 /* Fetch attribute flag and type. */
2178 startp = BGP_INPUT_PNT (peer);
2179 /* "The lower-order four bits of the Attribute Flags octet are
2180 unused. They MUST be zero when sent and MUST be ignored when
2182 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
2183 type = stream_getc (BGP_INPUT (peer));
2185 /* Check whether Extended-Length applies and is in bounds */
2186 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2187 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2189 zlog (peer->log, LOG_WARNING,
2190 "%s: Extended length set, but just %lu bytes of attr header",
2192 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2194 bgp_notify_send (peer,
2195 BGP_NOTIFY_UPDATE_ERR,
2196 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2197 return BGP_ATTR_PARSE_ERROR;
2200 /* Check extended attribue length bit. */
2201 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2202 length = stream_getw (BGP_INPUT (peer));
2204 length = stream_getc (BGP_INPUT (peer));
2206 /* If any attribute appears more than once in the UPDATE
2207 message, then the Error Subcode is set to Malformed Attribute
2210 if (CHECK_BITMAP (seen, type))
2212 zlog (peer->log, LOG_WARNING,
2213 "%s: error BGP attribute type %d appears twice in a message",
2216 bgp_notify_send (peer,
2217 BGP_NOTIFY_UPDATE_ERR,
2218 BGP_NOTIFY_UPDATE_MAL_ATTR);
2219 return BGP_ATTR_PARSE_ERROR;
2222 /* Set type to bitmap to check duplicate attribute. `type' is
2223 unsigned char so it never overflow bitmap range. */
2225 SET_BITMAP (seen, type);
2227 /* Overflow check. */
2228 attr_endp = BGP_INPUT_PNT (peer) + length;
2230 if (attr_endp > endp)
2232 zlog (peer->log, LOG_WARNING,
2233 "%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);
2234 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);
2235 bgp_notify_send_with_data (peer,
2236 BGP_NOTIFY_UPDATE_ERR,
2237 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2238 startp, endp - startp);
2239 return BGP_ATTR_PARSE_ERROR;
2242 struct bgp_attr_parser_args attr_args = {
2249 .total = attr_endp - startp,
2253 /* If any recognized attribute has Attribute Flags that conflict
2254 with the Attribute Type Code, then the Error Subcode is set to
2255 Attribute Flags Error. The Data field contains the erroneous
2256 attribute (type, length and value). */
2257 if (bgp_attr_flag_invalid (&attr_args))
2259 bgp_attr_parse_ret_t ret;
2260 ret = bgp_attr_malformed (&attr_args,
2261 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2263 if (ret == BGP_ATTR_PARSE_PROCEED)
2268 /* OK check attribute and store it's value. */
2271 case BGP_ATTR_ORIGIN:
2272 ret = bgp_attr_origin (&attr_args);
2274 case BGP_ATTR_AS_PATH:
2275 ret = bgp_attr_aspath (&attr_args);
2277 case BGP_ATTR_AS4_PATH:
2278 ret = bgp_attr_as4_path (&attr_args, &as4_path);
2280 case BGP_ATTR_NEXT_HOP:
2281 ret = bgp_attr_nexthop (&attr_args);
2283 case BGP_ATTR_MULTI_EXIT_DISC:
2284 ret = bgp_attr_med (&attr_args);
2286 case BGP_ATTR_LOCAL_PREF:
2287 ret = bgp_attr_local_pref (&attr_args);
2289 case BGP_ATTR_ATOMIC_AGGREGATE:
2290 ret = bgp_attr_atomic (&attr_args);
2292 case BGP_ATTR_AGGREGATOR:
2293 ret = bgp_attr_aggregator (&attr_args);
2295 case BGP_ATTR_AS4_AGGREGATOR:
2296 ret = bgp_attr_as4_aggregator (&attr_args,
2298 &as4_aggregator_addr);
2300 case BGP_ATTR_COMMUNITIES:
2301 ret = bgp_attr_community (&attr_args);
2303 case BGP_ATTR_LARGE_COMMUNITIES:
2304 ret = bgp_attr_large_community (&attr_args);
2306 case BGP_ATTR_ORIGINATOR_ID:
2307 ret = bgp_attr_originator_id (&attr_args);
2309 case BGP_ATTR_CLUSTER_LIST:
2310 ret = bgp_attr_cluster_list (&attr_args);
2312 case BGP_ATTR_MP_REACH_NLRI:
2313 ret = bgp_mp_reach_parse (&attr_args, mp_update);
2315 case BGP_ATTR_MP_UNREACH_NLRI:
2316 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
2318 case BGP_ATTR_EXT_COMMUNITIES:
2319 ret = bgp_attr_ext_communities (&attr_args);
2321 case BGP_ATTR_ENCAP:
2322 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2325 ret = bgp_attr_unknown (&attr_args);
2329 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2331 bgp_notify_send (peer,
2332 BGP_NOTIFY_UPDATE_ERR,
2333 BGP_NOTIFY_UPDATE_MAL_ATTR);
2334 ret = BGP_ATTR_PARSE_ERROR;
2337 /* If hard error occurred immediately return to the caller. */
2338 if (ret == BGP_ATTR_PARSE_ERROR)
2340 zlog (peer->log, LOG_WARNING,
2341 "%s: Attribute %s, parse error",
2343 LOOKUP (attr_str, type));
2345 aspath_unintern (&as4_path);
2348 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2351 zlog (peer->log, LOG_WARNING,
2352 "%s: Attribute %s, parse error - treating as withdrawal",
2354 LOOKUP (attr_str, type));
2356 aspath_unintern (&as4_path);
2360 /* Check the fetched length. */
2361 if (BGP_INPUT_PNT (peer) != attr_endp)
2363 zlog (peer->log, LOG_WARNING,
2364 "%s: BGP attribute %s, fetch error",
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 final read pointer is same as end pointer. */
2375 if (BGP_INPUT_PNT (peer) != endp)
2377 zlog (peer->log, LOG_WARNING,
2378 "%s: BGP attribute %s, length mismatch",
2379 peer->host, LOOKUP (attr_str, type));
2380 bgp_notify_send (peer,
2381 BGP_NOTIFY_UPDATE_ERR,
2382 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2384 aspath_unintern (&as4_path);
2385 return BGP_ATTR_PARSE_ERROR;
2388 /* Check all mandatory well-known attributes are present */
2390 bgp_attr_parse_ret_t ret;
2391 if ((ret = bgp_attr_check (peer, attr)) < 0)
2394 aspath_unintern (&as4_path);
2400 * At this place we can see whether we got AS4_PATH and/or
2401 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2402 * We can not do this before we've read all attributes because
2403 * the as4 handling does not say whether AS4_PATH has to be sent
2404 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2405 * in relationship to AGGREGATOR.
2406 * So, to be defensive, we are not relying on any order and read
2407 * all attributes first, including these 32bit ones, and now,
2408 * afterwards, we look what and if something is to be done for as4.
2410 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2413 /* actually... this doesn't ever return failure currently, but
2414 * better safe than sorry */
2415 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2416 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
2417 as4_aggregator, &as4_aggregator_addr))
2419 bgp_notify_send (peer,
2420 BGP_NOTIFY_UPDATE_ERR,
2421 BGP_NOTIFY_UPDATE_MAL_ATTR);
2423 aspath_unintern (&as4_path);
2424 return BGP_ATTR_PARSE_ERROR;
2427 /* At this stage, we have done all fiddling with as4, and the
2428 * resulting info is in attr->aggregator resp. attr->aspath
2429 * so we can chuck as4_aggregator and as4_path alltogether in
2430 * order to save memory
2434 aspath_unintern (&as4_path); /* unintern - it is in the hash */
2435 /* The flag that we got this is still there, but that does not
2440 * The "rest" of the code does nothing with as4_aggregator.
2441 * there is no memory attached specifically which is not part
2443 * so ignoring just means do nothing.
2446 * Finally do the checks on the aspath we did not do yet
2447 * because we waited for a potentially synthesized aspath.
2449 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
2451 ret = bgp_attr_aspath_check (peer, attr);
2452 if (ret != BGP_ATTR_PARSE_PROCEED)
2456 /* Finally intern unknown attribute. */
2457 if (attr->extra && attr->extra->transit)
2458 attr->extra->transit = transit_intern (attr->extra->transit);
2460 return BGP_ATTR_PARSE_PROCEED;
2463 int stream_put_prefix (struct stream *, struct prefix *);
2466 bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2471 /* Set extended bit always to encode the attribute length as 2 bytes */
2472 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2473 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2474 sizep = stream_get_endp (s);
2475 stream_putw (s, 0); /* Marker: Attribute length. */
2477 stream_putw (s, afi);
2478 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
2486 case SAFI_MULTICAST:
2488 stream_put_ipv4 (s, attr->nexthop.s_addr);
2491 stream_putc (s, 12);
2492 stream_putl (s, 0); /* RD = 0, per RFC */
2494 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2498 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2500 case SAFI_UNICAST: /* invalid for IPv4 */
2509 case SAFI_MULTICAST:
2511 struct attr_extra *attre = attr->extra;
2513 assert (attr->extra);
2514 stream_putc (s, attre->mp_nexthop_len);
2515 stream_put (s, &attre->mp_nexthop_global, 16);
2516 if (attre->mp_nexthop_len == 32)
2517 stream_put (s, &attre->mp_nexthop_local, 16);
2522 struct attr_extra *attre = attr->extra;
2524 assert (attr->extra);
2525 if (attre->mp_nexthop_len == 16) {
2526 stream_putc (s, 24);
2527 stream_putl (s, 0); /* RD = 0, per RFC */
2529 stream_put (s, &attre->mp_nexthop_global, 16);
2530 } else if (attre->mp_nexthop_len == 32) {
2531 stream_putc (s, 48);
2532 stream_putl (s, 0); /* RD = 0, per RFC */
2534 stream_put (s, &attre->mp_nexthop_global, 16);
2535 stream_putl (s, 0); /* RD = 0, per RFC */
2537 stream_put (s, &attre->mp_nexthop_local, 16);
2542 assert (attr->extra);
2543 stream_putc (s, 16);
2544 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2560 bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2561 struct prefix *p, struct prefix_rd *prd,
2564 if (safi == SAFI_MPLS_VPN)
2566 /* Tag, RD, Prefix write. */
2567 stream_putc (s, p->prefixlen + 88);
2568 stream_put (s, tag, 3);
2569 stream_put (s, prd->val, 8);
2570 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2573 stream_put_prefix (s, p);
2577 bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2579 int size = PSIZE (p->prefixlen);
2580 if (safi == SAFI_MPLS_VPN)
2586 * Encodes the tunnel encapsulation attribute
2589 bgp_packet_mpattr_tea(
2596 unsigned int attrlenfield = 0;
2597 unsigned int attrhdrlen = 0;
2598 struct bgp_attr_encap_subtlv *subtlvs;
2599 struct bgp_attr_encap_subtlv *st;
2600 const char *attrname;
2602 if (!attr || !attr->extra)
2606 case BGP_ATTR_ENCAP:
2607 attrname = "Tunnel Encap";
2608 subtlvs = attr->extra->encap_subtlvs;
2611 * The tunnel encap attr has an "outer" tlv.
2613 * L = total length of subtlvs,
2614 * V = concatenated subtlvs.
2616 attrlenfield = 2 + 2; /* T + L */
2617 attrhdrlen = 1 + 1; /* subTLV T + L */
2625 /* if no tlvs, don't make attr */
2626 if (subtlvs == NULL)
2629 /* compute attr length */
2630 for (st = subtlvs; st; st = st->next) {
2631 attrlenfield += (attrhdrlen + st->length);
2634 if (attrlenfield > 0xffff) {
2635 zlog (peer->log, LOG_ERR,
2636 "%s attribute is too long (length=%d), can't send it",
2642 if (attrlenfield > 0xff) {
2643 /* 2-octet length field */
2645 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2646 stream_putc (s, attrtype);
2647 stream_putw (s, attrlenfield & 0xffff);
2649 /* 1-octet length field */
2650 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2651 stream_putc (s, attrtype);
2652 stream_putc (s, attrlenfield & 0xff);
2655 if (attrtype == BGP_ATTR_ENCAP) {
2656 /* write outer T+L */
2657 stream_putw(s, attr->extra->encap_tunneltype);
2658 stream_putw(s, attrlenfield - 4);
2661 /* write each sub-tlv */
2662 for (st = subtlvs; st; st = st->next) {
2663 if (attrtype == BGP_ATTR_ENCAP) {
2664 stream_putc (s, st->type);
2665 stream_putc (s, st->length);
2667 stream_put (s, st->value, st->length);
2672 bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2674 /* Set MP attribute length. Don't count the (2) bytes used to encode
2676 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2679 /* Make attribute packet. */
2681 bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
2682 struct stream *s, struct attr *attr,
2683 struct prefix *p, afi_t afi, safi_t safi,
2684 struct peer *from, struct prefix_rd *prd, u_char *tag)
2687 size_t aspath_sizep;
2688 struct aspath *aspath;
2689 int send_as4_path = 0;
2690 int send_as4_aggregator = 0;
2691 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
2694 bgp = bgp_get_default ();
2696 /* Remember current pointer. */
2697 cp = stream_get_endp (s);
2699 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2701 size_t mpattrlen_pos = 0;
2702 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2703 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2704 bgp_packet_mpattr_end(s, mpattrlen_pos);
2707 /* Origin attribute. */
2708 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2709 stream_putc (s, BGP_ATTR_ORIGIN);
2711 stream_putc (s, attr->origin);
2713 /* AS path attribute. */
2715 /* If remote-peer is EBGP */
2716 if (peer->sort == BGP_PEER_EBGP
2717 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
2718 || attr->aspath->segments == NULL)
2719 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
2721 aspath = aspath_dup (attr->aspath);
2723 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2725 /* Strip the confed info, and then stuff our path CONFED_ID
2727 aspath = aspath_delete_confed_seq (aspath);
2728 aspath = aspath_add_seq (aspath, bgp->confed_id);
2732 if (peer->change_local_as) {
2733 /* If replace-as is specified, we only use the change_local_as when
2734 advertising routes. */
2735 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2736 aspath = aspath_add_seq (aspath, peer->local_as);
2738 aspath = aspath_add_seq (aspath, peer->change_local_as);
2740 aspath = aspath_add_seq (aspath, peer->local_as);
2744 else if (peer->sort == BGP_PEER_CONFED)
2746 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2747 aspath = aspath_dup (attr->aspath);
2748 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2751 aspath = attr->aspath;
2753 /* If peer is not AS4 capable, then:
2754 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2755 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2756 * types are in it (i.e. exclude them if they are there)
2757 * AND do this only if there is at least one asnum > 65535 in the path!
2758 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2759 * all ASnums > 65535 to BGP_AS_TRANS
2762 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2763 stream_putc (s, BGP_ATTR_AS_PATH);
2764 aspath_sizep = stream_get_endp (s);
2766 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2768 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2771 if (!use32bit && aspath_has_as4 (aspath))
2772 send_as4_path = 1; /* we'll do this later, at the correct place */
2774 /* Nexthop attribute. */
2775 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2776 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
2778 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2779 stream_putc (s, BGP_ATTR_NEXT_HOP);
2781 if (safi == SAFI_MPLS_VPN)
2783 if (attr->nexthop.s_addr == 0)
2784 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2786 stream_put_ipv4 (s, attr->nexthop.s_addr);
2789 stream_put_ipv4 (s, attr->nexthop.s_addr);
2792 /* MED attribute. */
2793 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2795 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2796 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2798 stream_putl (s, attr->med);
2801 /* Local preference. */
2802 if (peer->sort == BGP_PEER_IBGP ||
2803 peer->sort == BGP_PEER_CONFED)
2805 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2806 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2808 stream_putl (s, attr->local_pref);
2811 /* Atomic aggregate. */
2812 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2814 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2815 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2820 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2822 assert (attr->extra);
2824 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
2825 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2826 stream_putc (s, BGP_ATTR_AGGREGATOR);
2830 /* AS4 capable peer */
2832 stream_putl (s, attr->extra->aggregator_as);
2836 /* 2-byte AS peer */
2839 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2840 if ( attr->extra->aggregator_as > 65535 )
2842 stream_putw (s, BGP_AS_TRANS);
2844 /* we have to send AS4_AGGREGATOR, too.
2845 * we'll do that later in order to send attributes in ascending
2848 send_as4_aggregator = 1;
2851 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2853 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2856 /* Community attribute. */
2857 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2858 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2860 if (attr->community->size * 4 > 255)
2862 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2863 stream_putc (s, BGP_ATTR_COMMUNITIES);
2864 stream_putw (s, attr->community->size * 4);
2868 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2869 stream_putc (s, BGP_ATTR_COMMUNITIES);
2870 stream_putc (s, attr->community->size * 4);
2872 stream_put (s, attr->community->val, attr->community->size * 4);
2876 * Large Community attribute.
2879 CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)
2880 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)))
2882 if (attr->extra->lcommunity->size * 12 > 255)
2884 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2885 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
2886 stream_putw (s, attr->extra->lcommunity->size * 12);
2890 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2891 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
2892 stream_putc (s, attr->extra->lcommunity->size * 12);
2894 stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
2897 /* Route Reflector. */
2898 if (peer->sort == BGP_PEER_IBGP
2900 && from->sort == BGP_PEER_IBGP)
2902 /* Originator ID. */
2903 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2904 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2907 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
2908 stream_put_in_addr (s, &attr->extra->originator_id);
2910 stream_put_in_addr (s, &from->remote_id);
2913 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2914 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2916 if (attr->extra && attr->extra->cluster)
2918 stream_putc (s, attr->extra->cluster->length + 4);
2919 /* If this peer configuration's parent BGP has cluster_id. */
2920 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2921 stream_put_in_addr (s, &bgp->cluster_id);
2923 stream_put_in_addr (s, &bgp->router_id);
2924 stream_put (s, attr->extra->cluster->list,
2925 attr->extra->cluster->length);
2930 /* If this peer configuration's parent BGP has cluster_id. */
2931 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2932 stream_put_in_addr (s, &bgp->cluster_id);
2934 stream_put_in_addr (s, &bgp->router_id);
2938 /* Extended Communities attribute. */
2939 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2940 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2942 struct attr_extra *attre = attr->extra;
2946 if (peer->sort == BGP_PEER_IBGP
2947 || peer->sort == BGP_PEER_CONFED)
2949 if (attre->ecommunity->size * 8 > 255)
2951 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2952 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2953 stream_putw (s, attre->ecommunity->size * 8);
2957 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2958 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2959 stream_putc (s, attre->ecommunity->size * 8);
2961 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
2967 int ecom_tr_size = 0;
2970 for (i = 0; i < attre->ecommunity->size; i++)
2972 pnt = attre->ecommunity->val + (i * 8);
2975 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2983 if (ecom_tr_size * 8 > 255)
2985 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2986 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2987 stream_putw (s, ecom_tr_size * 8);
2991 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2992 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2993 stream_putc (s, ecom_tr_size * 8);
2996 for (i = 0; i < attre->ecommunity->size; i++)
2998 pnt = attre->ecommunity->val + (i * 8);
3001 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
3004 stream_put (s, pnt, 8);
3010 if ( send_as4_path )
3012 /* If the peer is NOT As4 capable, AND */
3013 /* there are ASnums > 65535 in path THEN
3014 * give out AS4_PATH */
3016 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3018 * Hm, I wonder... confederation things *should* only be at
3019 * the beginning of an aspath, right? Then we should use
3020 * aspath_delete_confed_seq for this, because it is already
3022 * Folks, talk to me: what is reasonable here!?
3024 aspath = aspath_delete_confed_seq (aspath);
3026 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
3027 stream_putc (s, BGP_ATTR_AS4_PATH);
3028 aspath_sizep = stream_get_endp (s);
3030 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
3033 if (aspath != attr->aspath)
3034 aspath_free (aspath);
3036 if ( send_as4_aggregator )
3038 assert (attr->extra);
3040 /* send AS4_AGGREGATOR, at this place */
3041 /* this section of code moved here in order to ensure the correct
3042 * *ascending* order of attributes
3044 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3045 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
3047 stream_putl (s, attr->extra->aggregator_as);
3048 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
3051 if ((afi == AFI_IP || afi == AFI_IP6) &&
3052 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
3054 /* Tunnel Encap attribute */
3055 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
3058 /* Unknown transit attribute. */
3059 if (attr->extra && attr->extra->transit)
3060 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
3062 /* Return total size of attribute. */
3063 return stream_get_endp (s) - cp;
3067 bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
3069 unsigned long attrlen_pnt;
3071 /* Set extended bit always to encode the attribute length as 2 bytes */
3072 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
3073 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
3075 attrlen_pnt = stream_get_endp (s);
3076 stream_putw (s, 0); /* Length of this attribute. */
3078 stream_putw (s, afi);
3079 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
3084 bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
3085 afi_t afi, safi_t safi, struct prefix_rd *prd,
3088 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
3092 bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
3094 bgp_packet_mpattr_end (s, attrlen_pnt);
3097 /* Initialization of attribute. */
3099 bgp_attr_init (void)
3111 bgp_attr_finish (void)
3115 community_finish ();
3116 ecommunity_finish ();
3117 lcommunity_finish ();
3122 /* Make attribute packet. */
3124 bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3125 struct prefix *prefix)
3130 struct aspath *aspath;
3132 /* Remember current pointer. */
3133 cp = stream_get_endp (s);
3135 /* Place holder of length. */
3138 /* Origin attribute. */
3139 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3140 stream_putc (s, BGP_ATTR_ORIGIN);
3142 stream_putc (s, attr->origin);
3144 aspath = attr->aspath;
3146 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3147 stream_putc (s, BGP_ATTR_AS_PATH);
3148 aspath_lenp = stream_get_endp (s);
3151 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
3153 /* Nexthop attribute. */
3154 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3156 && prefix->family != AF_INET6
3159 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3160 stream_putc (s, BGP_ATTR_NEXT_HOP);
3162 stream_put_ipv4 (s, attr->nexthop.s_addr);
3165 /* MED attribute. */
3166 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3168 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3169 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3171 stream_putl (s, attr->med);
3174 /* Local preference. */
3175 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3177 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3178 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3180 stream_putl (s, attr->local_pref);
3183 /* Atomic aggregate. */
3184 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3186 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3187 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3192 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3194 assert (attr->extra);
3195 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3196 stream_putc (s, BGP_ATTR_AGGREGATOR);
3198 stream_putl (s, attr->extra->aggregator_as);
3199 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
3202 /* Community attribute. */
3203 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3205 if (attr->community->size * 4 > 255)
3207 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3208 stream_putc (s, BGP_ATTR_COMMUNITIES);
3209 stream_putw (s, attr->community->size * 4);
3213 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3214 stream_putc (s, BGP_ATTR_COMMUNITIES);
3215 stream_putc (s, attr->community->size * 4);
3217 stream_put (s, attr->community->val, attr->community->size * 4);
3220 /* Large Community attribute. */
3221 if (attr->extra && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES))
3223 if (attr->extra->lcommunity->size * 12 > 255)
3225 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3226 stream_putc (s, BGP_ATTR_COMMUNITIES);
3227 stream_putw (s, attr->extra->lcommunity->size * 12);
3231 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3232 stream_putc (s, BGP_ATTR_COMMUNITIES);
3233 stream_putc (s, attr->extra->lcommunity->size * 12);
3236 stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
3239 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3240 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3241 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
3244 struct attr_extra *attre = attr->extra;
3246 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3247 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
3248 sizep = stream_get_endp (s);
3251 stream_putc (s, 0); /* Marker: Attribute length. */
3252 stream_putw(s, AFI_IP6); /* AFI */
3253 stream_putc(s, SAFI_UNICAST); /* SAFI */
3256 stream_putc(s, attre->mp_nexthop_len);
3257 stream_put(s, &attre->mp_nexthop_global, 16);
3258 if (attre->mp_nexthop_len == 32)
3259 stream_put(s, &attre->mp_nexthop_local, 16);
3265 stream_put_prefix(s, prefix);
3267 /* Set MP attribute length. */
3268 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
3271 /* Return total size of attribute. */
3272 len = stream_get_endp (s) - cp - 2;
3273 stream_putw_at (s, cp, len);