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
32 #include "bgpd/bgpd.h"
33 #include "bgpd/bgp_attr.h"
34 #include "bgpd/bgp_route.h"
35 #include "bgpd/bgp_aspath.h"
36 #include "bgpd/bgp_community.h"
37 #include "bgpd/bgp_debug.h"
38 #include "bgpd/bgp_packet.h"
39 #include "bgpd/bgp_ecommunity.h"
41 /* Attribute strings for logging. */
42 static struct message attr_str
[] =
44 { BGP_ATTR_ORIGIN
, "ORIGIN" },
45 { BGP_ATTR_AS_PATH
, "AS_PATH" },
46 { BGP_ATTR_NEXT_HOP
, "NEXT_HOP" },
47 { BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC" },
48 { BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF" },
49 { BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE" },
50 { BGP_ATTR_AGGREGATOR
, "AGGREGATOR" },
51 { BGP_ATTR_COMMUNITIES
, "COMMUNITY" },
52 { BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID" },
53 { BGP_ATTR_CLUSTER_LIST
, "CLUSTERLIST" },
54 { BGP_ATTR_DPA
, "DPA" },
55 { BGP_ATTR_ADVERTISER
, "ADVERTISER"} ,
56 { BGP_ATTR_RCID_PATH
, "RCID_PATH" },
57 { BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI" },
58 { BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI" },
59 { BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES" },
60 { BGP_ATTR_AS4_PATH
, "AS4_PATH" },
61 { BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR" },
62 { BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT" },
64 int attr_str_max
= sizeof(attr_str
)/sizeof(attr_str
[0]);
66 struct hash
*cluster_hash
;
69 cluster_hash_alloc (void *p
)
71 struct cluster_list
* val
= (struct cluster_list
*) p
;
72 struct cluster_list
*cluster
;
74 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
75 cluster
->length
= val
->length
;
79 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
80 memcpy (cluster
->list
, val
->list
, val
->length
);
90 /* Cluster list related functions. */
91 static struct cluster_list
*
92 cluster_parse (struct in_addr
* pnt
, int length
)
94 struct cluster_list tmp
;
95 struct cluster_list
*cluster
;
100 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
106 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
110 for (i
= 0; i
< cluster
->length
/ 4; i
++)
111 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
117 cluster_hash_key_make (void *p
)
119 struct cluster_list
* cluster
= (struct cluster_list
*) p
;
120 unsigned int key
= 0;
124 length
= cluster
->length
;
125 pnt
= (caddr_t
) cluster
->list
;
128 key
+= pnt
[--length
];
134 cluster_hash_cmp (const void *p1
, const void *p2
)
136 const struct cluster_list
* cluster1
= p1
;
137 const struct cluster_list
* cluster2
= p2
;
139 return (cluster1
->length
== cluster2
->length
&&
140 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
144 cluster_free (struct cluster_list
*cluster
)
147 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
148 XFREE (MTYPE_CLUSTER
, cluster
);
151 static struct cluster_list
*
152 cluster_dup (struct cluster_list
*cluster
)
154 struct cluster_list
*new;
156 new = XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
157 memset (new, 0, sizeof (struct cluster_list
));
158 new->length
= cluster
->length
;
162 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
163 memcpy (new->list
, cluster
->list
, cluster
->length
);
171 static struct cluster_list
*
172 cluster_intern (struct cluster_list
*cluster
)
174 struct cluster_list
*find
;
176 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
183 cluster_unintern (struct cluster_list
*cluster
)
185 struct cluster_list
*ret
;
190 if (cluster
->refcnt
== 0)
192 ret
= hash_release (cluster_hash
, cluster
);
193 cluster_free (cluster
);
200 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
203 /* Unknown transit attribute. */
204 struct hash
*transit_hash
;
207 transit_free (struct transit
*transit
)
210 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
211 XFREE (MTYPE_TRANSIT
, transit
);
216 transit_hash_alloc (void *p
)
218 /* Transit structure is already allocated. */
222 static struct transit
*
223 transit_intern (struct transit
*transit
)
225 struct transit
*find
;
227 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
229 transit_free (transit
);
236 transit_unintern (struct transit
*transit
)
243 if (transit
->refcnt
== 0)
245 ret
= hash_release (transit_hash
, transit
);
246 transit_free (transit
);
251 transit_hash_key_make (void *p
)
253 struct transit
* transit
= (struct transit
*) p
;
254 unsigned int key
= 0;
258 length
= transit
->length
;
259 pnt
= (caddr_t
) transit
->val
;
262 key
+= pnt
[--length
];
268 transit_hash_cmp (const void *p1
, const void *p2
)
270 const struct transit
* transit1
= p1
;
271 const struct transit
* transit2
= p2
;
273 return (transit1
->length
== transit2
->length
&&
274 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0);
280 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
283 /* Attribute hash routines. */
284 struct hash
*attrhash
;
286 static struct attr_extra
*
287 bgp_attr_extra_new (void)
289 return XCALLOC (MTYPE_ATTR_EXTRA
, sizeof (struct attr_extra
));
293 bgp_attr_extra_free (struct attr
*attr
)
297 XFREE (MTYPE_ATTR_EXTRA
, attr
->extra
);
303 bgp_attr_extra_get (struct attr
*attr
)
306 attr
->extra
= bgp_attr_extra_new();
310 /* Shallow copy of an attribute
311 * Though, not so shallow that it doesn't copy the contents
312 * of the attr_extra pointed to by 'extra'
315 bgp_attr_dup (struct attr
*new, struct attr
*orig
)
320 new->extra
= bgp_attr_extra_new();
321 *new->extra
= *orig
->extra
;
328 return attrhash
->count
;
332 attr_unknown_count (void)
334 return transit_hash
->count
;
338 attrhash_key_make (void *p
)
340 struct attr
* attr
= (struct attr
*) p
;
341 unsigned int key
= 0;
344 key
+= attr
->nexthop
.s_addr
;
346 key
+= attr
->local_pref
;
347 if (attr
->pathlimit
.as
)
349 key
+= attr
->pathlimit
.ttl
;
350 key
+= attr
->pathlimit
.as
;
355 key
+= attr
->extra
->aggregator_as
;
356 key
+= attr
->extra
->aggregator_addr
.s_addr
;
357 key
+= attr
->extra
->weight
;
358 key
+= attr
->extra
->mp_nexthop_global_in
.s_addr
;
362 key
+= aspath_key_make (attr
->aspath
);
364 key
+= community_hash_make (attr
->community
);
368 if (attr
->extra
->ecommunity
)
369 key
+= ecommunity_hash_make (attr
->extra
->ecommunity
);
370 if (attr
->extra
->cluster
)
371 key
+= cluster_hash_key_make (attr
->extra
->cluster
);
372 if (attr
->extra
->transit
)
373 key
+= transit_hash_key_make (attr
->extra
->transit
);
379 key
+= attr
->extra
->mp_nexthop_len
;
380 for (i
= 0; i
< 16; i
++)
381 key
+= attr
->extra
->mp_nexthop_global
.s6_addr
[i
];
382 for (i
= 0; i
< 16; i
++)
383 key
+= attr
->extra
->mp_nexthop_local
.s6_addr
[i
];
385 #endif /* HAVE_IPV6 */
392 attrhash_cmp (const void *p1
, const void *p2
)
394 const struct attr
* attr1
= p1
;
395 const struct attr
* attr2
= p2
;
397 if (attr1
->flag
== attr2
->flag
398 && attr1
->origin
== attr2
->origin
399 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
400 && attr1
->aspath
== attr2
->aspath
401 && attr1
->community
== attr2
->community
402 && attr1
->med
== attr2
->med
403 && attr1
->local_pref
== attr2
->local_pref
404 && attr1
->pathlimit
.ttl
== attr2
->pathlimit
.ttl
405 && attr1
->pathlimit
.as
== attr2
->pathlimit
.as
)
407 const struct attr_extra
*ae1
= attr1
->extra
;
408 const struct attr_extra
*ae2
= attr2
->extra
;
411 && ae1
->aggregator_as
== ae2
->aggregator_as
412 && ae1
->aggregator_addr
.s_addr
== ae2
->aggregator_addr
.s_addr
413 && ae1
->weight
== ae2
->weight
415 && ae1
->mp_nexthop_len
== ae2
->mp_nexthop_len
416 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_global
, &ae2
->mp_nexthop_global
)
417 && IPV6_ADDR_SAME (&ae1
->mp_nexthop_local
, &ae2
->mp_nexthop_local
)
418 #endif /* HAVE_IPV6 */
419 && IPV4_ADDR_SAME (&ae1
->mp_nexthop_global_in
, &ae2
->mp_nexthop_global_in
)
420 && ae1
->ecommunity
== ae2
->ecommunity
421 && ae1
->cluster
== ae2
->cluster
422 && ae1
->transit
== ae2
->transit
)
426 /* neither attribute has extra attributes, so they're same */
436 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
440 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
442 struct attr
*attr
= backet
->data
;
444 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
445 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
449 attr_show_all (struct vty
*vty
)
451 hash_iterate (attrhash
,
452 (void (*)(struct hash_backet
*, void *))
453 attr_show_all_iterator
,
458 bgp_attr_hash_alloc (void *p
)
460 struct attr
* val
= (struct attr
*) p
;
463 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
467 attr
->extra
= bgp_attr_extra_new ();
468 *attr
->extra
= *val
->extra
;
474 /* Internet argument attribute. */
476 bgp_attr_intern (struct attr
*attr
)
480 /* Intern referenced strucutre. */
483 if (! attr
->aspath
->refcnt
)
484 attr
->aspath
= aspath_intern (attr
->aspath
);
486 attr
->aspath
->refcnt
++;
490 if (! attr
->community
->refcnt
)
491 attr
->community
= community_intern (attr
->community
);
493 attr
->community
->refcnt
++;
497 struct attr_extra
*attre
= attr
->extra
;
499 if (attre
->ecommunity
)
501 if (! attre
->ecommunity
->refcnt
)
502 attre
->ecommunity
= ecommunity_intern (attre
->ecommunity
);
504 attre
->ecommunity
->refcnt
++;
508 if (! attre
->cluster
->refcnt
)
509 attre
->cluster
= cluster_intern (attre
->cluster
);
511 attre
->cluster
->refcnt
++;
515 if (! attre
->transit
->refcnt
)
516 attre
->transit
= transit_intern (attre
->transit
);
518 attre
->transit
->refcnt
++;
522 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
529 /* Make network statement's attribute. */
531 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
533 memset (attr
, 0, sizeof (struct attr
));
534 bgp_attr_extra_get (attr
);
536 attr
->origin
= origin
;
537 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
538 attr
->aspath
= aspath_empty ();
539 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
540 attr
->extra
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
541 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
543 attr
->extra
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
550 /* Make network statement's attribute. */
552 bgp_attr_default_intern (u_char origin
)
556 struct attr_extra
*attre
;
558 memset (&attr
, 0, sizeof (struct attr
));
559 attre
= bgp_attr_extra_get (&attr
);
561 bgp_attr_default_set(&attr
, origin
);
563 new = bgp_attr_intern (&attr
);
564 bgp_attr_extra_free (&attr
);
566 aspath_unintern (new->aspath
);
571 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
572 struct aspath
*aspath
,
573 struct community
*community
, int as_set
)
577 struct attr_extra
*attre
;
579 memset (&attr
, 0, sizeof (struct attr
));
580 attre
= bgp_attr_extra_get (&attr
);
582 /* Origin attribute. */
583 attr
.origin
= origin
;
584 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
586 /* AS path attribute. */
588 attr
.aspath
= aspath_intern (aspath
);
590 attr
.aspath
= aspath_empty ();
591 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
593 /* Next hop attribute. */
594 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
598 attr
.community
= community
;
599 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
602 attre
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
604 attre
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
607 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
608 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
609 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
610 attre
->aggregator_as
= bgp
->confed_id
;
612 attre
->aggregator_as
= bgp
->as
;
613 attre
->aggregator_addr
= bgp
->router_id
;
615 new = bgp_attr_intern (&attr
);
616 bgp_attr_extra_free (&attr
);
618 aspath_unintern (new->aspath
);
622 /* Free bgp attribute and aspath. */
624 bgp_attr_unintern (struct attr
*attr
)
627 struct aspath
*aspath
;
628 struct community
*community
;
629 struct ecommunity
*ecommunity
= NULL
;
630 struct cluster_list
*cluster
= NULL
;
631 struct transit
*transit
= NULL
;
633 /* Decrement attribute reference. */
635 aspath
= attr
->aspath
;
636 community
= attr
->community
;
639 ecommunity
= attr
->extra
->ecommunity
;
640 cluster
= attr
->extra
->cluster
;
641 transit
= attr
->extra
->transit
;
644 /* If reference becomes zero then free attribute object. */
645 if (attr
->refcnt
== 0)
647 ret
= hash_release (attrhash
, attr
);
648 assert (ret
!= NULL
);
649 bgp_attr_extra_free (attr
);
650 XFREE (MTYPE_ATTR
, attr
);
653 /* aspath refcount shoud be decrement. */
655 aspath_unintern (aspath
);
657 community_unintern (community
);
659 ecommunity_unintern (ecommunity
);
661 cluster_unintern (cluster
);
663 transit_unintern (transit
);
667 bgp_attr_flush (struct attr
*attr
)
669 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
670 aspath_free (attr
->aspath
);
671 if (attr
->community
&& ! attr
->community
->refcnt
)
672 community_free (attr
->community
);
675 struct attr_extra
*attre
= attr
->extra
;
676 if (attre
->ecommunity
&& ! attre
->ecommunity
->refcnt
)
677 ecommunity_free (attre
->ecommunity
);
678 if (attre
->cluster
&& ! attre
->cluster
->refcnt
)
679 cluster_free (attre
->cluster
);
680 if (attre
->transit
&& ! attre
->transit
->refcnt
)
681 transit_free (attre
->transit
);
685 /* Parse AS_PATHLIMIT attribute in an UPDATE */
687 bgp_attr_aspathlimit (struct peer
*peer
, bgp_size_t length
,
688 struct attr
*attr
, u_char flag
, u_char
*startp
)
692 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
694 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
695 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
))
697 zlog (peer
->log
, LOG_ERR
,
698 "AS-Pathlimit attribute flag isn't transitive %d", flag
);
699 bgp_notify_send_with_data (peer
,
700 BGP_NOTIFY_UPDATE_ERR
,
701 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
708 zlog (peer
->log
, LOG_ERR
,
709 "AS-Pathlimit length, %u, is not 5", length
);
710 bgp_notify_send_with_data (peer
,
711 BGP_NOTIFY_UPDATE_ERR
,
712 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
717 attr
->pathlimit
.ttl
= stream_getc (BGP_INPUT(peer
));
718 attr
->pathlimit
.as
= stream_getl (BGP_INPUT(peer
));
719 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATHLIMIT
);
722 /* Get origin attribute of the update message. */
724 bgp_attr_origin (struct peer
*peer
, bgp_size_t length
,
725 struct attr
*attr
, u_char flag
, u_char
*startp
)
729 /* total is entire attribute length include Attribute Flags (1),
730 Attribute Type code (1) and Attribute length (1 or 2). */
731 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
733 /* If any recognized attribute has Attribute Flags that conflict
734 with the Attribute Type Code, then the Error Subcode is set to
735 Attribute Flags Error. The Data field contains the erroneous
736 attribute (type, length and value). */
737 if (flag
!= BGP_ATTR_FLAG_TRANS
)
739 zlog (peer
->log
, LOG_ERR
,
740 "Origin attribute flag isn't transitive %d", flag
);
741 bgp_notify_send_with_data (peer
,
742 BGP_NOTIFY_UPDATE_ERR
,
743 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
748 /* If any recognized attribute has Attribute Length that conflicts
749 with the expected length (based on the attribute type code), then
750 the Error Subcode is set to Attribute Length Error. The Data
751 field contains the erroneous attribute (type, length and
755 zlog (peer
->log
, LOG_ERR
, "Origin attribute length is not one %d",
757 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
,
758 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
763 /* Fetch origin attribute. */
764 attr
->origin
= stream_getc (BGP_INPUT (peer
));
766 /* If the ORIGIN attribute has an undefined value, then the Error
767 Subcode is set to Invalid Origin Attribute. The Data field
768 contains the unrecognized attribute (type, length and value). */
769 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
770 && (attr
->origin
!= BGP_ORIGIN_EGP
)
771 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
773 zlog (peer
->log
, LOG_ERR
, "Origin attribute value is invalid %d",
776 bgp_notify_send_with_data (peer
,
777 BGP_NOTIFY_UPDATE_ERR
,
778 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
783 /* Set oring attribute flag. */
784 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
789 /* Parse AS path information. This function is wrapper of
792 bgp_attr_aspath (struct peer
*peer
, bgp_size_t length
,
793 struct attr
*attr
, u_char flag
, u_char
*startp
)
797 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
800 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
)
801 || ! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
803 zlog (peer
->log
, LOG_ERR
,
804 "As-Path attribute flag isn't transitive %d", flag
);
805 bgp_notify_send_with_data (peer
,
806 BGP_NOTIFY_UPDATE_ERR
,
807 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
813 * peer with AS4 => will get 4Byte ASnums
814 * otherwise, will get 16 Bit
816 attr
->aspath
= aspath_parse (peer
->ibuf
, length
,
817 CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
));
819 /* In case of IBGP, length will be zero. */
822 zlog (peer
->log
, LOG_ERR
, "Malformed AS path length is %d", length
);
823 bgp_notify_send (peer
,
824 BGP_NOTIFY_UPDATE_ERR
,
825 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
829 /* Forward pointer. */
830 /* stream_forward_getp (peer->ibuf, length);*/
832 /* Set aspath attribute flag. */
833 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
838 static int bgp_attr_aspath_check( struct peer
*peer
,
841 /* These checks were part of bgp_attr_aspath, but with
842 * as4 we should to check aspath things when
843 * aspath synthesizing with as4_path has already taken place.
844 * Otherwise we check ASPATH and use the synthesized thing, and that is
846 * So do the checks later, i.e. here
848 struct bgp
*bgp
= peer
->bgp
;
849 struct aspath
*aspath
;
853 /* First AS check for EBGP. */
854 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
856 if (peer_sort (peer
) == BGP_PEER_EBGP
857 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
859 zlog (peer
->log
, LOG_ERR
,
860 "%s incorrect first AS (must be %u)", peer
->host
, peer
->as
);
861 bgp_notify_send (peer
,
862 BGP_NOTIFY_UPDATE_ERR
,
863 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
868 /* local-as prepend */
869 if (peer
->change_local_as
&&
870 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
872 aspath
= aspath_dup (attr
->aspath
);
873 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
874 aspath_unintern (attr
->aspath
);
875 attr
->aspath
= aspath_intern (aspath
);
882 /* Parse AS4 path information. This function is another wrapper of
885 bgp_attr_as4_path (struct peer
*peer
, bgp_size_t length
,
886 struct attr
*attr
, struct aspath
**as4_path
)
888 *as4_path
= aspath_parse (peer
->ibuf
, length
, 1);
890 /* Set aspath attribute flag. */
892 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH
);
897 /* Nexthop attribute. */
899 bgp_attr_nexthop (struct peer
*peer
, bgp_size_t length
,
900 struct attr
*attr
, u_char flag
, u_char
*startp
)
904 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
907 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
)
908 || ! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
910 zlog (peer
->log
, LOG_ERR
,
911 "Origin attribute flag isn't transitive %d", flag
);
912 bgp_notify_send_with_data (peer
,
913 BGP_NOTIFY_UPDATE_ERR
,
914 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
919 /* Check nexthop attribute length. */
922 zlog (peer
->log
, LOG_ERR
, "Nexthop attribute length isn't four [%d]",
925 bgp_notify_send_with_data (peer
,
926 BGP_NOTIFY_UPDATE_ERR
,
927 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
932 attr
->nexthop
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
933 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
940 bgp_attr_med (struct peer
*peer
, bgp_size_t length
,
941 struct attr
*attr
, u_char flag
, u_char
*startp
)
945 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
950 zlog (peer
->log
, LOG_ERR
,
951 "MED attribute length isn't four [%d]", length
);
953 bgp_notify_send_with_data (peer
,
954 BGP_NOTIFY_UPDATE_ERR
,
955 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
960 attr
->med
= stream_getl (peer
->ibuf
);
962 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
967 /* Local preference attribute. */
969 bgp_attr_local_pref (struct peer
*peer
, bgp_size_t length
,
970 struct attr
*attr
, u_char flag
)
972 /* If it is contained in an UPDATE message that is received from an
973 external peer, then this attribute MUST be ignored by the
974 receiving speaker. */
975 if (peer_sort (peer
) == BGP_PEER_EBGP
)
977 stream_forward_getp (peer
->ibuf
, length
);
982 attr
->local_pref
= stream_getl (peer
->ibuf
);
984 attr
->local_pref
= 0;
986 /* Set atomic aggregate flag. */
987 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
992 /* Atomic aggregate. */
994 bgp_attr_atomic (struct peer
*peer
, bgp_size_t length
,
995 struct attr
*attr
, u_char flag
)
999 zlog (peer
->log
, LOG_ERR
, "Bad atomic aggregate length %d", length
);
1001 bgp_notify_send (peer
,
1002 BGP_NOTIFY_UPDATE_ERR
,
1003 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1007 /* Set atomic aggregate flag. */
1008 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
1013 /* Aggregator attribute */
1015 bgp_attr_aggregator (struct peer
*peer
, bgp_size_t length
,
1016 struct attr
*attr
, u_char flag
)
1019 struct attr_extra
*attre
= bgp_attr_extra_get (attr
);
1021 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1022 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1025 if (length
!= wantedlen
)
1027 zlog (peer
->log
, LOG_ERR
, "Aggregator length is not %d [%d]", wantedlen
, length
);
1029 bgp_notify_send (peer
,
1030 BGP_NOTIFY_UPDATE_ERR
,
1031 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1035 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1036 attre
->aggregator_as
= stream_getl (peer
->ibuf
);
1038 attre
->aggregator_as
= stream_getw (peer
->ibuf
);
1039 attre
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
1041 /* Set atomic aggregate flag. */
1042 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
1047 /* New Aggregator attribute */
1049 bgp_attr_as4_aggregator (struct peer
*peer
, bgp_size_t length
,
1050 struct attr
*attr
, as_t
*as4_aggregator_as
,
1051 struct in_addr
*as4_aggregator_addr
)
1055 zlog (peer
->log
, LOG_ERR
, "New Aggregator length is not 8 [%d]", length
);
1057 bgp_notify_send (peer
,
1058 BGP_NOTIFY_UPDATE_ERR
,
1059 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1062 *as4_aggregator_as
= stream_getl (peer
->ibuf
);
1063 as4_aggregator_addr
->s_addr
= stream_get_ipv4 (peer
->ibuf
);
1065 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
);
1070 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1073 bgp_attr_munge_as4_attrs (struct peer
*peer
, struct attr
*attr
,
1074 struct aspath
*as4_path
, as_t as4_aggregator
,
1075 struct in_addr
*as4_aggregator_addr
)
1077 int ignore_as4_path
= 0;
1078 struct aspath
*newpath
;
1079 struct attr_extra
*attre
= attr
->extra
;
1081 if ( CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
1083 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1085 * It is worth a warning though, because the peer really
1086 * should not send them
1088 if (BGP_DEBUG(as4
, AS4
))
1090 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1091 zlog_debug ("[AS4] %s %s AS4_PATH",
1092 peer
->host
, "AS4 capable peer, yet it sent");
1094 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1095 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1096 peer
->host
, "AS4 capable peer, yet it sent");
1102 if (attr
->flag
& ( ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))
1103 && !(attr
->flag
& ( ATTR_FLAG_BIT( BGP_ATTR_AS_PATH
))))
1105 /* Hu? This is not supposed to happen at all!
1106 * got as4_path and no aspath,
1107 * This should already
1108 * have been handled by 'well known attributes missing'
1109 * But... yeah, paranoia
1110 * Take this as a "malformed attribute"
1112 zlog (peer
->log
, LOG_ERR
,
1113 "%s BGP not AS4 capable peer sent AS4_PATH but"
1114 " no AS_PATH, cant do anything here", peer
->host
);
1115 bgp_notify_send (peer
,
1116 BGP_NOTIFY_UPDATE_ERR
,
1117 BGP_NOTIFY_UPDATE_MAL_ATTR
);
1121 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1122 * because that may override AS4_PATH
1124 if (attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR
) ) )
1126 if ( attr
->flag
& (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
) ) )
1131 * if the as_number in aggregator is not AS_TRANS,
1132 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1133 * and the Aggregator shall be taken as
1134 * info on the aggregating node, and the AS_PATH
1135 * shall be taken as the AS_PATH
1137 * the Aggregator shall be ignored and the
1138 * AS4_AGGREGATOR shall be taken as the
1139 * Aggregating node and the AS_PATH is to be
1140 * constructed "as in all other cases"
1142 if ( attre
->aggregator_as
!= BGP_AS_TRANS
)
1145 if ( BGP_DEBUG(as4
, AS4
))
1146 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1147 " send AGGREGATOR != AS_TRANS and"
1148 " AS4_AGGREGATOR, so ignore"
1149 " AS4_AGGREGATOR and AS4_PATH", peer
->host
);
1150 ignore_as4_path
= 1;
1154 /* "New_aggregator shall be taken as aggregator" */
1155 attre
->aggregator_as
= as4_aggregator
;
1156 attre
->aggregator_addr
.s_addr
= as4_aggregator_addr
->s_addr
;
1161 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1162 * That is bogus - but reading the conditions
1163 * we have to handle AS4_AGGREGATOR as if it were
1164 * AGGREGATOR in that case
1166 if ( BGP_DEBUG(as4
, AS4
))
1167 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1168 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1169 " it as if AGGREGATOR with AS_TRANS had been there", peer
->host
);
1170 (attre
= bgp_attr_extra_get (attr
))->aggregator_as
= as4_aggregator
;
1171 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1172 attr
->flag
|= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
));
1176 /* need to reconcile NEW_AS_PATH and AS_PATH */
1177 if ( !ignore_as4_path
&& (attr
->flag
& ( ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH
))) )
1179 newpath
= aspath_reconcile_as4 (attr
->aspath
, as4_path
);
1180 aspath_unintern (attr
->aspath
);
1181 attr
->aspath
= aspath_intern (newpath
);
1186 /* Community attribute. */
1188 bgp_attr_community (struct peer
*peer
, bgp_size_t length
,
1189 struct attr
*attr
, u_char flag
)
1193 attr
->community
= NULL
;
1199 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
1200 stream_forward_getp (peer
->ibuf
, length
);
1203 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
1208 /* Originator ID attribute. */
1210 bgp_attr_originator_id (struct peer
*peer
, bgp_size_t length
,
1211 struct attr
*attr
, u_char flag
)
1215 zlog (peer
->log
, LOG_ERR
, "Bad originator ID length %d", length
);
1217 bgp_notify_send (peer
,
1218 BGP_NOTIFY_UPDATE_ERR
,
1219 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1223 (bgp_attr_extra_get (attr
))->originator_id
.s_addr
1224 = stream_get_ipv4 (peer
->ibuf
);
1226 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
1231 /* Cluster list attribute. */
1233 bgp_attr_cluster_list (struct peer
*peer
, bgp_size_t length
,
1234 struct attr
*attr
, u_char flag
)
1239 zlog (peer
->log
, LOG_ERR
, "Bad cluster list length %d", length
);
1241 bgp_notify_send (peer
,
1242 BGP_NOTIFY_UPDATE_ERR
,
1243 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1247 (bgp_attr_extra_get (attr
))->cluster
1248 = cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
), length
);
1250 stream_forward_getp (peer
->ibuf
, length
);;
1252 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
1257 /* Multiprotocol reachability information parse. */
1259 bgp_mp_reach_parse (struct peer
*peer
, bgp_size_t length
, struct attr
*attr
,
1260 struct bgp_nlri
*mp_update
)
1264 bgp_size_t nlri_len
;
1268 struct attr_extra
*attre
= bgp_attr_extra_get(attr
);
1270 /* Set end of packet. */
1271 s
= BGP_INPUT(peer
);
1272 start
= stream_get_getp(s
);
1274 /* safe to read statically sized header? */
1275 #define BGP_MP_REACH_MIN_SIZE 5
1276 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1277 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
))
1279 zlog_info ("%s: %s sent invalid length, %lu",
1280 __func__
, peer
->host
, (unsigned long)length
);
1284 /* Load AFI, SAFI. */
1285 afi
= stream_getw (s
);
1286 safi
= stream_getc (s
);
1288 /* Get nexthop length. */
1289 attre
->mp_nexthop_len
= stream_getc (s
);
1291 if (LEN_LEFT
< attre
->mp_nexthop_len
)
1293 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1294 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1298 /* Nexthop length check. */
1299 switch (attre
->mp_nexthop_len
)
1302 stream_get (&attre
->mp_nexthop_global_in
, s
, 4);
1309 rd_high
= stream_getl (s
);
1310 rd_low
= stream_getl (s
);
1311 stream_get (&attre
->mp_nexthop_global_in
, s
, 4);
1316 stream_get (&attre
->mp_nexthop_global
, s
, 16);
1319 stream_get (&attre
->mp_nexthop_global
, s
, 16);
1320 stream_get (&attre
->mp_nexthop_local
, s
, 16);
1321 if (! IN6_IS_ADDR_LINKLOCAL (&attre
->mp_nexthop_local
))
1323 char buf1
[INET6_ADDRSTRLEN
];
1324 char buf2
[INET6_ADDRSTRLEN
];
1326 if (BGP_DEBUG (update
, UPDATE_IN
))
1327 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer
->host
,
1328 inet_ntop (AF_INET6
, &attre
->mp_nexthop_global
,
1329 buf1
, INET6_ADDRSTRLEN
),
1330 inet_ntop (AF_INET6
, &attre
->mp_nexthop_local
,
1331 buf2
, INET6_ADDRSTRLEN
));
1333 attre
->mp_nexthop_len
= 16;
1336 #endif /* HAVE_IPV6 */
1338 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1339 __func__
, peer
->host
, attre
->mp_nexthop_len
);
1345 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1346 __func__
, peer
->host
);
1352 if ((val
= stream_getc (s
)))
1353 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1357 /* must have nrli_len, what is left of the attribute */
1358 nlri_len
= LEN_LEFT
;
1359 if ((!nlri_len
) || (nlri_len
> STREAM_READABLE(s
)))
1361 zlog_info ("%s: (%s) Failed to read NLRI",
1362 __func__
, peer
->host
);
1366 if (safi
!= BGP_SAFI_VPNV4
)
1368 ret
= bgp_nlri_sanity_check (peer
, afi
, stream_pnt (s
), nlri_len
);
1371 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1372 __func__
, peer
->host
);
1377 mp_update
->afi
= afi
;
1378 mp_update
->safi
= safi
;
1379 mp_update
->nlri
= stream_pnt (s
);
1380 mp_update
->length
= nlri_len
;
1382 stream_forward_getp (s
, nlri_len
);
1388 /* Multiprotocol unreachable parse */
1390 bgp_mp_unreach_parse (struct peer
*peer
, bgp_size_t length
,
1391 struct bgp_nlri
*mp_withdraw
)
1396 u_int16_t withdraw_len
;
1401 #define BGP_MP_UNREACH_MIN_SIZE 3
1402 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1405 afi
= stream_getw (s
);
1406 safi
= stream_getc (s
);
1408 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1410 if (safi
!= BGP_SAFI_VPNV4
)
1412 ret
= bgp_nlri_sanity_check (peer
, afi
, stream_pnt (s
), withdraw_len
);
1417 mp_withdraw
->afi
= afi
;
1418 mp_withdraw
->safi
= safi
;
1419 mp_withdraw
->nlri
= stream_pnt (s
);
1420 mp_withdraw
->length
= withdraw_len
;
1422 stream_forward_getp (s
, withdraw_len
);
1427 /* Extended Community attribute. */
1429 bgp_attr_ext_communities (struct peer
*peer
, bgp_size_t length
,
1430 struct attr
*attr
, u_char flag
)
1435 attr
->extra
->ecommunity
= NULL
;
1439 (bgp_attr_extra_get (attr
))->ecommunity
=
1440 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
1441 stream_forward_getp (peer
->ibuf
, length
);
1443 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
1448 /* BGP unknown attribute treatment. */
1450 bgp_attr_unknown (struct peer
*peer
, struct attr
*attr
, u_char flag
,
1451 u_char type
, bgp_size_t length
, u_char
*startp
)
1454 struct transit
*transit
;
1455 struct attr_extra
*attre
;
1457 if (BGP_DEBUG (normal
, NORMAL
))
1458 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1459 peer
->host
, type
, length
);
1461 if (BGP_DEBUG (events
, EVENTS
))
1462 zlog (peer
->log
, LOG_DEBUG
,
1463 "Unknown attribute type %d length %d is received", type
, length
);
1465 /* Forward read pointer of input stream. */
1466 stream_forward_getp (peer
->ibuf
, length
);
1468 /* Adjest total length to include type and length. */
1469 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
1471 /* If any of the mandatory well-known attributes are not recognized,
1472 then the Error Subcode is set to Unrecognized Well-known
1473 Attribute. The Data field contains the unrecognized attribute
1474 (type, length and value). */
1475 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
1477 /* Adjust startp to do not include flag value. */
1478 bgp_notify_send_with_data (peer
,
1479 BGP_NOTIFY_UPDATE_ERR
,
1480 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
1485 /* Unrecognized non-transitive optional attributes must be quietly
1486 ignored and not passed along to other BGP peers. */
1487 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
1490 /* If a path with recognized transitive optional attribute is
1491 accepted and passed along to other BGP peers and the Partial bit
1492 in the Attribute Flags octet is set to 1 by some previous AS, it
1493 is not set back to 0 by the current AS. */
1494 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
1496 /* Store transitive attribute to the end of attr->transit. */
1497 if (! ((attre
= bgp_attr_extra_get(attr
))->transit
) )
1499 attre
->transit
= XMALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
1500 memset (attre
->transit
, 0, sizeof (struct transit
));
1503 transit
= attre
->transit
;
1506 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
1507 transit
->length
+ total
);
1509 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
1511 memcpy (transit
->val
+ transit
->length
, startp
, total
);
1512 transit
->length
+= total
;
1517 /* Read attribute of update packet. This function is called from
1518 bgp_update() in bgpd.c. */
1520 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
1521 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
1527 u_char
*startp
, *endp
;
1529 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
1530 /* we need the as4_path only until we have synthesized the as_path with it */
1531 /* same goes for as4_aggregator */
1532 struct aspath
*as4_path
= NULL
;
1533 as_t as4_aggregator
= 0;
1534 struct in_addr as4_aggregator_addr
= { 0 };
1536 /* Initialize bitmap. */
1537 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
1539 /* End pointer of BGP attribute. */
1540 endp
= BGP_INPUT_PNT (peer
) + size
;
1542 /* Get attributes to the end of attribute length. */
1543 while (BGP_INPUT_PNT (peer
) < endp
)
1545 /* Check remaining length check.*/
1546 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
1548 /* XXX warning: long int format, int arg (arg 5) */
1549 zlog (peer
->log
, LOG_WARNING
,
1550 "%s error BGP attribute length %lu is smaller than min len",
1552 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
1554 bgp_notify_send (peer
,
1555 BGP_NOTIFY_UPDATE_ERR
,
1556 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1560 /* Fetch attribute flag and type. */
1561 startp
= BGP_INPUT_PNT (peer
);
1562 flag
= stream_getc (BGP_INPUT (peer
));
1563 type
= stream_getc (BGP_INPUT (peer
));
1565 /* Check whether Extended-Length applies and is in bounds */
1566 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
)
1567 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1)))
1569 zlog (peer
->log
, LOG_WARNING
,
1570 "%s Extended length set, but just %lu bytes of attr header",
1572 (unsigned long) (endp
- STREAM_PNT (BGP_INPUT (peer
))));
1574 bgp_notify_send (peer
,
1575 BGP_NOTIFY_UPDATE_ERR
,
1576 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1580 /* Check extended attribue length bit. */
1581 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
1582 length
= stream_getw (BGP_INPUT (peer
));
1584 length
= stream_getc (BGP_INPUT (peer
));
1586 /* If any attribute appears more than once in the UPDATE
1587 message, then the Error Subcode is set to Malformed Attribute
1590 if (CHECK_BITMAP (seen
, type
))
1592 zlog (peer
->log
, LOG_WARNING
,
1593 "%s error BGP attribute type %d appears twice in a message",
1596 bgp_notify_send (peer
,
1597 BGP_NOTIFY_UPDATE_ERR
,
1598 BGP_NOTIFY_UPDATE_MAL_ATTR
);
1602 /* Set type to bitmap to check duplicate attribute. `type' is
1603 unsigned char so it never overflow bitmap range. */
1605 SET_BITMAP (seen
, type
);
1607 /* Overflow check. */
1608 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
1610 if (attr_endp
> endp
)
1612 zlog (peer
->log
, LOG_WARNING
,
1613 "%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
);
1614 bgp_notify_send (peer
,
1615 BGP_NOTIFY_UPDATE_ERR
,
1616 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1620 /* OK check attribute and store it's value. */
1623 case BGP_ATTR_ORIGIN
:
1624 ret
= bgp_attr_origin (peer
, length
, attr
, flag
, startp
);
1626 case BGP_ATTR_AS_PATH
:
1627 ret
= bgp_attr_aspath (peer
, length
, attr
, flag
, startp
);
1629 case BGP_ATTR_AS4_PATH
:
1630 ret
= bgp_attr_as4_path (peer
, length
, attr
, &as4_path
);
1632 case BGP_ATTR_NEXT_HOP
:
1633 ret
= bgp_attr_nexthop (peer
, length
, attr
, flag
, startp
);
1635 case BGP_ATTR_MULTI_EXIT_DISC
:
1636 ret
= bgp_attr_med (peer
, length
, attr
, flag
, startp
);
1638 case BGP_ATTR_LOCAL_PREF
:
1639 ret
= bgp_attr_local_pref (peer
, length
, attr
, flag
);
1641 case BGP_ATTR_ATOMIC_AGGREGATE
:
1642 ret
= bgp_attr_atomic (peer
, length
, attr
, flag
);
1644 case BGP_ATTR_AGGREGATOR
:
1645 ret
= bgp_attr_aggregator (peer
, length
, attr
, flag
);
1647 case BGP_ATTR_AS4_AGGREGATOR
:
1648 ret
= bgp_attr_as4_aggregator (peer
, length
, attr
, &as4_aggregator
, &as4_aggregator_addr
);
1650 case BGP_ATTR_COMMUNITIES
:
1651 ret
= bgp_attr_community (peer
, length
, attr
, flag
);
1653 case BGP_ATTR_ORIGINATOR_ID
:
1654 ret
= bgp_attr_originator_id (peer
, length
, attr
, flag
);
1656 case BGP_ATTR_CLUSTER_LIST
:
1657 ret
= bgp_attr_cluster_list (peer
, length
, attr
, flag
);
1659 case BGP_ATTR_MP_REACH_NLRI
:
1660 ret
= bgp_mp_reach_parse (peer
, length
, attr
, mp_update
);
1662 case BGP_ATTR_MP_UNREACH_NLRI
:
1663 ret
= bgp_mp_unreach_parse (peer
, length
, mp_withdraw
);
1665 case BGP_ATTR_EXT_COMMUNITIES
:
1666 ret
= bgp_attr_ext_communities (peer
, length
, attr
, flag
);
1668 case BGP_ATTR_AS_PATHLIMIT
:
1669 ret
= bgp_attr_aspathlimit (peer
, length
, attr
, flag
, startp
);
1672 ret
= bgp_attr_unknown (peer
, attr
, flag
, type
, length
, startp
);
1676 /* If error occured immediately return to the caller. */
1679 zlog (peer
->log
, LOG_WARNING
,
1680 "%s: Attribute %s, parse error",
1682 LOOKUP (attr_str
, type
));
1683 bgp_notify_send (peer
,
1684 BGP_NOTIFY_UPDATE_ERR
,
1685 BGP_NOTIFY_UPDATE_MAL_ATTR
);
1689 /* Check the fetched length. */
1690 if (BGP_INPUT_PNT (peer
) != attr_endp
)
1692 zlog (peer
->log
, LOG_WARNING
,
1693 "%s: BGP attribute %s, fetch error",
1694 peer
->host
, LOOKUP (attr_str
, type
));
1695 bgp_notify_send (peer
,
1696 BGP_NOTIFY_UPDATE_ERR
,
1697 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1702 /* Check final read pointer is same as end pointer. */
1703 if (BGP_INPUT_PNT (peer
) != endp
)
1705 zlog (peer
->log
, LOG_WARNING
,
1706 "%s BGP attribute %s, length mismatch",
1707 peer
->host
, LOOKUP (attr_str
, type
));
1708 bgp_notify_send (peer
,
1709 BGP_NOTIFY_UPDATE_ERR
,
1710 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1715 * At this place we can see whether we got AS4_PATH and/or
1716 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
1717 * We can not do this before we've read all attributes because
1718 * the as4 handling does not say whether AS4_PATH has to be sent
1719 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
1720 * in relationship to AGGREGATOR.
1721 * So, to be defensive, we are not relying on any order and read
1722 * all attributes first, including these 32bit ones, and now,
1723 * afterwards, we look what and if something is to be done for as4.
1725 if (bgp_attr_munge_as4_attrs (peer
, attr
, as4_path
,
1726 as4_aggregator
, &as4_aggregator_addr
))
1729 /* At this stage, we have done all fiddling with as4, and the
1730 * resulting info is in attr->aggregator resp. attr->aspath
1731 * so we can chuck as4_aggregator and as4_path alltogether in
1732 * order to save memory
1736 aspath_unintern( as4_path
); /* unintern - it is in the hash */
1738 /* The flag that we got this is still there, but that does not
1743 * The "rest" of the code does nothing with as4_aggregator.
1744 * there is no memory attached specifically which is not part
1746 * so ignoring just means do nothing.
1749 * Finally do the checks on the aspath we did not do yet
1750 * because we waited for a potentially synthesized aspath.
1752 if ( attr
->flag
& ( ATTR_FLAG_BIT( BGP_ATTR_AS_PATH
)))
1754 ret
= bgp_attr_aspath_check( peer
, attr
);
1759 /* Finally intern unknown attribute. */
1760 if (attr
->extra
&& attr
->extra
->transit
)
1761 attr
->extra
->transit
= transit_intern (attr
->extra
->transit
);
1766 /* Well-known attribute check. */
1768 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
1772 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
1773 type
= BGP_ATTR_ORIGIN
;
1775 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
1776 type
= BGP_ATTR_AS_PATH
;
1778 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
)))
1779 type
= BGP_ATTR_NEXT_HOP
;
1781 if (peer_sort (peer
) == BGP_PEER_IBGP
1782 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
1783 type
= BGP_ATTR_LOCAL_PREF
;
1787 zlog (peer
->log
, LOG_WARNING
,
1788 "%s Missing well-known attribute %d.",
1790 bgp_notify_send_with_data (peer
,
1791 BGP_NOTIFY_UPDATE_ERR
,
1792 BGP_NOTIFY_UPDATE_MISS_ATTR
,
1799 int stream_put_prefix (struct stream
*, struct prefix
*);
1801 /* Make attribute packet. */
1803 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
1804 struct stream
*s
, struct attr
*attr
, struct prefix
*p
,
1805 afi_t afi
, safi_t safi
, struct peer
*from
,
1806 struct prefix_rd
*prd
, u_char
*tag
)
1809 size_t aspath_sizep
;
1810 struct aspath
*aspath
;
1811 int send_as4_path
= 0;
1812 int send_as4_aggregator
= 0;
1813 int use32bit
= (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
1816 bgp
= bgp_get_default ();
1818 /* Remember current pointer. */
1819 cp
= stream_get_endp (s
);
1821 /* Origin attribute. */
1822 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1823 stream_putc (s
, BGP_ATTR_ORIGIN
);
1825 stream_putc (s
, attr
->origin
);
1827 /* AS path attribute. */
1829 /* If remote-peer is EBGP */
1830 if (peer_sort (peer
) == BGP_PEER_EBGP
1831 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
1832 || attr
->aspath
->segments
== NULL
)
1833 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
1835 aspath
= aspath_dup (attr
->aspath
);
1837 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1839 /* Strip the confed info, and then stuff our path CONFED_ID
1841 aspath
= aspath_delete_confed_seq (aspath
);
1842 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
1846 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
1847 if (peer
->change_local_as
)
1848 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1851 else if (peer_sort (peer
) == BGP_PEER_CONFED
)
1853 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
1854 aspath
= aspath_dup (attr
->aspath
);
1855 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
1858 aspath
= attr
->aspath
;
1860 /* If peer is not AS4 capable, then:
1861 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
1862 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
1863 * types are in it (i.e. exclude them if they are there)
1864 * AND do this only if there is at least one asnum > 65535 in the path!
1865 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
1866 * all ASnums > 65535 to BGP_AS_TRANS
1869 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
1870 stream_putc (s
, BGP_ATTR_AS_PATH
);
1871 aspath_sizep
= stream_get_endp (s
);
1873 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, use32bit
));
1875 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
1878 if (!use32bit
&& aspath_has_as4 (aspath
))
1879 send_as4_path
= 1; /* we'll do this later, at the correct place */
1881 /* Nexthop attribute. */
1882 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
) && afi
== AFI_IP
)
1884 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1885 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
1887 if (safi
== SAFI_MPLS_VPN
)
1889 if (attr
->nexthop
.s_addr
== 0)
1890 stream_put_ipv4 (s
, peer
->nexthop
.v4
.s_addr
);
1892 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
1895 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
1898 /* MED attribute. */
1899 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
1901 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1902 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
1904 stream_putl (s
, attr
->med
);
1907 /* Local preference. */
1908 if (peer_sort (peer
) == BGP_PEER_IBGP
||
1909 peer_sort (peer
) == BGP_PEER_CONFED
)
1911 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1912 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
1914 stream_putl (s
, attr
->local_pref
);
1917 /* Atomic aggregate. */
1918 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
1920 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1921 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
1926 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
1928 assert (attr
->extra
);
1930 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
1931 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
1932 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
1936 /* AS4 capable peer */
1938 stream_putl (s
, attr
->extra
->aggregator_as
);
1942 /* 2-byte AS peer */
1945 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
1946 if ( attr
->extra
->aggregator_as
> 65535 )
1948 stream_putw (s
, BGP_AS_TRANS
);
1950 /* we have to send AS4_AGGREGATOR, too.
1951 * we'll do that later in order to send attributes in ascending
1954 send_as4_aggregator
= 1;
1957 stream_putw (s
, (u_int16_t
) attr
->extra
->aggregator_as
);
1959 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
1962 /* Community attribute. */
1963 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
1964 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
1966 if (attr
->community
->size
* 4 > 255)
1968 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
1969 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
1970 stream_putw (s
, attr
->community
->size
* 4);
1974 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
1975 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
1976 stream_putc (s
, attr
->community
->size
* 4);
1978 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
1981 /* Route Reflector. */
1982 if (peer_sort (peer
) == BGP_PEER_IBGP
1984 && peer_sort (from
) == BGP_PEER_IBGP
)
1986 /* Originator ID. */
1987 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1988 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
1991 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1992 stream_put_in_addr (s
, &attr
->extra
->originator_id
);
1994 stream_put_in_addr (s
, &from
->remote_id
);
1997 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1998 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
2000 if (attr
->extra
&& attr
->extra
->cluster
)
2002 stream_putc (s
, attr
->extra
->cluster
->length
+ 4);
2003 /* If this peer configuration's parent BGP has cluster_id. */
2004 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
2005 stream_put_in_addr (s
, &bgp
->cluster_id
);
2007 stream_put_in_addr (s
, &bgp
->router_id
);
2008 stream_put (s
, attr
->extra
->cluster
->list
,
2009 attr
->extra
->cluster
->length
);
2014 /* If this peer configuration's parent BGP has cluster_id. */
2015 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
2016 stream_put_in_addr (s
, &bgp
->cluster_id
);
2018 stream_put_in_addr (s
, &bgp
->router_id
);
2023 /* If p is IPv6 address put it into attribute. */
2024 if (p
->family
== AF_INET6
)
2026 unsigned long sizep
;
2027 struct attr_extra
*attre
= attr
->extra
;
2029 assert (attr
->extra
);
2031 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2032 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2033 sizep
= stream_get_endp (s
);
2034 stream_putc (s
, 0); /* Marker: Attribute length. */
2035 stream_putw (s
, AFI_IP6
); /* AFI */
2036 stream_putc (s
, safi
); /* SAFI */
2038 stream_putc (s
, attre
->mp_nexthop_len
);
2040 if (attre
->mp_nexthop_len
== 16)
2041 stream_put (s
, &attre
->mp_nexthop_global
, 16);
2042 else if (attre
->mp_nexthop_len
== 32)
2044 stream_put (s
, &attre
->mp_nexthop_global
, 16);
2045 stream_put (s
, &attre
->mp_nexthop_local
, 16);
2052 stream_put_prefix (s
, p
);
2054 /* Set MP attribute length. */
2055 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
2057 #endif /* HAVE_IPV6 */
2059 if (p
->family
== AF_INET
&& safi
== SAFI_MULTICAST
)
2061 unsigned long sizep
;
2063 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2064 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2065 sizep
= stream_get_endp (s
);
2066 stream_putc (s
, 0); /* Marker: Attribute Length. */
2067 stream_putw (s
, AFI_IP
); /* AFI */
2068 stream_putc (s
, SAFI_MULTICAST
); /* SAFI */
2071 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2077 stream_put_prefix (s
, p
);
2079 /* Set MP attribute length. */
2080 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
2083 if (p
->family
== AF_INET
&& safi
== SAFI_MPLS_VPN
)
2085 unsigned long sizep
;
2087 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2088 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
2089 sizep
= stream_get_endp (s
);
2090 stream_putc (s
, 0); /* Length of this attribute. */
2091 stream_putw (s
, AFI_IP
); /* AFI */
2092 stream_putc (s
, BGP_SAFI_VPNV4
); /* SAFI */
2094 stream_putc (s
, 12);
2097 stream_put (s
, &attr
->extra
->mp_nexthop_global_in
, 4);
2102 /* Tag, RD, Prefix write. */
2103 stream_putc (s
, p
->prefixlen
+ 88);
2104 stream_put (s
, tag
, 3);
2105 stream_put (s
, prd
->val
, 8);
2106 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2108 /* Set MP attribute length. */
2109 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
2112 /* Extended Communities attribute. */
2113 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
2114 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
2116 struct attr_extra
*attre
= attr
->extra
;
2120 if (peer_sort (peer
) == BGP_PEER_IBGP
2121 || peer_sort (peer
) == BGP_PEER_CONFED
)
2123 if (attre
->ecommunity
->size
* 8 > 255)
2125 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2126 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2127 stream_putw (s
, attre
->ecommunity
->size
* 8);
2131 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2132 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2133 stream_putc (s
, attre
->ecommunity
->size
* 8);
2135 stream_put (s
, attre
->ecommunity
->val
, attre
->ecommunity
->size
* 8);
2141 int ecom_tr_size
= 0;
2144 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
2146 pnt
= attre
->ecommunity
->val
+ (i
* 8);
2149 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
2157 if (ecom_tr_size
* 8 > 255)
2159 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2160 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2161 stream_putw (s
, ecom_tr_size
* 8);
2165 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2166 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
2167 stream_putc (s
, ecom_tr_size
* 8);
2170 for (i
= 0; i
< attre
->ecommunity
->size
; i
++)
2172 pnt
= attre
->ecommunity
->val
+ (i
* 8);
2175 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
2178 stream_put (s
, pnt
, 8);
2184 if ( send_as4_path
)
2186 /* If the peer is NOT As4 capable, AND */
2187 /* there are ASnums > 65535 in path THEN
2188 * give out AS4_PATH */
2190 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2192 * Hm, I wonder... confederation things *should* only be at
2193 * the beginning of an aspath, right? Then we should use
2194 * aspath_delete_confed_seq for this, because it is already
2196 * Folks, talk to me: what is reasonable here!?
2198 aspath
= aspath_delete_confed_seq (aspath
);
2200 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_EXTLEN
);
2201 stream_putc (s
, BGP_ATTR_AS4_PATH
);
2202 aspath_sizep
= stream_get_endp (s
);
2204 stream_putw_at (s
, aspath_sizep
, aspath_put (s
, aspath
, 1));
2207 if (aspath
!= attr
->aspath
)
2208 aspath_free (aspath
);
2210 if ( send_as4_aggregator
)
2212 assert (attr
->extra
);
2214 /* send AS4_AGGREGATOR, at this place */
2215 /* this section of code moved here in order to ensure the correct
2216 * *ascending* order of attributes
2218 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2219 stream_putc (s
, BGP_ATTR_AS4_AGGREGATOR
);
2221 stream_putl (s
, attr
->extra
->aggregator_as
);
2222 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
2226 if (attr
->pathlimit
.ttl
)
2228 u_int32_t as
= attr
->pathlimit
.as
;
2230 /* should already have been done in announce_check(),
2231 * but just in case..
2234 as
= peer
->local_as
;
2236 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2237 stream_putc (s
, BGP_ATTR_AS_PATHLIMIT
);
2239 stream_putc (s
, attr
->pathlimit
.ttl
);
2240 stream_putl (s
, as
);
2243 /* Unknown transit attribute. */
2244 if (attr
->extra
&& attr
->extra
->transit
)
2245 stream_put (s
, attr
->extra
->transit
->val
, attr
->extra
->transit
->length
);
2247 /* Return total size of attribute. */
2248 return stream_get_endp (s
) - cp
;
2252 bgp_packet_withdraw (struct peer
*peer
, struct stream
*s
, struct prefix
*p
,
2253 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
2257 unsigned long attrlen_pnt
;
2260 cp
= stream_get_endp (s
);
2262 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2263 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
2265 attrlen_pnt
= stream_get_endp (s
);
2266 stream_putc (s
, 0); /* Length of this attribute. */
2268 stream_putw (s
, family2afi (p
->family
));
2270 if (safi
== SAFI_MPLS_VPN
)
2273 stream_putc (s
, BGP_SAFI_VPNV4
);
2276 stream_putc (s
, p
->prefixlen
+ 88);
2277 stream_put (s
, tag
, 3);
2278 stream_put (s
, prd
->val
, 8);
2279 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
2284 stream_putc (s
, safi
);
2287 stream_put_prefix (s
, p
);
2290 /* Set MP attribute length. */
2291 size
= stream_get_endp (s
) - attrlen_pnt
- 1;
2292 stream_putc_at (s
, attrlen_pnt
, size
);
2294 return stream_get_endp (s
) - cp
;
2297 /* Initialization of attribute. */
2299 bgp_attr_init (void)
2309 /* Make attribute packet. */
2311 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
2312 struct prefix
*prefix
)
2317 struct aspath
*aspath
;
2319 /* Remember current pointer. */
2320 cp
= stream_get_endp (s
);
2322 /* Place holder of length. */
2325 /* Origin attribute. */
2326 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2327 stream_putc (s
, BGP_ATTR_ORIGIN
);
2329 stream_putc (s
, attr
->origin
);
2331 aspath
= attr
->aspath
;
2333 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2334 stream_putc (s
, BGP_ATTR_AS_PATH
);
2335 aspath_lenp
= stream_get_endp (s
);
2338 stream_putw_at (s
, aspath_lenp
, aspath_put (s
, aspath
, 1));
2340 /* Nexthop attribute. */
2341 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2344 && prefix
->family
!= AF_INET6
2345 #endif /* HAVE_IPV6 */
2348 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2349 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
2351 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
2354 /* MED attribute. */
2355 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
2357 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
2358 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
2360 stream_putl (s
, attr
->med
);
2363 /* Local preference. */
2364 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
2366 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2367 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
2369 stream_putl (s
, attr
->local_pref
);
2372 /* Atomic aggregate. */
2373 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
2375 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
2376 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
2381 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
2383 assert (attr
->extra
);
2384 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2385 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
2387 stream_putl (s
, attr
->extra
->aggregator_as
);
2388 stream_put_ipv4 (s
, attr
->extra
->aggregator_addr
.s_addr
);
2391 /* Community attribute. */
2392 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
2394 if (attr
->community
->size
* 4 > 255)
2396 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
2397 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2398 stream_putw (s
, attr
->community
->size
* 4);
2402 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2403 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
2404 stream_putc (s
, attr
->community
->size
* 4);
2406 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
2410 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
2411 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
&& attr
->extra
&&
2412 (attr
->extra
->mp_nexthop_len
== 16 || attr
->extra
->mp_nexthop_len
== 32) )
2415 struct attr_extra
*attre
= attr
->extra
;
2417 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
2418 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2419 sizep
= stream_get_endp (s
);
2422 stream_putc (s
, 0); /* Marker: Attribute length. */
2423 stream_putw(s
, AFI_IP6
); /* AFI */
2424 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
2427 stream_putc(s
, attre
->mp_nexthop_len
);
2428 stream_put(s
, &attre
->mp_nexthop_global
, 16);
2429 if (attre
->mp_nexthop_len
== 32)
2430 stream_put(s
, &attre
->mp_nexthop_local
, 16);
2436 stream_put_prefix(s
, prefix
);
2438 /* Set MP attribute length. */
2439 stream_putc_at (s
, sizep
, (stream_get_endp (s
) - sizep
) - 1);
2441 #endif /* HAVE_IPV6 */
2444 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AS_PATHLIMIT
))
2446 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
2447 stream_putc (s
, BGP_ATTR_AS_PATHLIMIT
);
2449 stream_putc (s
, attr
->pathlimit
.ttl
);
2450 stream_putl (s
, attr
->pathlimit
.as
);
2453 /* Return total size of attribute. */
2454 len
= stream_get_endp (s
) - cp
- 2;
2455 stream_putw_at (s
, cp
, len
);