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 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" },
62 struct hash
*cluster_hash
;
65 cluster_hash_alloc (struct cluster_list
*val
)
67 struct cluster_list
*cluster
;
69 cluster
= XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
70 cluster
->length
= val
->length
;
74 cluster
->list
= XMALLOC (MTYPE_CLUSTER_VAL
, val
->length
);
75 memcpy (cluster
->list
, val
->list
, val
->length
);
85 /* Cluster list related functions. */
87 cluster_parse (struct in_addr
* pnt
, int length
)
89 struct cluster_list tmp
;
90 struct cluster_list
*cluster
;
95 cluster
= hash_get (cluster_hash
, &tmp
, cluster_hash_alloc
);
101 cluster_loop_check (struct cluster_list
*cluster
, struct in_addr originator
)
105 for (i
= 0; i
< cluster
->length
/ 4; i
++)
106 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
112 cluster_hash_key_make (struct cluster_list
*cluster
)
114 unsigned int key
= 0;
118 length
= cluster
->length
;
119 pnt
= (caddr_t
) cluster
->list
;
122 key
+= pnt
[--length
];
128 cluster_hash_cmp (struct cluster_list
*cluster1
, struct cluster_list
*cluster2
)
130 if (cluster1
->length
== cluster2
->length
&&
131 memcmp (cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0)
137 cluster_free (struct cluster_list
*cluster
)
140 XFREE (MTYPE_CLUSTER_VAL
, cluster
->list
);
141 XFREE (MTYPE_CLUSTER
, cluster
);
144 struct cluster_list
*
145 cluster_dup (struct cluster_list
*cluster
)
147 struct cluster_list
*new;
149 new = XMALLOC (MTYPE_CLUSTER
, sizeof (struct cluster_list
));
150 memset (new, 0, sizeof (struct cluster_list
));
151 new->length
= cluster
->length
;
155 new->list
= XMALLOC (MTYPE_CLUSTER_VAL
, cluster
->length
);
156 memcpy (new->list
, cluster
->list
, cluster
->length
);
164 struct cluster_list
*
165 cluster_intern (struct cluster_list
*cluster
)
167 struct cluster_list
*find
;
169 find
= hash_get (cluster_hash
, cluster
, cluster_hash_alloc
);
176 cluster_unintern (struct cluster_list
*cluster
)
178 struct cluster_list
*ret
;
183 if (cluster
->refcnt
== 0)
185 ret
= hash_release (cluster_hash
, cluster
);
186 cluster_free (cluster
);
193 cluster_hash
= hash_create (cluster_hash_key_make
, cluster_hash_cmp
);
196 /* Unknown transit attribute. */
197 struct hash
*transit_hash
;
200 transit_free (struct transit
*transit
)
203 XFREE (MTYPE_TRANSIT_VAL
, transit
->val
);
204 XFREE (MTYPE_TRANSIT
, transit
);
208 transit_hash_alloc (struct transit
*transit
)
210 /* Transit structure is already allocated. */
215 transit_intern (struct transit
*transit
)
217 struct transit
*find
;
219 find
= hash_get (transit_hash
, transit
, transit_hash_alloc
);
221 transit_free (transit
);
228 transit_unintern (struct transit
*transit
)
235 if (transit
->refcnt
== 0)
237 ret
= hash_release (transit_hash
, transit
);
238 transit_free (transit
);
243 transit_hash_key_make (struct transit
*transit
)
245 unsigned int key
= 0;
249 length
= transit
->length
;
250 pnt
= (caddr_t
) transit
->val
;
253 key
+= pnt
[--length
];
259 transit_hash_cmp (struct transit
*transit1
, struct transit
*transit2
)
261 if (transit1
->length
== transit2
->length
&&
262 memcmp (transit1
->val
, transit2
->val
, transit1
->length
) == 0)
270 transit_hash
= hash_create (transit_hash_key_make
, transit_hash_cmp
);
273 /* Attribute hash routines. */
275 struct hash
*attrhash
;
278 attrhash_key_make (struct attr
*attr
)
280 unsigned int key
= 0;
283 key
+= attr
->nexthop
.s_addr
;
285 key
+= attr
->local_pref
;
286 key
+= attr
->aggregator_as
;
287 key
+= attr
->aggregator_addr
.s_addr
;
290 key
+= attr
->mp_nexthop_global_in
.s_addr
;
292 key
+= aspath_key_make (attr
->aspath
);
294 key
+= community_hash_make (attr
->community
);
295 if (attr
->ecommunity
)
296 key
+= ecommunity_hash_make (attr
->ecommunity
);
298 key
+= cluster_hash_key_make (attr
->cluster
);
300 key
+= transit_hash_key_make (attr
->transit
);
306 key
+= attr
->mp_nexthop_len
;
307 for (i
= 0; i
< 16; i
++)
308 key
+= attr
->mp_nexthop_global
.s6_addr
[i
];
309 for (i
= 0; i
< 16; i
++)
310 key
+= attr
->mp_nexthop_local
.s6_addr
[i
];
312 #endif /* HAVE_IPV6 */
318 attrhash_cmp (struct attr
*attr1
, struct attr
*attr2
)
320 if (attr1
->flag
== attr2
->flag
321 && attr1
->origin
== attr2
->origin
322 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
323 && attr1
->med
== attr2
->med
324 && attr1
->local_pref
== attr2
->local_pref
325 && attr1
->aggregator_as
== attr2
->aggregator_as
326 && attr1
->aggregator_addr
.s_addr
== attr2
->aggregator_addr
.s_addr
327 && attr1
->weight
== attr2
->weight
329 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
330 && IPV6_ADDR_SAME (&attr1
->mp_nexthop_global
, &attr2
->mp_nexthop_global
)
331 && IPV6_ADDR_SAME (&attr1
->mp_nexthop_local
, &attr2
->mp_nexthop_local
)
332 #endif /* HAVE_IPV6 */
333 && IPV4_ADDR_SAME (&attr1
->mp_nexthop_global_in
, &attr2
->mp_nexthop_global_in
)
334 && attr1
->aspath
== attr2
->aspath
335 && attr1
->community
== attr2
->community
336 && attr1
->ecommunity
== attr2
->ecommunity
337 && attr1
->cluster
== attr2
->cluster
338 && attr1
->transit
== attr2
->transit
)
347 attrhash
= hash_create (attrhash_key_make
, attrhash_cmp
);
351 attr_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
353 struct attr
*attr
= backet
->data
;
355 vty_out (vty
, "attr[%ld] nexthop %s%s", attr
->refcnt
,
356 inet_ntoa (attr
->nexthop
), VTY_NEWLINE
);
360 attr_show_all (struct vty
*vty
)
362 hash_iterate (attrhash
,
363 (void (*)(struct hash_backet
*, void *))
364 attr_show_all_iterator
,
369 bgp_attr_hash_alloc (struct attr
*val
)
373 attr
= XMALLOC (MTYPE_ATTR
, sizeof (struct attr
));
379 /* Internet argument attribute. */
381 bgp_attr_intern (struct attr
*attr
)
385 /* Intern referenced strucutre. */
388 if (! attr
->aspath
->refcnt
)
389 attr
->aspath
= aspath_intern (attr
->aspath
);
391 attr
->aspath
->refcnt
++;
395 if (! attr
->community
->refcnt
)
396 attr
->community
= community_intern (attr
->community
);
398 attr
->community
->refcnt
++;
400 if (attr
->ecommunity
)
402 if (! attr
->ecommunity
->refcnt
)
403 attr
->ecommunity
= ecommunity_intern (attr
->ecommunity
);
405 attr
->ecommunity
->refcnt
++;
409 if (! attr
->cluster
->refcnt
)
410 attr
->cluster
= cluster_intern (attr
->cluster
);
412 attr
->cluster
->refcnt
++;
416 if (! attr
->transit
->refcnt
)
417 attr
->transit
= transit_intern (attr
->transit
);
419 attr
->transit
->refcnt
++;
422 find
= (struct attr
*) hash_get (attrhash
, attr
, bgp_attr_hash_alloc
);
428 /* Make network statement's attribute. */
430 bgp_attr_default_set (struct attr
*attr
, u_char origin
)
432 memset (attr
, 0, sizeof (struct attr
));
434 attr
->origin
= origin
;
435 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
436 attr
->aspath
= aspath_empty ();
437 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
438 attr
->weight
= 32768;
439 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
441 attr
->mp_nexthop_len
= 16;
446 /* Make network statement's attribute. */
448 bgp_attr_default_intern (u_char origin
)
453 memset (&attr
, 0, sizeof (struct attr
));
455 attr
.origin
= origin
;
456 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
457 attr
.aspath
= aspath_empty ();
458 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
460 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
462 attr
.mp_nexthop_len
= 16;
465 new = bgp_attr_intern (&attr
);
466 aspath_unintern (new->aspath
);
471 bgp_attr_aggregate_intern (struct bgp
*bgp
, u_char origin
,
472 struct aspath
*aspath
,
473 struct community
*community
, int as_set
)
478 memset (&attr
, 0, sizeof (struct attr
));
480 /* Origin attribute. */
481 attr
.origin
= origin
;
482 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
484 /* AS path attribute. */
486 attr
.aspath
= aspath_intern (aspath
);
488 attr
.aspath
= aspath_empty ();
489 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
491 /* Next hop attribute. */
492 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
496 attr
.community
= community
;
497 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
502 attr
.mp_nexthop_len
= 16;
505 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
506 attr
.flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
507 if (CHECK_FLAG (bgp
->config
, BGP_CONFIG_CONFEDERATION
))
508 attr
.aggregator_as
= bgp
->confed_id
;
510 attr
.aggregator_as
= bgp
->as
;
511 attr
.aggregator_addr
= bgp
->router_id
;
513 new = bgp_attr_intern (&attr
);
514 aspath_unintern (new->aspath
);
518 /* Free bgp attribute and aspath. */
520 bgp_attr_unintern (struct attr
*attr
)
523 struct aspath
*aspath
;
524 struct community
*community
;
525 struct ecommunity
*ecommunity
;
526 struct cluster_list
*cluster
;
527 struct transit
*transit
;
529 /* Decrement attribute reference. */
531 aspath
= attr
->aspath
;
532 community
= attr
->community
;
533 ecommunity
= attr
->ecommunity
;
534 cluster
= attr
->cluster
;
535 transit
= attr
->transit
;
537 /* If reference becomes zero then free attribute object. */
538 if (attr
->refcnt
== 0)
540 ret
= hash_release (attrhash
, attr
);
541 assert (ret
!= NULL
);
542 XFREE (MTYPE_ATTR
, attr
);
545 /* aspath refcount shoud be decrement. */
547 aspath_unintern (aspath
);
549 community_unintern (community
);
551 ecommunity_unintern (ecommunity
);
553 cluster_unintern (cluster
);
555 transit_unintern (transit
);
559 bgp_attr_flush (struct attr
*attr
)
561 if (attr
->aspath
&& ! attr
->aspath
->refcnt
)
562 aspath_free (attr
->aspath
);
563 if (attr
->community
&& ! attr
->community
->refcnt
)
564 community_free (attr
->community
);
565 if (attr
->ecommunity
&& ! attr
->ecommunity
->refcnt
)
566 ecommunity_free (attr
->ecommunity
);
567 if (attr
->cluster
&& ! attr
->cluster
->refcnt
)
568 cluster_free (attr
->cluster
);
569 if (attr
->transit
&& ! attr
->transit
->refcnt
)
570 transit_free (attr
->transit
);
573 /* Get origin attribute of the update message. */
575 bgp_attr_origin (struct peer
*peer
, bgp_size_t length
,
576 struct attr
*attr
, u_char flag
, u_char
*startp
)
580 /* total is entire attribute length include Attribute Flags (1),
581 Attribute Type code (1) and Attribute length (1 or 2). */
582 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
584 /* If any recognized attribute has Attribute Flags that conflict
585 with the Attribute Type Code, then the Error Subcode is set to
586 Attribute Flags Error. The Data field contains the erroneous
587 attribute (type, length and value). */
588 if (flag
!= BGP_ATTR_FLAG_TRANS
)
590 zlog (peer
->log
, LOG_ERR
,
591 "Origin attribute flag isn't transitive %d", flag
);
592 bgp_notify_send_with_data (peer
,
593 BGP_NOTIFY_UPDATE_ERR
,
594 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
599 /* If any recognized attribute has Attribute Length that conflicts
600 with the expected length (based on the attribute type code), then
601 the Error Subcode is set to Attribute Length Error. The Data
602 field contains the erroneous attribute (type, length and
606 zlog (peer
->log
, LOG_ERR
, "Origin attribute length is not one %d",
608 bgp_notify_send_with_data (peer
, BGP_NOTIFY_UPDATE_ERR
,
609 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
614 /* Fetch origin attribute. */
615 attr
->origin
= stream_getc (BGP_INPUT (peer
));
617 /* If the ORIGIN attribute has an undefined value, then the Error
618 Subcode is set to Invalid Origin Attribute. The Data field
619 contains the unrecognized attribute (type, length and value). */
620 if ((attr
->origin
!= BGP_ORIGIN_IGP
)
621 && (attr
->origin
!= BGP_ORIGIN_EGP
)
622 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
))
624 zlog (peer
->log
, LOG_ERR
, "Origin attribute value is invalid %d",
627 bgp_notify_send_with_data (peer
,
628 BGP_NOTIFY_UPDATE_ERR
,
629 BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
634 /* Set oring attribute flag. */
635 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
);
640 /* Parse AS path information. This function is wrapper of
643 bgp_attr_aspath (struct peer
*peer
, bgp_size_t length
,
644 struct attr
*attr
, u_char flag
, u_char
*startp
)
647 struct aspath
*aspath
;
650 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
653 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
)
654 || ! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
656 zlog (peer
->log
, LOG_ERR
,
657 "Origin attribute flag isn't transitive %d", flag
);
658 bgp_notify_send_with_data (peer
,
659 BGP_NOTIFY_UPDATE_ERR
,
660 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
665 /* In case of IBGP, length will be zero. */
666 attr
->aspath
= aspath_parse (stream_pnt (peer
->ibuf
), length
);
669 zlog (peer
->log
, LOG_ERR
, "Malformed AS path length is %d", length
);
670 bgp_notify_send (peer
,
671 BGP_NOTIFY_UPDATE_ERR
,
672 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
678 /* First AS check for EBGP. */
679 if (bgp
!= NULL
&& bgp_flag_check (bgp
, BGP_FLAG_ENFORCE_FIRST_AS
))
681 if (peer_sort (peer
) == BGP_PEER_EBGP
682 && ! aspath_firstas_check (attr
->aspath
, peer
->as
))
684 zlog (peer
->log
, LOG_ERR
,
685 "%s incorrect first AS (must be %d)", peer
->host
, peer
->as
);
686 bgp_notify_send (peer
,
687 BGP_NOTIFY_UPDATE_ERR
,
688 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
693 /* local-as prepend */
694 if (peer
->change_local_as
&&
695 ! CHECK_FLAG (peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
697 aspath
= aspath_dup (attr
->aspath
);
698 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
699 aspath_unintern (attr
->aspath
);
700 attr
->aspath
= aspath_intern (aspath
);
703 /* Forward pointer. */
704 stream_forward (peer
->ibuf
, length
);
706 /* Set aspath attribute flag. */
707 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
);
712 /* Nexthop attribute. */
714 bgp_attr_nexthop (struct peer
*peer
, bgp_size_t length
,
715 struct attr
*attr
, u_char flag
, u_char
*startp
)
719 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
722 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
)
723 || ! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
725 zlog (peer
->log
, LOG_ERR
,
726 "Origin attribute flag isn't transitive %d", flag
);
727 bgp_notify_send_with_data (peer
,
728 BGP_NOTIFY_UPDATE_ERR
,
729 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
734 /* Check nexthop attribute length. */
737 zlog (peer
->log
, LOG_ERR
, "Nexthop attribute length isn't four [%d]",
740 bgp_notify_send_with_data (peer
,
741 BGP_NOTIFY_UPDATE_ERR
,
742 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
747 attr
->nexthop
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
748 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
);
755 bgp_attr_med (struct peer
*peer
, bgp_size_t length
,
756 struct attr
*attr
, u_char flag
, u_char
*startp
)
760 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
765 zlog (peer
->log
, LOG_ERR
,
766 "MED attribute length isn't four [%d]", length
);
768 bgp_notify_send_with_data (peer
,
769 BGP_NOTIFY_UPDATE_ERR
,
770 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
775 attr
->med
= stream_getl (peer
->ibuf
);
777 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
);
782 /* Local preference attribute. */
784 bgp_attr_local_pref (struct peer
*peer
, bgp_size_t length
,
785 struct attr
*attr
, u_char flag
)
787 /* If it is contained in an UPDATE message that is received from an
788 external peer, then this attribute MUST be ignored by the
789 receiving speaker. */
790 if (peer_sort (peer
) == BGP_PEER_EBGP
)
792 stream_forward (peer
->ibuf
, length
);
797 attr
->local_pref
= stream_getl (peer
->ibuf
);
799 attr
->local_pref
= 0;
801 /* Set atomic aggregate flag. */
802 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
);
807 /* Atomic aggregate. */
809 bgp_attr_atomic (struct peer
*peer
, bgp_size_t length
,
810 struct attr
*attr
, u_char flag
)
814 zlog (peer
->log
, LOG_ERR
, "Bad atomic aggregate length %d", length
);
816 bgp_notify_send (peer
,
817 BGP_NOTIFY_UPDATE_ERR
,
818 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
822 /* Set atomic aggregate flag. */
823 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
);
828 /* Aggregator attribute */
830 bgp_attr_aggregator (struct peer
*peer
, bgp_size_t length
,
831 struct attr
*attr
, u_char flag
)
835 zlog (peer
->log
, LOG_ERR
, "Aggregator length is not 6 [%d]", length
);
837 bgp_notify_send (peer
,
838 BGP_NOTIFY_UPDATE_ERR
,
839 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
842 attr
->aggregator_as
= stream_getw (peer
->ibuf
);
843 attr
->aggregator_addr
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
845 /* Set atomic aggregate flag. */
846 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
);
851 /* Community attribute. */
853 bgp_attr_community (struct peer
*peer
, bgp_size_t length
,
854 struct attr
*attr
, u_char flag
)
857 attr
->community
= NULL
;
861 community_parse ((u_int32_t
*)stream_pnt (peer
->ibuf
), length
);
862 stream_forward (peer
->ibuf
, length
);
865 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
);
870 /* Originator ID attribute. */
872 bgp_attr_originator_id (struct peer
*peer
, bgp_size_t length
,
873 struct attr
*attr
, u_char flag
)
877 zlog (peer
->log
, LOG_ERR
, "Bad originator ID length %d", length
);
879 bgp_notify_send (peer
,
880 BGP_NOTIFY_UPDATE_ERR
,
881 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
885 attr
->originator_id
.s_addr
= stream_get_ipv4 (peer
->ibuf
);
887 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID
);
892 /* Cluster list attribute. */
894 bgp_attr_cluster_list (struct peer
*peer
, bgp_size_t length
,
895 struct attr
*attr
, u_char flag
)
900 zlog (peer
->log
, LOG_ERR
, "Bad cluster list length %d", length
);
902 bgp_notify_send (peer
,
903 BGP_NOTIFY_UPDATE_ERR
,
904 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
908 attr
->cluster
= cluster_parse ((struct in_addr
*)stream_pnt (peer
->ibuf
),
911 stream_forward (peer
->ibuf
, length
);;
913 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST
);
918 /* Multiprotocol reachability information parse. */
920 bgp_mp_reach_parse (struct peer
*peer
, bgp_size_t length
, struct attr
*attr
,
921 struct bgp_nlri
*mp_update
)
932 /* Set end of packet. */
934 lim
= stream_pnt (s
) + length
;
936 /* Load AFI, SAFI. */
937 afi
= stream_getw (s
);
938 safi
= stream_getc (s
);
940 /* Get nexthop length. */
941 attr
->mp_nexthop_len
= stream_getc (s
);
943 /* Nexthop length check. */
944 switch (attr
->mp_nexthop_len
)
947 stream_get (&attr
->mp_nexthop_global_in
, s
, 4);
954 rd_high
= stream_getl (s
);
955 rd_low
= stream_getl (s
);
956 stream_get (&attr
->mp_nexthop_global_in
, s
, 4);
961 stream_get (&attr
->mp_nexthop_global
, s
, 16);
964 stream_get (&attr
->mp_nexthop_global
, s
, 16);
965 stream_get (&attr
->mp_nexthop_local
, s
, 16);
966 if (! IN6_IS_ADDR_LINKLOCAL (&attr
->mp_nexthop_local
))
968 char buf1
[INET6_ADDRSTRLEN
];
969 char buf2
[INET6_ADDRSTRLEN
];
971 if (BGP_DEBUG (update
, UPDATE_IN
))
972 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer
->host
,
973 inet_ntop (AF_INET6
, &attr
->mp_nexthop_global
,
974 buf1
, INET6_ADDRSTRLEN
),
975 inet_ntop (AF_INET6
, &attr
->mp_nexthop_local
,
976 buf2
, INET6_ADDRSTRLEN
));
978 attr
->mp_nexthop_len
= 16;
981 #endif /* HAVE_IPV6 */
983 zlog_info ("Wrong multiprotocol next hop length: %d",
984 attr
->mp_nexthop_len
);
989 snpa_num
= stream_getc (s
);
993 snpa_len
= stream_getc (s
);
994 stream_forward (s
, (snpa_len
+ 1) >> 1);
997 /* If peer is based on old draft-00. I read NLRI length from the
999 if (peer
->version
== BGP_VERSION_MP_4_DRAFT_00
)
1001 bgp_size_t nlri_total_len
;
1002 nlri_total_len
= stream_getw (s
);
1005 nlri_len
= lim
- stream_pnt (s
);
1007 if (safi
!= BGP_SAFI_VPNV4
)
1009 ret
= bgp_nlri_sanity_check (peer
, afi
, stream_pnt (s
), nlri_len
);
1014 mp_update
->afi
= afi
;
1015 mp_update
->safi
= safi
;
1016 mp_update
->nlri
= stream_pnt (s
);
1017 mp_update
->length
= nlri_len
;
1019 stream_forward (s
, nlri_len
);
1024 /* Multiprotocol unreachable parse */
1026 bgp_mp_unreach_parse (struct peer
*peer
, int length
,
1027 struct bgp_nlri
*mp_withdraw
)
1033 u_int16_t withdraw_len
;
1037 lim
= stream_pnt (s
) + length
;
1039 afi
= stream_getw (s
);
1040 safi
= stream_getc (s
);
1042 withdraw_len
= lim
- stream_pnt (s
);
1044 if (safi
!= BGP_SAFI_VPNV4
)
1046 ret
= bgp_nlri_sanity_check (peer
, afi
, stream_pnt (s
), withdraw_len
);
1051 mp_withdraw
->afi
= afi
;
1052 mp_withdraw
->safi
= safi
;
1053 mp_withdraw
->nlri
= stream_pnt (s
);
1054 mp_withdraw
->length
= withdraw_len
;
1056 stream_forward (s
, withdraw_len
);
1061 /* Extended Community attribute. */
1063 bgp_attr_ext_communities (struct peer
*peer
, bgp_size_t length
,
1064 struct attr
*attr
, u_char flag
)
1067 attr
->ecommunity
= NULL
;
1071 ecommunity_parse ((u_int8_t
*)stream_pnt (peer
->ibuf
), length
);
1072 stream_forward (peer
->ibuf
, length
);
1074 attr
->flag
|= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
);
1079 /* BGP unknown attribute treatment. */
1081 bgp_attr_unknown (struct peer
*peer
, struct attr
*attr
, u_char flag
,
1082 u_char type
, bgp_size_t length
, u_char
*startp
)
1085 struct transit
*transit
;
1087 if (BGP_DEBUG (events
, EVENTS
))
1088 zlog (peer
->log
, LOG_DEBUG
,
1089 "Unknown attribute type %d length %d is received", type
, length
);
1091 /* Forward read pointer of input stream. */
1092 stream_forward (peer
->ibuf
, length
);
1094 /* Adjest total length to include type and length. */
1095 total
= length
+ (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
1097 /* If any of the mandatory well-known attributes are not recognized,
1098 then the Error Subcode is set to Unrecognized Well-known
1099 Attribute. The Data field contains the unrecognized attribute
1100 (type, length and value). */
1101 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_OPTIONAL
))
1103 /* Adjust startp to do not include flag value. */
1104 bgp_notify_send_with_data (peer
,
1105 BGP_NOTIFY_UPDATE_ERR
,
1106 BGP_NOTIFY_UPDATE_UNREC_ATTR
,
1111 /* Unrecognized non-transitive optional attributes must be quietly
1112 ignored and not passed along to other BGP peers. */
1113 if (! CHECK_FLAG (flag
, BGP_ATTR_FLAG_TRANS
))
1116 /* If a path with recognized transitive optional attribute is
1117 accepted and passed along to other BGP peers and the Partial bit
1118 in the Attribute Flags octet is set to 1 by some previous AS, it
1119 is not set back to 0 by the current AS. */
1120 SET_FLAG (*startp
, BGP_ATTR_FLAG_PARTIAL
);
1122 /* Store transitive attribute to the end of attr->transit. */
1123 if (! attr
->transit
)
1125 attr
->transit
= XMALLOC (MTYPE_TRANSIT
, sizeof (struct transit
));
1126 memset (attr
->transit
, 0, sizeof (struct transit
));
1129 transit
= attr
->transit
;
1132 transit
->val
= XREALLOC (MTYPE_TRANSIT_VAL
, transit
->val
,
1133 transit
->length
+ total
);
1135 transit
->val
= XMALLOC (MTYPE_TRANSIT_VAL
, total
);
1137 memcpy (transit
->val
+ transit
->length
, startp
, total
);
1138 transit
->length
+= total
;
1143 /* Read attribute of update packet. This function is called from
1144 bgp_update() in bgpd.c. */
1146 bgp_attr_parse (struct peer
*peer
, struct attr
*attr
, bgp_size_t size
,
1147 struct bgp_nlri
*mp_update
, struct bgp_nlri
*mp_withdraw
)
1153 u_char
*startp
, *endp
;
1155 u_char seen
[BGP_ATTR_BITMAP_SIZE
];
1157 /* Initialize bitmap. */
1158 memset (seen
, 0, BGP_ATTR_BITMAP_SIZE
);
1160 /* End pointer of BGP attribute. */
1161 endp
= BGP_INPUT_PNT (peer
) + size
;
1163 /* Get attributes to the end of attribute length. */
1164 while (BGP_INPUT_PNT (peer
) < endp
)
1166 /* Check remaining length check.*/
1167 if (endp
- BGP_INPUT_PNT (peer
) < BGP_ATTR_MIN_LEN
)
1169 zlog (peer
->log
, LOG_WARNING
,
1170 "%s error BGP attribute length %ld is smaller than min len",
1171 peer
->host
, endp
- STREAM_PNT (BGP_INPUT (peer
)));
1173 bgp_notify_send (peer
,
1174 BGP_NOTIFY_UPDATE_ERR
,
1175 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1179 /* Fetch attribute flag and type. */
1180 startp
= BGP_INPUT_PNT (peer
);
1181 flag
= stream_getc (BGP_INPUT (peer
));
1182 type
= stream_getc (BGP_INPUT (peer
));
1184 /* Check extended attribue length bit. */
1185 if (CHECK_FLAG (flag
, BGP_ATTR_FLAG_EXTLEN
))
1186 length
= stream_getw (BGP_INPUT (peer
));
1188 length
= stream_getc (BGP_INPUT (peer
));
1190 /* If any attribute appears more than once in the UPDATE
1191 message, then the Error Subcode is set to Malformed Attribute
1194 if (CHECK_BITMAP (seen
, type
))
1196 zlog (peer
->log
, LOG_WARNING
,
1197 "%s error BGP attribute type %d appears twice in a message",
1200 bgp_notify_send (peer
,
1201 BGP_NOTIFY_UPDATE_ERR
,
1202 BGP_NOTIFY_UPDATE_MAL_ATTR
);
1206 /* Set type to bitmap to check duplicate attribute. `type' is
1207 unsigned char so it never overflow bitmap range. */
1209 SET_BITMAP (seen
, type
);
1211 /* Overflow check. */
1212 attr_endp
= BGP_INPUT_PNT (peer
) + length
;
1214 if (attr_endp
> endp
)
1216 zlog (peer
->log
, LOG_WARNING
,
1217 "%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
);
1218 bgp_notify_send (peer
,
1219 BGP_NOTIFY_UPDATE_ERR
,
1220 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1224 /* OK check attribute and store it's value. */
1227 case BGP_ATTR_ORIGIN
:
1228 ret
= bgp_attr_origin (peer
, length
, attr
, flag
, startp
);
1230 case BGP_ATTR_AS_PATH
:
1231 ret
= bgp_attr_aspath (peer
, length
, attr
, flag
, startp
);
1233 case BGP_ATTR_NEXT_HOP
:
1234 ret
= bgp_attr_nexthop (peer
, length
, attr
, flag
, startp
);
1236 case BGP_ATTR_MULTI_EXIT_DISC
:
1237 ret
= bgp_attr_med (peer
, length
, attr
, flag
, startp
);
1239 case BGP_ATTR_LOCAL_PREF
:
1240 ret
= bgp_attr_local_pref (peer
, length
, attr
, flag
);
1242 case BGP_ATTR_ATOMIC_AGGREGATE
:
1243 ret
= bgp_attr_atomic (peer
, length
, attr
, flag
);
1245 case BGP_ATTR_AGGREGATOR
:
1246 ret
= bgp_attr_aggregator (peer
, length
, attr
, flag
);
1248 case BGP_ATTR_COMMUNITIES
:
1249 ret
= bgp_attr_community (peer
, length
, attr
, flag
);
1251 case BGP_ATTR_ORIGINATOR_ID
:
1252 ret
= bgp_attr_originator_id (peer
, length
, attr
, flag
);
1254 case BGP_ATTR_CLUSTER_LIST
:
1255 ret
= bgp_attr_cluster_list (peer
, length
, attr
, flag
);
1257 case BGP_ATTR_MP_REACH_NLRI
:
1258 ret
= bgp_mp_reach_parse (peer
, length
, attr
, mp_update
);
1260 case BGP_ATTR_MP_UNREACH_NLRI
:
1261 ret
= bgp_mp_unreach_parse (peer
, length
, mp_withdraw
);
1263 case BGP_ATTR_EXT_COMMUNITIES
:
1264 ret
= bgp_attr_ext_communities (peer
, length
, attr
, flag
);
1267 ret
= bgp_attr_unknown (peer
, attr
, flag
, type
, length
, startp
);
1271 /* If error occured immediately return to the caller. */
1275 /* Check the fetched length. */
1276 if (BGP_INPUT_PNT (peer
) != attr_endp
)
1278 zlog (peer
->log
, LOG_WARNING
,
1279 "%s BGP attribute fetch error", peer
->host
);
1280 bgp_notify_send (peer
,
1281 BGP_NOTIFY_UPDATE_ERR
,
1282 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1287 /* Check final read pointer is same as end pointer. */
1288 if (BGP_INPUT_PNT (peer
) != endp
)
1290 zlog (peer
->log
, LOG_WARNING
,
1291 "%s BGP attribute length mismatch", peer
->host
);
1292 bgp_notify_send (peer
,
1293 BGP_NOTIFY_UPDATE_ERR
,
1294 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
1298 /* Finally intern unknown attribute. */
1300 attr
->transit
= transit_intern (attr
->transit
);
1305 /* Well-known attribute check. */
1307 bgp_attr_check (struct peer
*peer
, struct attr
*attr
)
1311 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN
)))
1312 type
= BGP_ATTR_ORIGIN
;
1314 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH
)))
1315 type
= BGP_ATTR_AS_PATH
;
1317 if (! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
)))
1318 type
= BGP_ATTR_NEXT_HOP
;
1320 if (peer_sort (peer
) == BGP_PEER_IBGP
1321 && ! CHECK_FLAG (attr
->flag
, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
)))
1322 type
= BGP_ATTR_LOCAL_PREF
;
1326 zlog (peer
->log
, LOG_WARNING
,
1327 "%s Missing well-known attribute %d.",
1329 bgp_notify_send_with_data (peer
,
1330 BGP_NOTIFY_UPDATE_ERR
,
1331 BGP_NOTIFY_UPDATE_MISS_ATTR
,
1338 int stream_put_prefix (struct stream
*, struct prefix
*);
1340 /* Make attribute packet. */
1342 bgp_packet_attribute (struct bgp
*bgp
, struct peer
*peer
,
1343 struct stream
*s
, struct attr
*attr
, struct prefix
*p
,
1344 afi_t afi
, safi_t safi
, struct peer
*from
,
1345 struct prefix_rd
*prd
, char *tag
)
1348 struct aspath
*aspath
;
1351 bgp
= bgp_get_default ();
1353 /* Remember current pointer. */
1354 cp
= stream_get_putp (s
);
1356 /* Origin attribute. */
1357 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1358 stream_putc (s
, BGP_ATTR_ORIGIN
);
1360 stream_putc (s
, attr
->origin
);
1362 /* AS path attribute. */
1364 /* If remote-peer is EBGP */
1365 if (peer_sort (peer
) == BGP_PEER_EBGP
1366 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_AS_PATH_UNCHANGED
)
1367 || attr
->aspath
->length
== 0)
1368 && (! CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)))
1370 aspath
= aspath_dup (attr
->aspath
);
1372 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1374 /* Strip the confed info, and then stuff our path CONFED_ID
1376 aspath
= aspath_delete_confed_seq (aspath
);
1377 aspath
= aspath_add_seq (aspath
, bgp
->confed_id
);
1381 aspath
= aspath_add_seq (aspath
, peer
->local_as
);
1382 if (peer
->change_local_as
)
1383 aspath
= aspath_add_seq (aspath
, peer
->change_local_as
);
1386 else if (peer_sort (peer
) == BGP_PEER_CONFED
)
1388 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
1389 aspath
= aspath_dup (attr
->aspath
);
1390 aspath
= aspath_add_confed_seq (aspath
, peer
->local_as
);
1393 aspath
= attr
->aspath
;
1395 /* AS path attribute extended length bit check. */
1396 if (aspath
->length
> 255)
1398 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
1399 stream_putc (s
, BGP_ATTR_AS_PATH
);
1400 stream_putw (s
, aspath
->length
);
1404 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1405 stream_putc(s
, BGP_ATTR_AS_PATH
);
1406 stream_putc (s
, aspath
->length
);
1408 stream_put (s
, aspath
->data
, aspath
->length
);
1410 if (aspath
!= attr
->aspath
)
1411 aspath_free (aspath
);
1413 /* Nexthop attribute. */
1414 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP
) && afi
== AFI_IP
)
1416 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1417 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
1419 if (safi
== SAFI_MPLS_VPN
)
1421 if (attr
->nexthop
.s_addr
== 0)
1422 stream_put_ipv4 (s
, peer
->nexthop
.v4
.s_addr
);
1424 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
1427 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
1430 /* MED attribute. */
1431 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
1433 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1434 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
1436 stream_putl (s
, attr
->med
);
1439 /* Local preference. */
1440 if (peer_sort (peer
) == BGP_PEER_IBGP
||
1441 peer_sort (peer
) == BGP_PEER_CONFED
)
1443 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1444 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
1446 stream_putl (s
, attr
->local_pref
);
1449 /* Atomic aggregate. */
1450 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
1452 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1453 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
1458 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
1460 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
1461 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
1463 stream_putw (s
, attr
->aggregator_as
);
1464 stream_put_ipv4 (s
, attr
->aggregator_addr
.s_addr
);
1467 /* Community attribute. */
1468 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
1469 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
)))
1471 if (attr
->community
->size
* 4 > 255)
1473 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
1474 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
1475 stream_putw (s
, attr
->community
->size
* 4);
1479 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
1480 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
1481 stream_putc (s
, attr
->community
->size
* 4);
1483 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
1486 /* Route Reflector. */
1487 if (peer_sort (peer
) == BGP_PEER_IBGP
1489 && peer_sort (from
) == BGP_PEER_IBGP
)
1491 /* Originator ID. */
1492 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1493 stream_putc (s
, BGP_ATTR_ORIGINATOR_ID
);
1496 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1497 stream_put_in_addr (s
, &attr
->originator_id
);
1501 stream_put_in_addr (s
, &from
->remote_id
);
1503 stream_put_in_addr (s
, &attr
->originator_id
);
1507 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1508 stream_putc (s
, BGP_ATTR_CLUSTER_LIST
);
1512 stream_putc (s
, attr
->cluster
->length
+ 4);
1513 /* If this peer configuration's parent BGP has cluster_id. */
1514 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1515 stream_put_in_addr (s
, &bgp
->cluster_id
);
1517 stream_put_in_addr (s
, &bgp
->router_id
);
1518 stream_put (s
, attr
->cluster
->list
, attr
->cluster
->length
);
1523 /* If this peer configuration's parent BGP has cluster_id. */
1524 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1525 stream_put_in_addr (s
, &bgp
->cluster_id
);
1527 stream_put_in_addr (s
, &bgp
->router_id
);
1532 /* If p is IPv6 address put it into attribute. */
1533 if (p
->family
== AF_INET6
)
1535 unsigned long sizep
;
1536 unsigned long draftp
= 0;
1538 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1539 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
1540 sizep
= stream_get_putp (s
);
1541 stream_putc (s
, 0); /* Length of this attribute. */
1542 stream_putw (s
, AFI_IP6
); /* AFI */
1543 stream_putc (s
, safi
); /* SAFI */
1545 stream_putc (s
, attr
->mp_nexthop_len
);
1547 if (attr
->mp_nexthop_len
== 16)
1548 stream_put (s
, &attr
->mp_nexthop_global
, 16);
1549 else if (attr
->mp_nexthop_len
== 32)
1551 stream_put (s
, &attr
->mp_nexthop_global
, 16);
1552 stream_put (s
, &attr
->mp_nexthop_local
, 16);
1558 /* In case of old draft BGP-4+. */
1559 if (peer
->version
== BGP_VERSION_MP_4_DRAFT_00
)
1561 draftp
= stream_get_putp (s
);
1566 stream_put_prefix (s
, p
);
1568 /* Set MP attribute length. */
1569 stream_putc_at (s
, sizep
, (stream_get_putp (s
) - sizep
) - 1);
1571 /* In case of old draft BGP-4+. */
1572 if (peer
->version
== BGP_VERSION_MP_4_DRAFT_00
)
1573 stream_putw_at (s
, draftp
, (stream_get_putp (s
) - draftp
) - 2);
1575 #endif /* HAVE_IPV6 */
1577 if (p
->family
== AF_INET
&& safi
== SAFI_MULTICAST
)
1579 unsigned long sizep
;
1580 unsigned long draftp
= 0;
1582 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1583 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
1584 sizep
= stream_get_putp (s
);
1585 stream_putc (s
, 0); /* Length of this attribute. */
1586 stream_putw (s
, AFI_IP
); /* AFI */
1587 stream_putc (s
, SAFI_MULTICAST
); /* SAFI */
1590 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
1595 /* In case of old draft BGP-4+. */
1596 if (peer
->version
== BGP_VERSION_MP_4_DRAFT_00
)
1598 draftp
= stream_get_putp (s
);
1603 stream_put_prefix (s
, p
);
1605 /* Set MP attribute length. */
1606 stream_putc_at (s
, sizep
, (stream_get_putp (s
) - sizep
) - 1);
1608 /* In case of old draft BGP-4+. */
1609 if (peer
->version
== BGP_VERSION_MP_4_DRAFT_00
)
1610 stream_putw_at (s
, draftp
, (stream_get_putp (s
) - draftp
) - 2);
1613 if (p
->family
== AF_INET
&& safi
== SAFI_MPLS_VPN
)
1615 unsigned long sizep
;
1616 unsigned long draftp
= 0;
1618 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1619 stream_putc (s
, BGP_ATTR_MP_REACH_NLRI
);
1620 sizep
= stream_get_putp (s
);
1621 stream_putc (s
, 0); /* Length of this attribute. */
1622 stream_putw (s
, AFI_IP
); /* AFI */
1623 stream_putc (s
, BGP_SAFI_VPNV4
); /* SAFI */
1625 stream_putc (s
, 12);
1628 stream_put (s
, &attr
->mp_nexthop_global_in
, 4);
1633 /* In case of old draft BGP-4+. */
1634 if (peer
->version
== BGP_VERSION_MP_4_DRAFT_00
)
1636 draftp
= stream_get_putp (s
);
1640 /* Tag, RD, Prefix write. */
1641 stream_putc (s
, p
->prefixlen
+ 88);
1642 stream_put (s
, tag
, 3);
1643 stream_put (s
, prd
->val
, 8);
1644 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
1646 /* Set MP attribute length. */
1647 stream_putc_at (s
, sizep
, (stream_get_putp (s
) - sizep
) - 1);
1649 /* In case of old draft BGP-4+. */
1650 if (peer
->version
== BGP_VERSION_MP_4_DRAFT_00
)
1651 stream_putw_at (s
, draftp
, (stream_get_putp (s
) - draftp
) - 2);
1654 /* Extended Communities attribute. */
1655 if (CHECK_FLAG (peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
1656 && (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES
)))
1658 if (peer_sort (peer
) == BGP_PEER_IBGP
|| peer_sort (peer
) == BGP_PEER_CONFED
)
1660 if (attr
->ecommunity
->size
* 8 > 255)
1662 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
1663 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
1664 stream_putw (s
, attr
->ecommunity
->size
* 8);
1668 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
1669 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
1670 stream_putc (s
, attr
->ecommunity
->size
* 8);
1672 stream_put (s
, attr
->ecommunity
->val
, attr
->ecommunity
->size
* 8);
1678 int ecom_tr_size
= 0;
1681 for (i
= 0; i
< attr
->ecommunity
->size
; i
++)
1683 pnt
= attr
->ecommunity
->val
+ (i
* 8);
1686 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
1694 if (ecom_tr_size
* 8 > 255)
1696 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
1697 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
1698 stream_putw (s
, ecom_tr_size
* 8);
1702 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
1703 stream_putc (s
, BGP_ATTR_EXT_COMMUNITIES
);
1704 stream_putc (s
, ecom_tr_size
* 8);
1707 for (i
= 0; i
< attr
->ecommunity
->size
; i
++)
1709 pnt
= attr
->ecommunity
->val
+ (i
* 8);
1712 if (CHECK_FLAG (tbit
, ECOMMUNITY_FLAG_NON_TRANSITIVE
))
1715 stream_put (s
, pnt
, 8);
1721 /* Unknown transit attribute. */
1723 stream_put (s
, attr
->transit
->val
, attr
->transit
->length
);
1725 /* Return total size of attribute. */
1726 return stream_get_putp (s
) - cp
;
1730 bgp_packet_withdraw (struct peer
*peer
, struct stream
*s
, struct prefix
*p
,
1731 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
1735 unsigned long attrlen_pnt
;
1738 cp
= stream_get_putp (s
);
1740 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1741 stream_putc (s
, BGP_ATTR_MP_UNREACH_NLRI
);
1743 attrlen_pnt
= stream_get_putp (s
);
1744 stream_putc (s
, 0); /* Length of this attribute. */
1746 stream_putw (s
, family2afi (p
->family
));
1748 if (safi
== SAFI_MPLS_VPN
)
1751 stream_putc (s
, BGP_SAFI_VPNV4
);
1754 stream_putc (s
, p
->prefixlen
+ 88);
1755 stream_put (s
, tag
, 3);
1756 stream_put (s
, prd
->val
, 8);
1757 stream_put (s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
1762 stream_putc (s
, safi
);
1765 stream_put_prefix (s
, p
);
1768 /* Set MP attribute length. */
1769 size
= stream_get_putp (s
) - attrlen_pnt
- 1;
1770 stream_putc_at (s
, attrlen_pnt
, size
);
1772 return stream_get_putp (s
) - cp
;
1775 /* Initialization of attribute. */
1779 void attrhash_init ();
1789 /* Make attribute packet. */
1791 bgp_dump_routes_attr (struct stream
*s
, struct attr
*attr
,
1792 struct prefix
*prefix
)
1796 struct aspath
*aspath
;
1798 /* Remember current pointer. */
1799 cp
= stream_get_putp (s
);
1801 /* Place holder of length. */
1804 /* Origin attribute. */
1805 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1806 stream_putc (s
, BGP_ATTR_ORIGIN
);
1808 stream_putc (s
, attr
->origin
);
1810 aspath
= attr
->aspath
;
1812 if (aspath
->length
> 255)
1814 stream_putc (s
, BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
1815 stream_putc (s
, BGP_ATTR_AS_PATH
);
1816 stream_putw (s
, aspath
->length
);
1820 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1821 stream_putc (s
, BGP_ATTR_AS_PATH
);
1822 stream_putc (s
, aspath
->length
);
1824 stream_put (s
, aspath
->data
, aspath
->length
);
1826 /* Nexthop attribute. */
1827 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
1830 && prefix
->family
!= AF_INET6
1831 #endif /* HAVE_IPV6 */
1834 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1835 stream_putc (s
, BGP_ATTR_NEXT_HOP
);
1837 stream_put_ipv4 (s
, attr
->nexthop
.s_addr
);
1840 /* MED attribute. */
1841 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC
))
1843 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
);
1844 stream_putc (s
, BGP_ATTR_MULTI_EXIT_DISC
);
1846 stream_putl (s
, attr
->med
);
1849 /* Local preference. */
1850 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF
))
1852 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1853 stream_putc (s
, BGP_ATTR_LOCAL_PREF
);
1855 stream_putl (s
, attr
->local_pref
);
1858 /* Atomic aggregate. */
1859 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE
))
1861 stream_putc (s
, BGP_ATTR_FLAG_TRANS
);
1862 stream_putc (s
, BGP_ATTR_ATOMIC_AGGREGATE
);
1867 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR
))
1869 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
1870 stream_putc (s
, BGP_ATTR_AGGREGATOR
);
1872 stream_putw (s
, attr
->aggregator_as
);
1873 stream_put_ipv4 (s
, attr
->aggregator_addr
.s_addr
);
1876 /* Community attribute. */
1877 if (attr
->flag
& ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES
))
1879 if (attr
->community
->size
* 4 > 255)
1881 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
|BGP_ATTR_FLAG_EXTLEN
);
1882 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
1883 stream_putw (s
, attr
->community
->size
* 4);
1887 stream_putc (s
, BGP_ATTR_FLAG_OPTIONAL
|BGP_ATTR_FLAG_TRANS
);
1888 stream_putc (s
, BGP_ATTR_COMMUNITIES
);
1889 stream_putc (s
, attr
->community
->size
* 4);
1891 stream_put (s
, attr
->community
->val
, attr
->community
->size
* 4);
1895 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
1896 if(prefix
!= NULL
&& prefix
->family
== AF_INET6
&&
1897 (attr
->mp_nexthop_len
== 16 || attr
->mp_nexthop_len
== 32) )
1901 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
1902 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
1903 sizep
= stream_get_putp (s
);
1906 stream_putc (s
, 0); /* Length of this attribute. */
1907 stream_putw(s
, AFI_IP6
); /* AFI */
1908 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
1911 stream_putc(s
, attr
->mp_nexthop_len
);
1912 stream_put(s
, &attr
->mp_nexthop_global
, 16);
1913 if(attr
->mp_nexthop_len
== 32)
1914 stream_put(s
, &attr
->mp_nexthop_local
, 16);
1920 stream_put_prefix(s
, prefix
);
1922 /* Set MP attribute length. */
1923 stream_putc_at (s
, sizep
, (stream_get_putp (s
) - sizep
) - 1);
1925 #endif /* HAVE_IPV6 */
1927 /* Return total size of attribute. */
1928 len
= stream_get_putp (s
) - cp
- 2;
1929 stream_putw_at (s
, cp
, len
);