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 (caddr_t pnt, int length)
89
struct cluster_list tmp;
90
struct cluster_list *cluster;
93
tmp.list = (struct in_addr *) pnt;
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;
860
attr->community = community_parse (stream_pnt (peer->ibuf), length);
861
stream_forward (peer->ibuf, length);
864
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
869
/* Originator ID attribute. */
871
bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
872
struct attr *attr, u_char flag)
876
zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
878
bgp_notify_send (peer,
879
BGP_NOTIFY_UPDATE_ERR,
880
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
884
attr->originator_id.s_addr = stream_get_ipv4 (peer->ibuf);
886
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
891
/* Cluster list attribute. */
893
bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
894
struct attr *attr, u_char flag)
899
zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
901
bgp_notify_send (peer,
902
BGP_NOTIFY_UPDATE_ERR,
903
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
907
attr->cluster = cluster_parse (stream_pnt (peer->ibuf), length);
909
stream_forward (peer->ibuf, length);;
911
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
916
/* Multiprotocol reachability information parse. */
918
bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
919
struct bgp_nlri *mp_update)
930
/* Set end of packet. */
932
lim = stream_pnt (s) + length;
934
/* Load AFI, SAFI. */
935
afi = stream_getw (s);
936
safi = stream_getc (s);
938
/* Get nexthop length. */
939
attr->mp_nexthop_len = stream_getc (s);
941
/* Nexthop length check. */
942
switch (attr->mp_nexthop_len)
945
stream_get (&attr->mp_nexthop_global_in, s, 4);
952
rd_high = stream_getl (s);
953
rd_low = stream_getl (s);
954
stream_get (&attr->mp_nexthop_global_in, s, 4);
959
stream_get (&attr->mp_nexthop_global, s, 16);
962
stream_get (&attr->mp_nexthop_global, s, 16);
963
stream_get (&attr->mp_nexthop_local, s, 16);
964
if (! IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local))
966
char buf1[INET6_ADDRSTRLEN];
967
char buf2[INET6_ADDRSTRLEN];
969
if (BGP_DEBUG (update, UPDATE_IN))
970
zlog_warn ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
971
inet_ntop (AF_INET6, &attr->mp_nexthop_global,
972
buf1, INET6_ADDRSTRLEN),
973
inet_ntop (AF_INET6, &attr->mp_nexthop_local,
974
buf2, INET6_ADDRSTRLEN));
976
attr->mp_nexthop_len = 16;
979
#endif /* HAVE_IPV6 */
981
zlog_info ("Wrong multiprotocol next hop length: %d",
982
attr->mp_nexthop_len);
987
snpa_num = stream_getc (s);
991
snpa_len = stream_getc (s);
992
stream_forward (s, (snpa_len + 1) >> 1);
995
/* If peer is based on old draft-00. I read NLRI length from the
997
if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
999
bgp_size_t nlri_total_len;
1000
nlri_total_len = stream_getw (s);
1003
nlri_len = lim - stream_pnt (s);
1005
if (safi != BGP_SAFI_VPNV4)
1007
ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
1012
mp_update->afi = afi;
1013
mp_update->safi = safi;
1014
mp_update->nlri = stream_pnt (s);
1015
mp_update->length = nlri_len;
1017
stream_forward (s, nlri_len);
1022
/* Multiprotocol unreachable parse */
1024
bgp_mp_unreach_parse (struct peer *peer, int length,
1025
struct bgp_nlri *mp_withdraw)
1031
u_int16_t withdraw_len;
1035
lim = stream_pnt (s) + length;
1037
afi = stream_getw (s);
1038
safi = stream_getc (s);
1040
withdraw_len = lim - stream_pnt (s);
1042
if (safi != BGP_SAFI_VPNV4)
1044
ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
1049
mp_withdraw->afi = afi;
1050
mp_withdraw->safi = safi;
1051
mp_withdraw->nlri = stream_pnt (s);
1052
mp_withdraw->length = withdraw_len;
1054
stream_forward (s, withdraw_len);
1059
/* Extended Community attribute. */
1061
bgp_attr_ext_communities (struct peer *peer, bgp_size_t length,
1062
struct attr *attr, u_char flag)
1065
attr->ecommunity = NULL;
1068
attr->ecommunity = ecommunity_parse (stream_pnt (peer->ibuf), length);
1069
stream_forward (peer->ibuf, length);
1071
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1076
/* BGP unknown attribute treatment. */
1078
bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
1079
u_char type, bgp_size_t length, u_char *startp)
1082
struct transit *transit;
1084
if (BGP_DEBUG (events, EVENTS))
1085
zlog (peer->log, LOG_INFO,
1086
"Unknown attribute type %d length %d is received", type, length);
1088
/* Forward read pointer of input stream. */
1089
stream_forward (peer->ibuf, length);
1091
/* Adjest total length to include type and length. */
1092
total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1094
/* If any of the mandatory well-known attributes are not recognized,
1095
then the Error Subcode is set to Unrecognized Well-known
1096
Attribute. The Data field contains the unrecognized attribute
1097
(type, length and value). */
1098
if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
1100
/* Adjust startp to do not include flag value. */
1101
bgp_notify_send_with_data (peer,
1102
BGP_NOTIFY_UPDATE_ERR,
1103
BGP_NOTIFY_UPDATE_UNREC_ATTR,
1108
/* Unrecognized non-transitive optional attributes must be quietly
1109
ignored and not passed along to other BGP peers. */
1110
if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
1113
/* If a path with recognized transitive optional attribute is
1114
accepted and passed along to other BGP peers and the Partial bit
1115
in the Attribute Flags octet is set to 1 by some previous AS, it
1116
is not set back to 0 by the current AS. */
1117
SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1119
/* Store transitive attribute to the end of attr->transit. */
1120
if (! attr->transit)
1122
attr->transit = XMALLOC (MTYPE_TRANSIT, sizeof (struct transit));
1123
memset (attr->transit, 0, sizeof (struct transit));
1126
transit = attr->transit;
1129
transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1130
transit->length + total);
1132
transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1134
memcpy (transit->val + transit->length, startp, total);
1135
transit->length += total;
1140
/* Read attribute of update packet. This function is called from
1141
bgp_update() in bgpd.c. */
1143
bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1144
struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1150
u_char *startp, *endp;
1152
u_char seen[BGP_ATTR_BITMAP_SIZE];
1154
/* Initialize bitmap. */
1155
memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1157
/* End pointer of BGP attribute. */
1158
endp = BGP_INPUT_PNT (peer) + size;
1160
/* Get attributes to the end of attribute length. */
1161
while (BGP_INPUT_PNT (peer) < endp)
1163
/* Check remaining length check.*/
1164
if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1166
zlog (peer->log, LOG_WARNING,
1167
"%s error BGP attribute length %d is smaller than min len",
1168
peer->host, endp - STREAM_PNT (BGP_INPUT (peer)));
1170
bgp_notify_send (peer,
1171
BGP_NOTIFY_UPDATE_ERR,
1172
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1176
/* Fetch attribute flag and type. */
1177
startp = BGP_INPUT_PNT (peer);
1178
flag = stream_getc (BGP_INPUT (peer));
1179
type = stream_getc (BGP_INPUT (peer));
1181
/* Check extended attribue length bit. */
1182
if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1183
length = stream_getw (BGP_INPUT (peer));
1185
length = stream_getc (BGP_INPUT (peer));
1187
/* If any attribute appears more than once in the UPDATE
1188
message, then the Error Subcode is set to Malformed Attribute
1191
if (CHECK_BITMAP (seen, type))
1193
zlog (peer->log, LOG_WARNING,
1194
"%s error BGP attribute type %d appears twice in a message",
1197
bgp_notify_send (peer,
1198
BGP_NOTIFY_UPDATE_ERR,
1199
BGP_NOTIFY_UPDATE_MAL_ATTR);
1203
/* Set type to bitmap to check duplicate attribute. `type' is
1204
unsigned char so it never overflow bitmap range. */
1206
SET_BITMAP (seen, type);
1208
/* Overflow check. */
1209
attr_endp = BGP_INPUT_PNT (peer) + length;
1211
if (attr_endp > endp)
1213
zlog (peer->log, LOG_WARNING,
1214
"%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);
1215
bgp_notify_send (peer,
1216
BGP_NOTIFY_UPDATE_ERR,
1217
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1221
/* OK check attribute and store it's value. */
1224
case BGP_ATTR_ORIGIN:
1225
ret = bgp_attr_origin (peer, length, attr, flag, startp);
1227
case BGP_ATTR_AS_PATH:
1228
ret = bgp_attr_aspath (peer, length, attr, flag, startp);
1230
case BGP_ATTR_NEXT_HOP:
1231
ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
1233
case BGP_ATTR_MULTI_EXIT_DISC:
1234
ret = bgp_attr_med (peer, length, attr, flag, startp);
1236
case BGP_ATTR_LOCAL_PREF:
1237
ret = bgp_attr_local_pref (peer, length, attr, flag);
1239
case BGP_ATTR_ATOMIC_AGGREGATE:
1240
ret = bgp_attr_atomic (peer, length, attr, flag);
1242
case BGP_ATTR_AGGREGATOR:
1243
ret = bgp_attr_aggregator (peer, length, attr, flag);
1245
case BGP_ATTR_COMMUNITIES:
1246
ret = bgp_attr_community (peer, length, attr, flag);
1248
case BGP_ATTR_ORIGINATOR_ID:
1249
ret = bgp_attr_originator_id (peer, length, attr, flag);
1251
case BGP_ATTR_CLUSTER_LIST:
1252
ret = bgp_attr_cluster_list (peer, length, attr, flag);
1254
case BGP_ATTR_MP_REACH_NLRI:
1255
ret = bgp_mp_reach_parse (peer, length, attr, mp_update);
1257
case BGP_ATTR_MP_UNREACH_NLRI:
1258
ret = bgp_mp_unreach_parse (peer, length, mp_withdraw);
1260
case BGP_ATTR_EXT_COMMUNITIES:
1261
ret = bgp_attr_ext_communities (peer, length, attr, flag);
1264
ret = bgp_attr_unknown (peer, attr, flag, type, length, startp);
1268
/* If error occured immediately return to the caller. */
1272
/* Check the fetched length. */
1273
if (BGP_INPUT_PNT (peer) != attr_endp)
1275
zlog (peer->log, LOG_WARNING,
1276
"%s BGP attribute fetch error", peer->host);
1277
bgp_notify_send (peer,
1278
BGP_NOTIFY_UPDATE_ERR,
1279
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1284
/* Check final read pointer is same as end pointer. */
1285
if (BGP_INPUT_PNT (peer) != endp)
1287
zlog (peer->log, LOG_WARNING,
1288
"%s BGP attribute length mismatch", peer->host);
1289
bgp_notify_send (peer,
1290
BGP_NOTIFY_UPDATE_ERR,
1291
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1295
/* Finally intern unknown attribute. */
1297
attr->transit = transit_intern (attr->transit);
1302
/* Well-known attribute check. */
1304
bgp_attr_check (struct peer *peer, struct attr *attr)
1308
if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
1309
type = BGP_ATTR_ORIGIN;
1311
if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
1312
type = BGP_ATTR_AS_PATH;
1314
if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
1315
type = BGP_ATTR_NEXT_HOP;
1317
if (peer_sort (peer) == BGP_PEER_IBGP
1318
&& ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
1319
type = BGP_ATTR_LOCAL_PREF;
1323
zlog (peer->log, LOG_WARNING,
1324
"%s Missing well-known attribute %d.",
1326
bgp_notify_send_with_data (peer,
1327
BGP_NOTIFY_UPDATE_ERR,
1328
BGP_NOTIFY_UPDATE_MISS_ATTR,
1335
int stream_put_prefix (struct stream *, struct prefix *);
1337
/* Make attribute packet. */
1339
bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
1340
struct stream *s, struct attr *attr, struct prefix *p,
1341
afi_t afi, safi_t safi, struct peer *from,
1342
struct prefix_rd *prd, u_char *tag)
1345
struct aspath *aspath;
1348
bgp = bgp_get_default ();
1350
/* Remember current pointer. */
1351
cp = stream_get_putp (s);
1353
/* Origin attribute. */
1354
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1355
stream_putc (s, BGP_ATTR_ORIGIN);
1357
stream_putc (s, attr->origin);
1359
/* AS path attribute. */
1361
/* If remote-peer is EBGP */
1362
if (peer_sort (peer) == BGP_PEER_EBGP
1363
&& (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
1364
|| attr->aspath->length == 0)
1365
&& ! (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1366
&& CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
1368
aspath = aspath_dup (attr->aspath);
1370
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
1372
/* Strip the confed info, and then stuff our path CONFED_ID
1374
aspath = aspath_delete_confed_seq (aspath);
1375
aspath = aspath_add_seq (aspath, bgp->confed_id);
1379
aspath = aspath_add_seq (aspath, peer->local_as);
1380
if (peer->change_local_as)
1381
aspath = aspath_add_seq (aspath, peer->change_local_as);
1384
else if (peer_sort (peer) == BGP_PEER_CONFED)
1386
/* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
1387
aspath = aspath_dup (attr->aspath);
1388
aspath = aspath_add_confed_seq (aspath, peer->local_as);
1391
aspath = attr->aspath;
1393
/* AS path attribute extended length bit check. */
1394
if (aspath->length > 255)
1396
stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1397
stream_putc (s, BGP_ATTR_AS_PATH);
1398
stream_putw (s, aspath->length);
1402
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1403
stream_putc(s, BGP_ATTR_AS_PATH);
1404
stream_putc (s, aspath->length);
1406
stream_put (s, aspath->data, aspath->length);
1408
if (aspath != attr->aspath)
1409
aspath_free (aspath);
1411
/* Nexthop attribute. */
1412
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
1414
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1415
stream_putc (s, BGP_ATTR_NEXT_HOP);
1417
if (safi == SAFI_MPLS_VPN)
1419
if (attr->nexthop.s_addr == 0)
1420
stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
1422
stream_put_ipv4 (s, attr->nexthop.s_addr);
1425
stream_put_ipv4 (s, attr->nexthop.s_addr);
1428
/* MED attribute. */
1429
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
1431
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1432
stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
1434
stream_putl (s, attr->med);
1437
/* Local preference. */
1438
if (peer_sort (peer) == BGP_PEER_IBGP ||
1439
peer_sort (peer) == BGP_PEER_CONFED)
1441
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1442
stream_putc (s, BGP_ATTR_LOCAL_PREF);
1444
stream_putl (s, attr->local_pref);
1447
/* Atomic aggregate. */
1448
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
1450
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1451
stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
1456
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
1458
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1459
stream_putc (s, BGP_ATTR_AGGREGATOR);
1461
stream_putw (s, attr->aggregator_as);
1462
stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
1465
/* Community attribute. */
1466
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
1467
&& (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
1469
if (attr->community->size * 4 > 255)
1471
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1472
stream_putc (s, BGP_ATTR_COMMUNITIES);
1473
stream_putw (s, attr->community->size * 4);
1477
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1478
stream_putc (s, BGP_ATTR_COMMUNITIES);
1479
stream_putc (s, attr->community->size * 4);
1481
stream_put (s, attr->community->val, attr->community->size * 4);
1484
/* Route Reflector. */
1485
if (peer_sort (peer) == BGP_PEER_IBGP
1487
&& peer_sort (from) == BGP_PEER_IBGP)
1489
/* Originator ID. */
1490
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1491
stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
1494
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1495
stream_put_in_addr (s, &attr->originator_id);
1499
stream_put_in_addr (s, &from->remote_id);
1501
stream_put_in_addr (s, &attr->originator_id);
1505
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1506
stream_putc (s, BGP_ATTR_CLUSTER_LIST);
1510
stream_putc (s, attr->cluster->length + 4);
1511
/* If this peer configuration's parent BGP has cluster_id. */
1512
if (bgp->config & BGP_CONFIG_CLUSTER_ID)
1513
stream_put_in_addr (s, &bgp->cluster_id);
1515
stream_put_in_addr (s, &bgp->router_id);
1516
stream_put (s, attr->cluster->list, attr->cluster->length);
1521
/* If this peer configuration's parent BGP has cluster_id. */
1522
if (bgp->config & BGP_CONFIG_CLUSTER_ID)
1523
stream_put_in_addr (s, &bgp->cluster_id);
1525
stream_put_in_addr (s, &bgp->router_id);
1530
/* If p is IPv6 address put it into attribute. */
1531
if (p->family == AF_INET6)
1533
unsigned long sizep;
1534
unsigned long draftp = 0;
1536
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1537
stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
1538
sizep = stream_get_putp (s);
1539
stream_putc (s, 0); /* Length of this attribute. */
1540
stream_putw (s, AFI_IP6); /* AFI */
1541
stream_putc (s, safi); /* SAFI */
1543
stream_putc (s, attr->mp_nexthop_len);
1545
if (attr->mp_nexthop_len == 16)
1546
stream_put (s, &attr->mp_nexthop_global, 16);
1547
else if (attr->mp_nexthop_len == 32)
1549
stream_put (s, &attr->mp_nexthop_global, 16);
1550
stream_put (s, &attr->mp_nexthop_local, 16);
1556
/* In case of old draft BGP-4+. */
1557
if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1559
draftp = stream_get_putp (s);
1564
stream_put_prefix (s, p);
1566
/* Set MP attribute length. */
1567
stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
1569
/* In case of old draft BGP-4+. */
1570
if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1571
stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
1573
#endif /* HAVE_IPV6 */
1575
if (p->family == AF_INET && safi == SAFI_MULTICAST)
1577
unsigned long sizep;
1578
unsigned long draftp = 0;
1580
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1581
stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
1582
sizep = stream_get_putp (s);
1583
stream_putc (s, 0); /* Length of this attribute. */
1584
stream_putw (s, AFI_IP); /* AFI */
1585
stream_putc (s, SAFI_MULTICAST); /* SAFI */
1588
stream_put_ipv4 (s, attr->nexthop.s_addr);
1593
/* In case of old draft BGP-4+. */
1594
if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1596
draftp = stream_get_putp (s);
1601
stream_put_prefix (s, p);
1603
/* Set MP attribute length. */
1604
stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
1606
/* In case of old draft BGP-4+. */
1607
if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1608
stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
1611
if (p->family == AF_INET && safi == SAFI_MPLS_VPN)
1613
unsigned long sizep;
1614
unsigned long draftp = 0;
1616
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1617
stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
1618
sizep = stream_get_putp (s);
1619
stream_putc (s, 0); /* Length of this attribute. */
1620
stream_putw (s, AFI_IP); /* AFI */
1621
stream_putc (s, BGP_SAFI_VPNV4); /* SAFI */
1623
stream_putc (s, 12);
1626
stream_put (s, &attr->mp_nexthop_global_in, 4);
1631
/* In case of old draft BGP-4+. */
1632
if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1634
draftp = stream_get_putp (s);
1638
/* Tag, RD, Prefix write. */
1639
stream_putc (s, p->prefixlen + 88);
1640
stream_put (s, tag, 3);
1641
stream_put (s, prd->val, 8);
1642
stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
1644
/* Set MP attribute length. */
1645
stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
1647
/* In case of old draft BGP-4+. */
1648
if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1649
stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
1652
/* Extended Communities attribute. */
1653
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
1654
&& (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
1656
if (attr->ecommunity->size * 8 > 255)
1658
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1659
stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
1660
stream_putw (s, attr->ecommunity->size * 8);
1664
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1665
stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
1666
stream_putc (s, attr->ecommunity->size * 8);
1668
stream_put (s, attr->ecommunity->val, attr->ecommunity->size * 8);
1671
/* Unknown transit attribute. */
1673
stream_put (s, attr->transit->val, attr->transit->length);
1675
/* Return total size of attribute. */
1676
return stream_get_putp (s) - cp;
1680
bgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p,
1681
afi_t afi, safi_t safi, struct prefix_rd *prd,
1685
unsigned long attrlen_pnt;
1688
cp = stream_get_putp (s);
1690
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1691
stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
1693
attrlen_pnt = stream_get_putp (s);
1694
stream_putc (s, 0); /* Length of this attribute. */
1696
stream_putw (s, family2afi (p->family));
1698
if (safi == SAFI_MPLS_VPN)
1701
stream_putc (s, BGP_SAFI_VPNV4);
1704
stream_putc (s, p->prefixlen + 88);
1705
stream_put (s, tag, 3);
1706
stream_put (s, prd->val, 8);
1707
stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
1712
stream_putc (s, safi);
1715
stream_put_prefix (s, p);
1718
/* Set MP attribute length. */
1719
size = stream_get_putp (s) - attrlen_pnt - 1;
1720
stream_putc_at (s, attrlen_pnt, size);
1722
return stream_get_putp (s) - cp;
1725
/* Initialization of attribute. */
1729
void attrhash_init ();
1739
/* Make attribute packet. */
1741
bgp_dump_routes_attr (struct stream *s, struct attr *attr,
1742
struct prefix *prefix)
1746
struct aspath *aspath;
1748
/* Remember current pointer. */
1749
cp = stream_get_putp (s);
1751
/* Place holder of length. */
1754
/* Origin attribute. */
1755
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1756
stream_putc (s, BGP_ATTR_ORIGIN);
1758
stream_putc (s, attr->origin);
1760
aspath = attr->aspath;
1762
if (aspath->length > 255)
1764
stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1765
stream_putc (s, BGP_ATTR_AS_PATH);
1766
stream_putw (s, aspath->length);
1770
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1771
stream_putc (s, BGP_ATTR_AS_PATH);
1772
stream_putc (s, aspath->length);
1774
stream_put (s, aspath->data, aspath->length);
1776
/* Nexthop attribute. */
1777
/* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
1780
&& prefix->family != AF_INET6
1781
#endif /* HAVE_IPV6 */
1784
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1785
stream_putc (s, BGP_ATTR_NEXT_HOP);
1787
stream_put_ipv4 (s, attr->nexthop.s_addr);
1790
/* MED attribute. */
1791
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
1793
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1794
stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
1796
stream_putl (s, attr->med);
1799
/* Local preference. */
1800
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
1802
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1803
stream_putc (s, BGP_ATTR_LOCAL_PREF);
1805
stream_putl (s, attr->local_pref);
1808
/* Atomic aggregate. */
1809
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
1811
stream_putc (s, BGP_ATTR_FLAG_TRANS);
1812
stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
1817
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
1819
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1820
stream_putc (s, BGP_ATTR_AGGREGATOR);
1822
stream_putw (s, attr->aggregator_as);
1823
stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
1826
/* Community attribute. */
1827
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
1829
if (attr->community->size * 4 > 255)
1831
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1832
stream_putc (s, BGP_ATTR_COMMUNITIES);
1833
stream_putw (s, attr->community->size * 4);
1837
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1838
stream_putc (s, BGP_ATTR_COMMUNITIES);
1839
stream_putc (s, attr->community->size * 4);
1841
stream_put (s, attr->community->val, attr->community->size * 4);
1845
/* Add a MP_NLRI attribute to dump the IPv6 next hop */
1846
if(prefix != NULL && prefix->family == AF_INET6 &&
1847
(attr->mp_nexthop_len == 16 || attr->mp_nexthop_len == 32) )
1851
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
1852
stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
1853
sizep = stream_get_putp (s);
1856
stream_putc (s, 0); /* Length of this attribute. */
1857
stream_putw(s, AFI_IP6); /* AFI */
1858
stream_putc(s, SAFI_UNICAST); /* SAFI */
1861
stream_putc(s, attr->mp_nexthop_len);
1862
stream_put(s, &attr->mp_nexthop_global, 16);
1863
if(attr->mp_nexthop_len == 32)
1864
stream_put(s, &attr->mp_nexthop_local, 16);
1870
stream_put_prefix(s, prefix);
1872
/* Set MP attribute length. */
1873
stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
1875
#endif /* HAVE_IPV6 */
1877
/* Return total size of attribute. */
1878
len = stream_get_putp (s) - cp - 2;
1879
stream_putw_at (s, cp, len);