]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_attr.c
bgpd: add replace-as modifier for BGP neighbor
[mirror_frr.git] / bgpd / bgp_attr.c
CommitLineData
718e3744 1/* BGP attributes management routines.
2 Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "linklist.h"
24#include "prefix.h"
25#include "memory.h"
26#include "vector.h"
27#include "vty.h"
28#include "stream.h"
29#include "log.h"
30#include "hash.h"
c8e7b895 31#include "jhash.h"
718e3744 32
33#include "bgpd/bgpd.h"
34#include "bgpd/bgp_attr.h"
35#include "bgpd/bgp_route.h"
36#include "bgpd/bgp_aspath.h"
37#include "bgpd/bgp_community.h"
38#include "bgpd/bgp_debug.h"
39#include "bgpd/bgp_packet.h"
40#include "bgpd/bgp_ecommunity.h"
41\f
42/* Attribute strings for logging. */
9bddac4b 43static const struct message attr_str [] =
718e3744 44{
45 { BGP_ATTR_ORIGIN, "ORIGIN" },
46 { BGP_ATTR_AS_PATH, "AS_PATH" },
47 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
48 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
49 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
50 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
51 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
52 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
53 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
f8627ff1 54 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
718e3744 55 { BGP_ATTR_DPA, "DPA" },
56 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
57 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
58 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
59 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
0b2aa3a0
PJ
60 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
61 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
62 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
63 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
718e3744 64};
837d16cc 65static const int attr_str_max = array_size(attr_str);
afcb7679
DO
66
67static const struct message attr_flag_str[] =
68{
69 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
70 { BGP_ATTR_FLAG_TRANS, "Transitive" },
71 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
72 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
73 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
74};
837d16cc 75static const size_t attr_flag_str_max = array_size(attr_flag_str);
718e3744 76\f
9bddac4b 77static struct hash *cluster_hash;
718e3744 78
94f2b392 79static void *
923de654 80cluster_hash_alloc (void *p)
718e3744 81{
923de654 82 struct cluster_list * val = (struct cluster_list *) p;
718e3744 83 struct cluster_list *cluster;
84
85 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
86 cluster->length = val->length;
87
88 if (cluster->length)
89 {
90 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
91 memcpy (cluster->list, val->list, val->length);
92 }
93 else
94 cluster->list = NULL;
95
96 cluster->refcnt = 0;
97
98 return cluster;
99}
100
101/* Cluster list related functions. */
94f2b392 102static struct cluster_list *
5228ad27 103cluster_parse (struct in_addr * pnt, int length)
718e3744 104{
105 struct cluster_list tmp;
106 struct cluster_list *cluster;
107
108 tmp.length = length;
5228ad27 109 tmp.list = pnt;
718e3744 110
111 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
112 cluster->refcnt++;
113 return cluster;
114}
115
116int
117cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
118{
119 int i;
120
121 for (i = 0; i < cluster->length / 4; i++)
122 if (cluster->list[i].s_addr == originator.s_addr)
123 return 1;
124 return 0;
125}
126
94f2b392 127static unsigned int
923de654 128cluster_hash_key_make (void *p)
718e3744 129{
c8e7b895 130 const struct cluster_list *cluster = p;
718e3744 131
c8e7b895 132 return jhash(cluster->list, cluster->length, 0);
718e3744 133}
134
94f2b392 135static int
ffe11cfb 136cluster_hash_cmp (const void *p1, const void *p2)
718e3744 137{
ffe11cfb
SH
138 const struct cluster_list * cluster1 = p1;
139 const struct cluster_list * cluster2 = p2;
923de654 140
ffe11cfb
SH
141 return (cluster1->length == cluster2->length &&
142 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
718e3744 143}
144
94f2b392 145static void
718e3744 146cluster_free (struct cluster_list *cluster)
147{
148 if (cluster->list)
149 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
150 XFREE (MTYPE_CLUSTER, cluster);
151}
152
228da428 153#if 0
94f2b392 154static struct cluster_list *
718e3744 155cluster_dup (struct cluster_list *cluster)
156{
157 struct cluster_list *new;
158
393deb9b 159 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
718e3744 160 new->length = cluster->length;
161
162 if (cluster->length)
163 {
164 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
165 memcpy (new->list, cluster->list, cluster->length);
166 }
167 else
168 new->list = NULL;
169
170 return new;
171}
228da428 172#endif
718e3744 173
94f2b392 174static struct cluster_list *
718e3744 175cluster_intern (struct cluster_list *cluster)
176{
177 struct cluster_list *find;
178
179 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
180 find->refcnt++;
181
182 return find;
183}
184
185void
186cluster_unintern (struct cluster_list *cluster)
187{
718e3744 188 if (cluster->refcnt)
189 cluster->refcnt--;
190
191 if (cluster->refcnt == 0)
192 {
9206f9ec 193 hash_release (cluster_hash, cluster);
718e3744 194 cluster_free (cluster);
195 }
196}
197
94f2b392 198static void
199cluster_init (void)
718e3744 200{
201 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
202}
228da428
CC
203
204static void
205cluster_finish (void)
206{
207 hash_free (cluster_hash);
208 cluster_hash = NULL;
209}
718e3744 210\f
211/* Unknown transit attribute. */
9bddac4b 212static struct hash *transit_hash;
718e3744 213
94f2b392 214static void
718e3744 215transit_free (struct transit *transit)
216{
217 if (transit->val)
218 XFREE (MTYPE_TRANSIT_VAL, transit->val);
219 XFREE (MTYPE_TRANSIT, transit);
220}
221
923de654 222
94f2b392 223static void *
923de654 224transit_hash_alloc (void *p)
718e3744 225{
226 /* Transit structure is already allocated. */
923de654 227 return p;
718e3744 228}
229
94f2b392 230static struct transit *
718e3744 231transit_intern (struct transit *transit)
232{
233 struct transit *find;
234
235 find = hash_get (transit_hash, transit, transit_hash_alloc);
236 if (find != transit)
237 transit_free (transit);
238 find->refcnt++;
239
240 return find;
241}
242
243void
244transit_unintern (struct transit *transit)
245{
718e3744 246 if (transit->refcnt)
247 transit->refcnt--;
248
249 if (transit->refcnt == 0)
250 {
9206f9ec 251 hash_release (transit_hash, transit);
718e3744 252 transit_free (transit);
253 }
254}
255
94f2b392 256static unsigned int
923de654 257transit_hash_key_make (void *p)
718e3744 258{
c8e7b895 259 const struct transit * transit = p;
718e3744 260
c8e7b895 261 return jhash(transit->val, transit->length, 0);
718e3744 262}
263
94f2b392 264static int
ffe11cfb 265transit_hash_cmp (const void *p1, const void *p2)
718e3744 266{
ffe11cfb
SH
267 const struct transit * transit1 = p1;
268 const struct transit * transit2 = p2;
923de654 269
ffe11cfb
SH
270 return (transit1->length == transit2->length &&
271 memcmp (transit1->val, transit2->val, transit1->length) == 0);
718e3744 272}
273
94f2b392 274static void
66e5cd87 275transit_init (void)
718e3744 276{
277 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
278}
228da428
CC
279
280static void
281transit_finish (void)
282{
283 hash_free (transit_hash);
284 transit_hash = NULL;
285}
718e3744 286\f
287/* Attribute hash routines. */
9bddac4b 288static struct hash *attrhash;
718e3744 289
fb982c25
PJ
290static struct attr_extra *
291bgp_attr_extra_new (void)
292{
293 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
294}
295
296void
297bgp_attr_extra_free (struct attr *attr)
298{
299 if (attr->extra)
300 {
301 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
302 attr->extra = NULL;
303 }
304}
305
306struct attr_extra *
307bgp_attr_extra_get (struct attr *attr)
308{
309 if (!attr->extra)
310 attr->extra = bgp_attr_extra_new();
311 return attr->extra;
312}
313
314/* Shallow copy of an attribute
315 * Though, not so shallow that it doesn't copy the contents
316 * of the attr_extra pointed to by 'extra'
317 */
318void
319bgp_attr_dup (struct attr *new, struct attr *orig)
320{
558d1fec
JBD
321 struct attr_extra *extra = new->extra;
322
fb982c25
PJ
323 *new = *orig;
324 if (orig->extra)
325 {
558d1fec
JBD
326 /* if caller provided attr_extra space use it */
327 if (! extra)
328 new->extra = bgp_attr_extra_new();
fb982c25
PJ
329 *new->extra = *orig->extra;
330 }
331}
332
cbdfbaa5
PJ
333unsigned long int
334attr_count (void)
335{
336 return attrhash->count;
337}
338
339unsigned long int
340attr_unknown_count (void)
341{
342 return transit_hash->count;
343}
344
718e3744 345unsigned int
923de654 346attrhash_key_make (void *p)
718e3744 347{
7fb0cd82
JBD
348 const struct attr *attr = (struct attr *) p;
349 const struct attr_extra *extra = attr->extra;
c8e7b895
SH
350 uint32_t key = 0;
351#define MIX(val) key = jhash_1word(val, key)
352
353 MIX(attr->origin);
354 MIX(attr->nexthop.s_addr);
355 MIX(attr->med);
356 MIX(attr->local_pref);
718e3744 357
c8f3fe30
PJ
358 key += attr->origin;
359 key += attr->nexthop.s_addr;
360 key += attr->med;
361 key += attr->local_pref;
fb982c25 362
7fb0cd82 363 if (extra)
fb982c25 364 {
7fb0cd82
JBD
365 MIX(extra->aggregator_as);
366 MIX(extra->aggregator_addr.s_addr);
367 MIX(extra->weight);
368 MIX(extra->mp_nexthop_global_in.s_addr);
fb982c25
PJ
369 }
370
718e3744 371 if (attr->aspath)
c8e7b895 372 MIX(aspath_key_make (attr->aspath));
718e3744 373 if (attr->community)
c8e7b895 374 MIX(community_hash_make (attr->community));
fb982c25 375
7fb0cd82 376 if (extra)
fb982c25 377 {
7fb0cd82
JBD
378 if (extra->ecommunity)
379 MIX(ecommunity_hash_make (extra->ecommunity));
380 if (extra->cluster)
381 MIX(cluster_hash_key_make (extra->cluster));
382 if (extra->transit)
383 MIX(transit_hash_key_make (extra->transit));
718e3744 384
385#ifdef HAVE_IPV6
7fb0cd82
JBD
386 MIX(extra->mp_nexthop_len);
387 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
388 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
718e3744 389#endif /* HAVE_IPV6 */
fb982c25 390 }
718e3744 391
392 return key;
393}
394
395int
ffe11cfb 396attrhash_cmp (const void *p1, const void *p2)
718e3744 397{
ffe11cfb
SH
398 const struct attr * attr1 = p1;
399 const struct attr * attr2 = p2;
923de654 400
718e3744 401 if (attr1->flag == attr2->flag
402 && attr1->origin == attr2->origin
403 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
fb982c25
PJ
404 && attr1->aspath == attr2->aspath
405 && attr1->community == attr2->community
718e3744 406 && attr1->med == attr2->med
c8f3fe30 407 && attr1->local_pref == attr2->local_pref)
fb982c25 408 {
ffe11cfb
SH
409 const struct attr_extra *ae1 = attr1->extra;
410 const struct attr_extra *ae2 = attr2->extra;
fb982c25
PJ
411
412 if (ae1 && ae2
413 && ae1->aggregator_as == ae2->aggregator_as
414 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
415 && ae1->weight == ae2->weight
718e3744 416#ifdef HAVE_IPV6
fb982c25
PJ
417 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
418 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
419 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
718e3744 420#endif /* HAVE_IPV6 */
fb982c25
PJ
421 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
422 && ae1->ecommunity == ae2->ecommunity
423 && ae1->cluster == ae2->cluster
424 && ae1->transit == ae2->transit)
425 return 1;
426 else if (ae1 || ae2)
427 return 0;
428 /* neither attribute has extra attributes, so they're same */
429 return 1;
430 }
718e3744 431 else
432 return 0;
433}
434
94f2b392 435static void
ffe11cfb 436attrhash_init (void)
718e3744 437{
438 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
439}
440
228da428
CC
441static void
442attrhash_finish (void)
443{
444 hash_free (attrhash);
445 attrhash = NULL;
446}
447
94f2b392 448static void
718e3744 449attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
450{
451 struct attr *attr = backet->data;
452
453 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
454 inet_ntoa (attr->nexthop), VTY_NEWLINE);
455}
456
457void
458attr_show_all (struct vty *vty)
459{
460 hash_iterate (attrhash,
461 (void (*)(struct hash_backet *, void *))
462 attr_show_all_iterator,
463 vty);
464}
465
94f2b392 466static void *
923de654 467bgp_attr_hash_alloc (void *p)
718e3744 468{
923de654 469 struct attr * val = (struct attr *) p;
718e3744 470 struct attr *attr;
471
472 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
473 *attr = *val;
fb982c25
PJ
474 if (val->extra)
475 {
476 attr->extra = bgp_attr_extra_new ();
477 *attr->extra = *val->extra;
478 }
718e3744 479 attr->refcnt = 0;
480 return attr;
481}
482
483/* Internet argument attribute. */
484struct attr *
485bgp_attr_intern (struct attr *attr)
486{
487 struct attr *find;
488
489 /* Intern referenced strucutre. */
490 if (attr->aspath)
491 {
492 if (! attr->aspath->refcnt)
493 attr->aspath = aspath_intern (attr->aspath);
494 else
495 attr->aspath->refcnt++;
496 }
497 if (attr->community)
498 {
499 if (! attr->community->refcnt)
500 attr->community = community_intern (attr->community);
501 else
502 attr->community->refcnt++;
503 }
fb982c25 504 if (attr->extra)
718e3744 505 {
fb982c25
PJ
506 struct attr_extra *attre = attr->extra;
507
508 if (attre->ecommunity)
509 {
510 if (! attre->ecommunity->refcnt)
511 attre->ecommunity = ecommunity_intern (attre->ecommunity);
512 else
513 attre->ecommunity->refcnt++;
f6f434b2 514
fb982c25
PJ
515 }
516 if (attre->cluster)
517 {
518 if (! attre->cluster->refcnt)
519 attre->cluster = cluster_intern (attre->cluster);
520 else
521 attre->cluster->refcnt++;
522 }
523 if (attre->transit)
524 {
525 if (! attre->transit->refcnt)
526 attre->transit = transit_intern (attre->transit);
527 else
528 attre->transit->refcnt++;
529 }
718e3744 530 }
f6f434b2 531
718e3744 532 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
533 find->refcnt++;
f6f434b2 534
718e3744 535 return find;
536}
537
03e214c8 538
718e3744 539/* Make network statement's attribute. */
540struct attr *
541bgp_attr_default_set (struct attr *attr, u_char origin)
542{
543 memset (attr, 0, sizeof (struct attr));
fb982c25
PJ
544 bgp_attr_extra_get (attr);
545
718e3744 546 attr->origin = origin;
547 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
548 attr->aspath = aspath_empty ();
549 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
fb982c25 550 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
718e3744 551 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
552#ifdef HAVE_IPV6
fb982c25 553 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
718e3744 554#endif
03e214c8 555
718e3744 556 return attr;
557}
558
03e214c8 559
718e3744 560/* Make network statement's attribute. */
561struct attr *
562bgp_attr_default_intern (u_char origin)
563{
564 struct attr attr;
565 struct attr *new;
e16a4133 566
03e214c8 567 bgp_attr_default_set(&attr, origin);
718e3744 568
569 new = bgp_attr_intern (&attr);
fb982c25
PJ
570 bgp_attr_extra_free (&attr);
571
f6f434b2 572 aspath_unintern (&new->aspath);
718e3744 573 return new;
574}
575
576struct attr *
577bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
578 struct aspath *aspath,
579 struct community *community, int as_set)
580{
581 struct attr attr;
582 struct attr *new;
938ef3a2 583 struct attr_extra attre;
718e3744 584
585 memset (&attr, 0, sizeof (struct attr));
938ef3a2
JBD
586 memset (&attre, 0, sizeof (struct attr_extra));
587 attr.extra = &attre;
588
718e3744 589 /* Origin attribute. */
590 attr.origin = origin;
591 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
592
593 /* AS path attribute. */
594 if (aspath)
595 attr.aspath = aspath_intern (aspath);
596 else
597 attr.aspath = aspath_empty ();
598 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
599
600 /* Next hop attribute. */
601 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
602
603 if (community)
604 {
605 attr.community = community;
606 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
607 }
608
938ef3a2 609 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
718e3744 610#ifdef HAVE_IPV6
938ef3a2 611 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
718e3744 612#endif
613 if (! as_set)
614 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
615 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
616 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
938ef3a2 617 attre.aggregator_as = bgp->confed_id;
718e3744 618 else
938ef3a2
JBD
619 attre.aggregator_as = bgp->as;
620 attre.aggregator_addr = bgp->router_id;
718e3744 621
622 new = bgp_attr_intern (&attr);
938ef3a2 623
f6f434b2 624 aspath_unintern (&new->aspath);
718e3744 625 return new;
626}
627
b881c707
PJ
628/* Unintern just the sub-components of the attr, but not the attr */
629void
630bgp_attr_unintern_sub (struct attr *attr)
631{
632 /* aspath refcount shoud be decrement. */
633 if (attr->aspath)
634 aspath_unintern (&attr->aspath);
635 UNSET_FLAG(attr->flag, BGP_ATTR_AS_PATH);
636
637 if (attr->community)
638 community_unintern (&attr->community);
639 UNSET_FLAG(attr->flag, BGP_ATTR_COMMUNITIES);
640
641 if (attr->extra)
642 {
643 if (attr->extra->ecommunity)
644 ecommunity_unintern (&attr->extra->ecommunity);
645 UNSET_FLAG(attr->flag, BGP_ATTR_EXT_COMMUNITIES);
646
647 if (attr->extra->cluster)
648 cluster_unintern (attr->extra->cluster);
649 UNSET_FLAG(attr->flag, BGP_ATTR_CLUSTER_LIST);
650
651 if (attr->extra->transit)
652 transit_unintern (attr->extra->transit);
653 }
654}
655
718e3744 656/* Free bgp attribute and aspath. */
657void
1a2fd707 658bgp_attr_unintern (struct attr **pattr)
718e3744 659{
1a2fd707 660 struct attr *attr = *pattr;
718e3744 661 struct attr *ret;
b881c707 662 struct attr tmp;
b9f1dca1 663 struct attr_extra tmp_extra;
f6f434b2 664
718e3744 665 /* Decrement attribute reference. */
1a2fd707 666 attr->refcnt--;
b881c707 667
1a2fd707 668 tmp = *attr;
b881c707 669
1a2fd707 670 if (attr->extra)
fb982c25 671 {
b9f1dca1 672 tmp.extra = &tmp_extra;
1a2fd707 673 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
fb982c25 674 }
f6f434b2 675
718e3744 676 /* If reference becomes zero then free attribute object. */
1a2fd707
JBD
677 if (attr->refcnt == 0)
678 {
679 ret = hash_release (attrhash, attr);
718e3744 680 assert (ret != NULL);
1a2fd707
JBD
681 bgp_attr_extra_free (attr);
682 XFREE (MTYPE_ATTR, attr);
683 *pattr = NULL;
718e3744 684 }
685
b881c707 686 bgp_attr_unintern_sub (&tmp);
718e3744 687}
688
689void
690bgp_attr_flush (struct attr *attr)
691{
692 if (attr->aspath && ! attr->aspath->refcnt)
693 aspath_free (attr->aspath);
694 if (attr->community && ! attr->community->refcnt)
695 community_free (attr->community);
fb982c25
PJ
696 if (attr->extra)
697 {
698 struct attr_extra *attre = attr->extra;
f6f434b2 699
fb982c25 700 if (attre->ecommunity && ! attre->ecommunity->refcnt)
f6f434b2 701 ecommunity_free (&attre->ecommunity);
fb982c25
PJ
702 if (attre->cluster && ! attre->cluster->refcnt)
703 cluster_free (attre->cluster);
704 if (attre->transit && ! attre->transit->refcnt)
705 transit_free (attre->transit);
706 }
718e3744 707}
708
b881c707
PJ
709/* Implement draft-scudder-idr-optional-transitive behaviour and
710 * avoid resetting sessions for malformed attributes which are
711 * are partial/optional and hence where the error likely was not
712 * introduced by the sending neighbour.
713 */
714static bgp_attr_parse_ret_t
835315bf
PJ
715bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
716 bgp_size_t length)
b881c707 717{
835315bf
PJ
718 struct peer *const peer = args->peer;
719 const u_int8_t flags = args->flags;
720 /* startp and length must be special-cased, as whether or not to
721 * send the attribute data with the NOTIFY depends on the error,
722 * the caller therefore signals this with the seperate length argument
723 */
bd471fea 724 u_char *notify_datap = (length > 0 ? args->startp : NULL);
835315bf 725
b881c707 726 /* Only relax error handling for eBGP peers */
6d85b15b 727 if (peer->sort != BGP_PEER_EBGP)
b881c707
PJ
728 {
729 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
bd471fea 730 notify_datap, length);
b881c707
PJ
731 return BGP_ATTR_PARSE_ERROR;
732
733 }
734
bd471fea
PJ
735 /* Adjust the stream getp to the end of the attribute, in case we can
736 * still proceed but the caller hasn't read all the attribute.
737 */
738 stream_set_getp (BGP_INPUT (peer),
739 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
740 + args->total);
741
835315bf 742 switch (args->type) {
fa61e16d
PJ
743 /* where an attribute is relatively inconsequential, e.g. it does not
744 * affect route selection, and can be safely ignored, then any such
745 * attributes which are malformed should just be ignored and the route
746 * processed as normal.
b881c707
PJ
747 */
748 case BGP_ATTR_AS4_AGGREGATOR:
749 case BGP_ATTR_AGGREGATOR:
750 case BGP_ATTR_ATOMIC_AGGREGATE:
751 return BGP_ATTR_PARSE_PROCEED;
752
753 /* Core attributes, particularly ones which may influence route
fa61e16d 754 * selection, should always cause session resets
b881c707
PJ
755 */
756 case BGP_ATTR_ORIGIN:
757 case BGP_ATTR_AS_PATH:
758 case BGP_ATTR_NEXT_HOP:
759 case BGP_ATTR_MULTI_EXIT_DISC:
760 case BGP_ATTR_LOCAL_PREF:
761 case BGP_ATTR_COMMUNITIES:
762 case BGP_ATTR_ORIGINATOR_ID:
763 case BGP_ATTR_CLUSTER_LIST:
764 case BGP_ATTR_MP_REACH_NLRI:
765 case BGP_ATTR_MP_UNREACH_NLRI:
766 case BGP_ATTR_EXT_COMMUNITIES:
767 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
bd471fea 768 notify_datap, length);
b881c707
PJ
769 return BGP_ATTR_PARSE_ERROR;
770 }
771
772 /* Partial optional attributes that are malformed should not cause
773 * the whole session to be reset. Instead treat it as a withdrawal
774 * of the routes, if possible.
775 */
835315bf
PJ
776 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
777 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
778 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
b881c707
PJ
779 return BGP_ATTR_PARSE_WITHDRAW;
780
781 /* default to reset */
782 return BGP_ATTR_PARSE_ERROR;
783}
784
afcb7679
DO
785/* Find out what is wrong with the path attribute flag bits and log the error.
786 "Flag bits" here stand for Optional, Transitive and Partial, but not for
787 Extended Length. Checking O/T/P bits at once implies, that the attribute
788 being diagnosed is defined by RFC as either a "well-known" or an "optional,
789 non-transitive" attribute. */
790static void
835315bf
PJ
791bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
792 u_int8_t desired_flags /* how RFC says it must be */
afcb7679
DO
793)
794{
795 u_char seen = 0, i;
835315bf
PJ
796 u_char real_flags = args->flags;
797 const u_int8_t attr_code = args->type;
798
afcb7679
DO
799 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
800 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
801 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
802 if
803 (
804 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
805 CHECK_FLAG (real_flags, attr_flag_str[i].key)
806 )
807 {
835315bf 808 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
afcb7679
DO
809 LOOKUP (attr_str, attr_code),
810 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
811 attr_flag_str[i].str);
812 seen = 1;
813 }
fa5831e8
PJ
814 if (!seen)
815 {
816 zlog (args->peer->log, LOG_DEBUG,
817 "Strange, %s called for attr %s, but no problem found with flags"
818 " (real flags 0x%x, desired 0x%x)",
819 __func__, LOOKUP (attr_str, attr_code),
820 real_flags, desired_flags);
821 }
afcb7679
DO
822}
823
3ecab4c8
PJ
824/* Required flags for attributes. EXTLEN will be masked off when testing,
825 * as will PARTIAL for optional+transitive attributes.
826 */
827const u_int8_t attr_flags_values [] = {
828 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
829 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
830 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
831 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
832 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
833 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
834 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
835 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
836 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
837 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
838 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
839 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
840 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
841 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
842 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
843};
844static const size_t attr_flags_values_max =
845 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
846
847static int
835315bf 848bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
3ecab4c8
PJ
849{
850 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
835315bf
PJ
851 const u_int8_t flags = args->flags;
852 const u_int8_t attr_code = args->type;
853 struct peer *const peer = args->peer;
3ecab4c8
PJ
854
855 /* there may be attributes we don't know about */
856 if (attr_code > attr_flags_values_max)
857 return 0;
858 if (attr_flags_values[attr_code] == 0)
859 return 0;
860
861 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
862 * 1."
863 */
864 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
865 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
866 {
867 zlog (peer->log, LOG_ERR,
868 "%s well-known attributes must have transitive flag set (%x)",
869 LOOKUP (attr_str, attr_code), flags);
870 return 1;
871 }
872
873 /* "For well-known attributes and for optional non-transitive attributes,
874 * the Partial bit MUST be set to 0."
875 */
876 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
877 {
878 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
879 {
880 zlog (peer->log, LOG_ERR,
881 "%s well-known attribute "
882 "must NOT have the partial flag set (%x)",
883 LOOKUP (attr_str, attr_code), flags);
884 return 1;
885 }
886 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
887 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
888 {
889 zlog (peer->log, LOG_ERR,
890 "%s optional + transitive attribute "
891 "must NOT have the partial flag set (%x)",
892 LOOKUP (attr_str, attr_code), flags);
893 return 1;
894 }
895 }
896
897 /* Optional transitive attributes may go through speakers that don't
898 * reocgnise them and set the Partial bit.
899 */
900 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
901 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
902 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
903
683f2b86 904 if ((flags & ~mask)
3ecab4c8
PJ
905 == attr_flags_values[attr_code])
906 return 0;
907
835315bf 908 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
3ecab4c8
PJ
909 return 1;
910}
911
718e3744 912/* Get origin attribute of the update message. */
b881c707 913static bgp_attr_parse_ret_t
835315bf 914bgp_attr_origin (struct bgp_attr_parser_args *args)
718e3744 915{
835315bf
PJ
916 struct peer *const peer = args->peer;
917 struct attr *const attr = args->attr;
918 const bgp_size_t length = args->length;
919
718e3744 920 /* If any recognized attribute has Attribute Length that conflicts
921 with the expected length (based on the attribute type code), then
922 the Error Subcode is set to Attribute Length Error. The Data
923 field contains the erroneous attribute (type, length and
924 value). */
925 if (length != 1)
926 {
927 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
928 length);
835315bf 929 return bgp_attr_malformed (args,
b881c707 930 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 931 args->total);
718e3744 932 }
933
934 /* Fetch origin attribute. */
935 attr->origin = stream_getc (BGP_INPUT (peer));
936
937 /* If the ORIGIN attribute has an undefined value, then the Error
938 Subcode is set to Invalid Origin Attribute. The Data field
939 contains the unrecognized attribute (type, length and value). */
940 if ((attr->origin != BGP_ORIGIN_IGP)
941 && (attr->origin != BGP_ORIGIN_EGP)
942 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
943 {
944 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
945 attr->origin);
835315bf 946 return bgp_attr_malformed (args,
b881c707 947 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
835315bf 948 args->total);
718e3744 949 }
950
951 /* Set oring attribute flag. */
952 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
953
954 return 0;
955}
ab005298
PJ
956
957/* Parse AS path information. This function is wrapper of
958 aspath_parse. */
959static int
835315bf 960bgp_attr_aspath (struct bgp_attr_parser_args *args)
718e3744 961{
835315bf
PJ
962 struct attr *const attr = args->attr;
963 struct peer *const peer = args->peer;
964 const bgp_size_t length = args->length;
3ecab4c8 965
ab005298
PJ
966 /*
967 * peer with AS4 => will get 4Byte ASnums
968 * otherwise, will get 16 Bit
0b2aa3a0 969 */
ab005298
PJ
970 attr->aspath = aspath_parse (peer->ibuf, length,
971 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
0b2aa3a0 972
ab005298
PJ
973 /* In case of IBGP, length will be zero. */
974 if (! attr->aspath)
cddb8112 975 {
b881c707
PJ
976 zlog (peer->log, LOG_ERR,
977 "Malformed AS path from %s, length is %d",
978 peer->host, length);
835315bf 979 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
cddb8112 980 }
cddb8112 981
ab005298
PJ
982 /* Set aspath attribute flag. */
983 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
0b2aa3a0 984
b881c707 985 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
986}
987
b881c707 988static bgp_attr_parse_ret_t
835315bf 989bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
0b2aa3a0
PJ
990{
991 /* These checks were part of bgp_attr_aspath, but with
992 * as4 we should to check aspath things when
993 * aspath synthesizing with as4_path has already taken place.
994 * Otherwise we check ASPATH and use the synthesized thing, and that is
995 * not right.
996 * So do the checks later, i.e. here
997 */
998 struct bgp *bgp = peer->bgp;
999 struct aspath *aspath;
1000
ca87e1d3 1001 /* Confederation sanity check. */
6d85b15b
JBD
1002 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1003 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
ca87e1d3
VT
1004 {
1005 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
835315bf
PJ
1006 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1007 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1008 return BGP_ATTR_PARSE_ERROR;
ca87e1d3
VT
1009 }
1010
718e3744 1011 /* First AS check for EBGP. */
1012 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1013 {
6d85b15b 1014 if (peer->sort == BGP_PEER_EBGP
718e3744 1015 && ! aspath_firstas_check (attr->aspath, peer->as))
1016 {
1017 zlog (peer->log, LOG_ERR,
aea339f7 1018 "%s incorrect first AS (must be %u)", peer->host, peer->as);
835315bf
PJ
1019 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1020 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1021 return BGP_ATTR_PARSE_ERROR;
718e3744 1022 }
1023 }
1024
1025 /* local-as prepend */
1026 if (peer->change_local_as &&
1027 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1028 {
1029 aspath = aspath_dup (attr->aspath);
1030 aspath = aspath_add_seq (aspath, peer->change_local_as);
f6f434b2 1031 aspath_unintern (&attr->aspath);
718e3744 1032 attr->aspath = aspath_intern (aspath);
1033 }
1034
b881c707 1035 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1036}
1037
ab005298
PJ
1038/* Parse AS4 path information. This function is another wrapper of
1039 aspath_parse. */
1040static int
835315bf 1041bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
ab005298 1042{
835315bf
PJ
1043 struct peer *const peer = args->peer;
1044 struct attr *const attr = args->attr;
1045 const bgp_size_t length = args->length;
3ecab4c8 1046
ab005298
PJ
1047 *as4_path = aspath_parse (peer->ibuf, length, 1);
1048
b881c707
PJ
1049 /* In case of IBGP, length will be zero. */
1050 if (!*as4_path)
1051 {
1052 zlog (peer->log, LOG_ERR,
1053 "Malformed AS4 path from %s, length is %d",
1054 peer->host, length);
835315bf 1055 return bgp_attr_malformed (args,
b881c707 1056 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
835315bf 1057 0);
b881c707
PJ
1058 }
1059
ab005298
PJ
1060 /* Set aspath attribute flag. */
1061 if (as4_path)
1062 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1063
b881c707 1064 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1065}
1066
718e3744 1067/* Nexthop attribute. */
b881c707 1068static bgp_attr_parse_ret_t
835315bf 1069bgp_attr_nexthop (struct bgp_attr_parser_args *args)
718e3744 1070{
835315bf
PJ
1071 struct peer *const peer = args->peer;
1072 struct attr *const attr = args->attr;
1073 const bgp_size_t length = args->length;
1074
bc3443eb 1075 in_addr_t nexthop_h, nexthop_n;
718e3744 1076
718e3744 1077 /* Check nexthop attribute length. */
1078 if (length != 4)
1079 {
1080 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1081 length);
1082
835315bf 1083 return bgp_attr_malformed (args,
b881c707 1084 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1085 args->total);
718e3744 1086 }
1087
bc3443eb
DO
1088 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1089 attribute must result in a NOTIFICATION message (this is implemented below).
1090 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1091 logged locally (this is implemented somewhere else). The UPDATE message
1092 gets ignored in any of these cases. */
1093 nexthop_n = stream_get_ipv4 (peer->ibuf);
1094 nexthop_h = ntohl (nexthop_n);
1095 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1096 {
1097 char buf[INET_ADDRSTRLEN];
1098 inet_ntop (AF_INET, &nexthop_h, buf, INET_ADDRSTRLEN);
1099 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
835315bf 1100 return bgp_attr_malformed (args,
bc3443eb 1101 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
835315bf 1102 args->total);
bc3443eb
DO
1103 }
1104
1105 attr->nexthop.s_addr = nexthop_n;
718e3744 1106 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1107
b881c707 1108 return BGP_ATTR_PARSE_PROCEED;
718e3744 1109}
1110
1111/* MED atrribute. */
b881c707 1112static bgp_attr_parse_ret_t
835315bf 1113bgp_attr_med (struct bgp_attr_parser_args *args)
718e3744 1114{
835315bf
PJ
1115 struct peer *const peer = args->peer;
1116 struct attr *const attr = args->attr;
1117 const bgp_size_t length = args->length;
1118
718e3744 1119 /* Length check. */
1120 if (length != 4)
1121 {
1122 zlog (peer->log, LOG_ERR,
1123 "MED attribute length isn't four [%d]", length);
b881c707 1124
835315bf 1125 return bgp_attr_malformed (args,
b881c707 1126 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1127 args->total);
718e3744 1128 }
1129
1130 attr->med = stream_getl (peer->ibuf);
1131
1132 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1133
b881c707 1134 return BGP_ATTR_PARSE_PROCEED;
718e3744 1135}
1136
1137/* Local preference attribute. */
b881c707 1138static bgp_attr_parse_ret_t
835315bf 1139bgp_attr_local_pref (struct bgp_attr_parser_args *args)
718e3744 1140{
835315bf
PJ
1141 struct peer *const peer = args->peer;
1142 struct attr *const attr = args->attr;
1143 const bgp_size_t length = args->length;
3ecab4c8 1144
a624cae2
DO
1145 /* Length check. */
1146 if (length != 4)
1147 {
835315bf
PJ
1148 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1149 length);
1150 return bgp_attr_malformed (args,
a624cae2 1151 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1152 args->total);
a624cae2 1153 }
0ea968d2 1154
718e3744 1155 /* If it is contained in an UPDATE message that is received from an
1156 external peer, then this attribute MUST be ignored by the
1157 receiving speaker. */
6d85b15b 1158 if (peer->sort == BGP_PEER_EBGP)
718e3744 1159 {
9985f83c 1160 stream_forward_getp (peer->ibuf, length);
b881c707 1161 return BGP_ATTR_PARSE_PROCEED;
718e3744 1162 }
1163
a624cae2 1164 attr->local_pref = stream_getl (peer->ibuf);
718e3744 1165
1166 /* Set atomic aggregate flag. */
1167 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1168
b881c707 1169 return BGP_ATTR_PARSE_PROCEED;
718e3744 1170}
1171
1172/* Atomic aggregate. */
94f2b392 1173static int
835315bf 1174bgp_attr_atomic (struct bgp_attr_parser_args *args)
718e3744 1175{
835315bf
PJ
1176 struct peer *const peer = args->peer;
1177 struct attr *const attr = args->attr;
1178 const bgp_size_t length = args->length;
3ecab4c8 1179
9eba2ada 1180 /* Length check. */
718e3744 1181 if (length != 0)
1182 {
835315bf
PJ
1183 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1184 length);
1185 return bgp_attr_malformed (args,
b881c707 1186 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1187 args->total);
718e3744 1188 }
1189
1190 /* Set atomic aggregate flag. */
1191 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1192
b881c707 1193 return BGP_ATTR_PARSE_PROCEED;
718e3744 1194}
1195
1196/* Aggregator attribute */
94f2b392 1197static int
835315bf 1198bgp_attr_aggregator (struct bgp_attr_parser_args *args)
718e3744 1199{
835315bf
PJ
1200 struct peer *const peer = args->peer;
1201 struct attr *const attr = args->attr;
1202 const bgp_size_t length = args->length;
1203
0b2aa3a0 1204 int wantedlen = 6;
fb982c25 1205 struct attr_extra *attre = bgp_attr_extra_get (attr);
3ecab4c8 1206
0b2aa3a0 1207 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
b881c707 1208 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
0b2aa3a0
PJ
1209 wantedlen = 8;
1210
1211 if (length != wantedlen)
718e3744 1212 {
835315bf
PJ
1213 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1214 wantedlen, length);
1215 return bgp_attr_malformed (args,
b881c707 1216 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1217 args->total);
718e3744 1218 }
0b2aa3a0
PJ
1219
1220 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1221 attre->aggregator_as = stream_getl (peer->ibuf);
1222 else
1223 attre->aggregator_as = stream_getw (peer->ibuf);
fb982c25 1224 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
718e3744 1225
1226 /* Set atomic aggregate flag. */
1227 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1228
b881c707 1229 return BGP_ATTR_PARSE_PROCEED;
718e3744 1230}
1231
0b2aa3a0 1232/* New Aggregator attribute */
b881c707 1233static bgp_attr_parse_ret_t
835315bf
PJ
1234bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1235 as_t *as4_aggregator_as,
1236 struct in_addr *as4_aggregator_addr)
0b2aa3a0 1237{
835315bf
PJ
1238 struct peer *const peer = args->peer;
1239 struct attr *const attr = args->attr;
1240 const bgp_size_t length = args->length;
1241
0b2aa3a0
PJ
1242 if (length != 8)
1243 {
835315bf
PJ
1244 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1245 length);
1246 return bgp_attr_malformed (args,
b881c707 1247 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1248 0);
0b2aa3a0 1249 }
3ecab4c8 1250
0b2aa3a0
PJ
1251 *as4_aggregator_as = stream_getl (peer->ibuf);
1252 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1253
1254 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1255
b881c707 1256 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1257}
1258
1259/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1260 */
b881c707 1261static bgp_attr_parse_ret_t
835315bf
PJ
1262bgp_attr_munge_as4_attrs (struct peer *const peer,
1263 struct attr *const attr,
0b2aa3a0
PJ
1264 struct aspath *as4_path, as_t as4_aggregator,
1265 struct in_addr *as4_aggregator_addr)
1266{
1267 int ignore_as4_path = 0;
1268 struct aspath *newpath;
1269 struct attr_extra *attre = attr->extra;
1270
b881c707 1271 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
0b2aa3a0
PJ
1272 {
1273 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1274 * if given.
1275 * It is worth a warning though, because the peer really
1276 * should not send them
1277 */
1278 if (BGP_DEBUG(as4, AS4))
1279 {
1280 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1281 zlog_debug ("[AS4] %s %s AS4_PATH",
1282 peer->host, "AS4 capable peer, yet it sent");
1283
1284 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1285 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1286 peer->host, "AS4 capable peer, yet it sent");
1287 }
1288
b881c707 1289 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1290 }
1291
0b2aa3a0
PJ
1292 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1293 * because that may override AS4_PATH
1294 */
1295 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1296 {
b881c707 1297 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
0b2aa3a0 1298 {
370b64a2
PJ
1299 assert (attre);
1300
0b2aa3a0
PJ
1301 /* received both.
1302 * if the as_number in aggregator is not AS_TRANS,
1303 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1304 * and the Aggregator shall be taken as
1305 * info on the aggregating node, and the AS_PATH
1306 * shall be taken as the AS_PATH
1307 * otherwise
1308 * the Aggregator shall be ignored and the
1309 * AS4_AGGREGATOR shall be taken as the
1310 * Aggregating node and the AS_PATH is to be
1311 * constructed "as in all other cases"
1312 */
b881c707 1313 if (attre->aggregator_as != BGP_AS_TRANS)
0b2aa3a0
PJ
1314 {
1315 /* ignore */
1316 if ( BGP_DEBUG(as4, AS4))
1317 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1318 " send AGGREGATOR != AS_TRANS and"
1319 " AS4_AGGREGATOR, so ignore"
1320 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1321 ignore_as4_path = 1;
1322 }
1323 else
1324 {
1325 /* "New_aggregator shall be taken as aggregator" */
1326 attre->aggregator_as = as4_aggregator;
1327 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1328 }
1329 }
1330 else
1331 {
1332 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1333 * That is bogus - but reading the conditions
1334 * we have to handle AS4_AGGREGATOR as if it were
1335 * AGGREGATOR in that case
1336 */
1337 if ( BGP_DEBUG(as4, AS4))
1338 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1339 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1340 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
370b64a2 1341 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
0b2aa3a0
PJ
1342 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1343 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1344 }
1345 }
1346
1347 /* need to reconcile NEW_AS_PATH and AS_PATH */
b881c707 1348 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
0b2aa3a0
PJ
1349 {
1350 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
f6f434b2 1351 aspath_unintern (&attr->aspath);
0b2aa3a0
PJ
1352 attr->aspath = aspath_intern (newpath);
1353 }
b881c707 1354 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1355}
1356
718e3744 1357/* Community attribute. */
b881c707 1358static bgp_attr_parse_ret_t
835315bf 1359bgp_attr_community (struct bgp_attr_parser_args *args)
718e3744 1360{
835315bf
PJ
1361 struct peer *const peer = args->peer;
1362 struct attr *const attr = args->attr;
1363 const bgp_size_t length = args->length;
b881c707 1364
718e3744 1365 if (length == 0)
b2ceea18
PJ
1366 {
1367 attr->community = NULL;
b881c707 1368 return BGP_ATTR_PARSE_PROCEED;
b2ceea18 1369 }
0c466381
PJ
1370
1371 attr->community =
1372 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1373
1374 /* XXX: fix community_parse to use stream API and remove this */
1375 stream_forward_getp (peer->ibuf, length);
718e3744 1376
0c466381 1377 if (!attr->community)
835315bf 1378 return bgp_attr_malformed (args,
b881c707 1379 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
835315bf 1380 args->total);
0c466381 1381
718e3744 1382 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1383
b881c707 1384 return BGP_ATTR_PARSE_PROCEED;
718e3744 1385}
1386
1387/* Originator ID attribute. */
b881c707 1388static bgp_attr_parse_ret_t
835315bf 1389bgp_attr_originator_id (struct bgp_attr_parser_args *args)
718e3744 1390{
835315bf
PJ
1391 struct peer *const peer = args->peer;
1392 struct attr *const attr = args->attr;
1393 const bgp_size_t length = args->length;
1394
d595b566 1395 /* Length check. */
718e3744 1396 if (length != 4)
1397 {
1398 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1399
835315bf 1400 return bgp_attr_malformed (args,
b881c707 1401 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1402 args->total);
718e3744 1403 }
1404
fb982c25
PJ
1405 (bgp_attr_extra_get (attr))->originator_id.s_addr
1406 = stream_get_ipv4 (peer->ibuf);
718e3744 1407
1408 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1409
b881c707 1410 return BGP_ATTR_PARSE_PROCEED;
718e3744 1411}
1412
1413/* Cluster list attribute. */
b881c707 1414static bgp_attr_parse_ret_t
835315bf 1415bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
718e3744 1416{
835315bf
PJ
1417 struct peer *const peer = args->peer;
1418 struct attr *const attr = args->attr;
1419 const bgp_size_t length = args->length;
1420
718e3744 1421 /* Check length. */
1422 if (length % 4)
1423 {
1424 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1425
835315bf
PJ
1426 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1427 args->total);
718e3744 1428 }
1429
fb982c25
PJ
1430 (bgp_attr_extra_get (attr))->cluster
1431 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
b881c707
PJ
1432
1433 /* XXX: Fix cluster_parse to use stream API and then remove this */
1434 stream_forward_getp (peer->ibuf, length);
718e3744 1435
1436 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1437
b881c707 1438 return BGP_ATTR_PARSE_PROCEED;
718e3744 1439}
1440
1441/* Multiprotocol reachability information parse. */
03292809 1442int
835315bf
PJ
1443bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1444 struct bgp_nlri *mp_update)
718e3744 1445{
4c9641ba
ML
1446 afi_t afi;
1447 safi_t safi;
718e3744 1448 bgp_size_t nlri_len;
6e4ab12f 1449 size_t start;
718e3744 1450 int ret;
1451 struct stream *s;
835315bf
PJ
1452 struct peer *const peer = args->peer;
1453 struct attr *const attr = args->attr;
1454 const bgp_size_t length = args->length;
fb982c25 1455 struct attr_extra *attre = bgp_attr_extra_get(attr);
835315bf 1456
718e3744 1457 /* Set end of packet. */
6e4ab12f
PJ
1458 s = BGP_INPUT(peer);
1459 start = stream_get_getp(s);
1460
1461 /* safe to read statically sized header? */
1462#define BGP_MP_REACH_MIN_SIZE 5
03292809 1463#define LEN_LEFT (length - (stream_get_getp(s) - start))
6e4ab12f 1464 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
03292809
PJ
1465 {
1466 zlog_info ("%s: %s sent invalid length, %lu",
1467 __func__, peer->host, (unsigned long)length);
b881c707 1468 return BGP_ATTR_PARSE_ERROR;
03292809 1469 }
6e4ab12f 1470
718e3744 1471 /* Load AFI, SAFI. */
1472 afi = stream_getw (s);
1473 safi = stream_getc (s);
1474
1475 /* Get nexthop length. */
fb982c25 1476 attre->mp_nexthop_len = stream_getc (s);
6e4ab12f 1477
03292809
PJ
1478 if (LEN_LEFT < attre->mp_nexthop_len)
1479 {
1480 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1481 __func__, peer->host, attre->mp_nexthop_len);
b881c707 1482 return BGP_ATTR_PARSE_ERROR;
03292809 1483 }
6e4ab12f 1484
718e3744 1485 /* Nexthop length check. */
fb982c25 1486 switch (attre->mp_nexthop_len)
718e3744 1487 {
1488 case 4:
fb982c25 1489 stream_get (&attre->mp_nexthop_global_in, s, 4);
66bed4f4
ML
1490 /* Probably needed for RFC 2283 */
1491 if (attr->nexthop.s_addr == 0)
1492 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
718e3744 1493 break;
1494 case 12:
9206f9ec
SH
1495 stream_getl (s); /* RD high */
1496 stream_getl (s); /* RD low */
1497 stream_get (&attre->mp_nexthop_global_in, s, 4);
718e3744 1498 break;
1499#ifdef HAVE_IPV6
1500 case 16:
fb982c25 1501 stream_get (&attre->mp_nexthop_global, s, 16);
718e3744 1502 break;
1503 case 32:
fb982c25
PJ
1504 stream_get (&attre->mp_nexthop_global, s, 16);
1505 stream_get (&attre->mp_nexthop_local, s, 16);
1506 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
718e3744 1507 {
1508 char buf1[INET6_ADDRSTRLEN];
1509 char buf2[INET6_ADDRSTRLEN];
1510
1511 if (BGP_DEBUG (update, UPDATE_IN))
557865c2 1512 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
fb982c25 1513 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
718e3744 1514 buf1, INET6_ADDRSTRLEN),
fb982c25 1515 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
718e3744 1516 buf2, INET6_ADDRSTRLEN));
1517
fb982c25 1518 attre->mp_nexthop_len = 16;
718e3744 1519 }
1520 break;
1521#endif /* HAVE_IPV6 */
1522 default:
03292809
PJ
1523 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1524 __func__, peer->host, attre->mp_nexthop_len);
b881c707 1525 return BGP_ATTR_PARSE_ERROR;
718e3744 1526 }
1527
03292809
PJ
1528 if (!LEN_LEFT)
1529 {
1530 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1531 __func__, peer->host);
b881c707 1532 return BGP_ATTR_PARSE_ERROR;
03292809 1533 }
718e3744 1534
6e4ab12f
PJ
1535 {
1536 u_char val;
1537 if ((val = stream_getc (s)))
1538 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1539 peer->host, val);
1540 }
1541
1542 /* must have nrli_len, what is left of the attribute */
03292809 1543 nlri_len = LEN_LEFT;
6e4ab12f 1544 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
03292809
PJ
1545 {
1546 zlog_info ("%s: (%s) Failed to read NLRI",
1547 __func__, peer->host);
b881c707 1548 return BGP_ATTR_PARSE_ERROR;
03292809 1549 }
718e3744 1550
42e6d745 1551 if (safi != SAFI_MPLS_LABELED_VPN)
718e3744 1552 {
1553 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
03292809
PJ
1554 if (ret < 0)
1555 {
1556 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1557 __func__, peer->host);
b881c707 1558 return BGP_ATTR_PARSE_ERROR;
03292809 1559 }
718e3744 1560 }
1561
1562 mp_update->afi = afi;
1563 mp_update->safi = safi;
1564 mp_update->nlri = stream_pnt (s);
1565 mp_update->length = nlri_len;
1566
9985f83c 1567 stream_forward_getp (s, nlri_len);
718e3744 1568
b881c707 1569 return BGP_ATTR_PARSE_PROCEED;
03292809 1570#undef LEN_LEFT
718e3744 1571}
1572
1573/* Multiprotocol unreachable parse */
03292809 1574int
835315bf 1575bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
718e3744 1576 struct bgp_nlri *mp_withdraw)
1577{
1578 struct stream *s;
4c9641ba
ML
1579 afi_t afi;
1580 safi_t safi;
718e3744 1581 u_int16_t withdraw_len;
1582 int ret;
835315bf
PJ
1583 struct peer *const peer = args->peer;
1584 const bgp_size_t length = args->length;
718e3744 1585
1586 s = peer->ibuf;
6e4ab12f
PJ
1587
1588#define BGP_MP_UNREACH_MIN_SIZE 3
1589 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
b881c707 1590 return BGP_ATTR_PARSE_ERROR;
6e4ab12f 1591
718e3744 1592 afi = stream_getw (s);
1593 safi = stream_getc (s);
6e4ab12f
PJ
1594
1595 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
718e3744 1596
42e6d745 1597 if (safi != SAFI_MPLS_LABELED_VPN)
718e3744 1598 {
1599 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
1600 if (ret < 0)
b881c707 1601 return BGP_ATTR_PARSE_ERROR;
718e3744 1602 }
1603
1604 mp_withdraw->afi = afi;
1605 mp_withdraw->safi = safi;
1606 mp_withdraw->nlri = stream_pnt (s);
1607 mp_withdraw->length = withdraw_len;
1608
9985f83c 1609 stream_forward_getp (s, withdraw_len);
718e3744 1610
b881c707 1611 return BGP_ATTR_PARSE_PROCEED;
718e3744 1612}
1613
1614/* Extended Community attribute. */
b881c707 1615static bgp_attr_parse_ret_t
835315bf 1616bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
718e3744 1617{
835315bf
PJ
1618 struct peer *const peer = args->peer;
1619 struct attr *const attr = args->attr;
1620 const bgp_size_t length = args->length;
b881c707 1621
718e3744 1622 if (length == 0)
fb982c25
PJ
1623 {
1624 if (attr->extra)
1625 attr->extra->ecommunity = NULL;
0c466381 1626 /* Empty extcomm doesn't seem to be invalid per se */
b881c707 1627 return BGP_ATTR_PARSE_PROCEED;
fb982c25 1628 }
0c466381
PJ
1629
1630 (bgp_attr_extra_get (attr))->ecommunity =
1631 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1632 /* XXX: fix ecommunity_parse to use stream API */
1633 stream_forward_getp (peer->ibuf, length);
1634
1635 if (!attr->extra->ecommunity)
835315bf
PJ
1636 return bgp_attr_malformed (args,
1637 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1638 args->total);
0c466381 1639
718e3744 1640 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1641
b881c707 1642 return BGP_ATTR_PARSE_PROCEED;
718e3744 1643}
1644
1645/* BGP unknown attribute treatment. */
b881c707 1646static bgp_attr_parse_ret_t
835315bf 1647bgp_attr_unknown (struct bgp_attr_parser_args *args)
718e3744 1648{
8794e8d2 1649 bgp_size_t total = args->total;
718e3744 1650 struct transit *transit;
fb982c25 1651 struct attr_extra *attre;
835315bf
PJ
1652 struct peer *const peer = args->peer;
1653 struct attr *const attr = args->attr;
1654 u_char *const startp = args->startp;
1655 const u_char type = args->type;
1656 const u_char flag = args->flags;
1657 const bgp_size_t length = args->length;
1658
718e3744 1659
f418446b 1660 if (BGP_DEBUG (normal, NORMAL))
1661 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1662 peer->host, type, length);
1663
718e3744 1664 if (BGP_DEBUG (events, EVENTS))
557865c2 1665 zlog (peer->log, LOG_DEBUG,
718e3744 1666 "Unknown attribute type %d length %d is received", type, length);
1667
1668 /* Forward read pointer of input stream. */
9985f83c 1669 stream_forward_getp (peer->ibuf, length);
718e3744 1670
718e3744 1671 /* If any of the mandatory well-known attributes are not recognized,
1672 then the Error Subcode is set to Unrecognized Well-known
1673 Attribute. The Data field contains the unrecognized attribute
1674 (type, length and value). */
b881c707 1675 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
718e3744 1676 {
835315bf 1677 return bgp_attr_malformed (args,
b881c707 1678 BGP_NOTIFY_UPDATE_UNREC_ATTR,
835315bf 1679 args->total);
718e3744 1680 }
1681
1682 /* Unrecognized non-transitive optional attributes must be quietly
1683 ignored and not passed along to other BGP peers. */
1684 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
b881c707 1685 return BGP_ATTR_PARSE_PROCEED;
718e3744 1686
1687 /* If a path with recognized transitive optional attribute is
1688 accepted and passed along to other BGP peers and the Partial bit
1689 in the Attribute Flags octet is set to 1 by some previous AS, it
1690 is not set back to 0 by the current AS. */
1691 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1692
1693 /* Store transitive attribute to the end of attr->transit. */
fb982c25 1694 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
393deb9b 1695 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
718e3744 1696
fb982c25 1697 transit = attre->transit;
718e3744 1698
1699 if (transit->val)
1700 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1701 transit->length + total);
1702 else
1703 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1704
1705 memcpy (transit->val + transit->length, startp, total);
1706 transit->length += total;
1707
b881c707 1708 return BGP_ATTR_PARSE_PROCEED;
718e3744 1709}
1710
1711/* Read attribute of update packet. This function is called from
1712 bgp_update() in bgpd.c. */
b881c707 1713bgp_attr_parse_ret_t
718e3744 1714bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1715 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1716{
1717 int ret;
b881c707 1718 u_char flag = 0;
0b2aa3a0 1719 u_char type = 0;
718e3744 1720 bgp_size_t length;
1721 u_char *startp, *endp;
1722 u_char *attr_endp;
1723 u_char seen[BGP_ATTR_BITMAP_SIZE];
0b2aa3a0
PJ
1724 /* we need the as4_path only until we have synthesized the as_path with it */
1725 /* same goes for as4_aggregator */
1726 struct aspath *as4_path = NULL;
1727 as_t as4_aggregator = 0;
1728 struct in_addr as4_aggregator_addr = { 0 };
718e3744 1729
1730 /* Initialize bitmap. */
1731 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1732
1733 /* End pointer of BGP attribute. */
1734 endp = BGP_INPUT_PNT (peer) + size;
b881c707 1735
718e3744 1736 /* Get attributes to the end of attribute length. */
1737 while (BGP_INPUT_PNT (peer) < endp)
1738 {
1739 /* Check remaining length check.*/
1740 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1741 {
c29fdba7 1742 /* XXX warning: long int format, int arg (arg 5) */
718e3744 1743 zlog (peer->log, LOG_WARNING,
d68ab100 1744 "%s: error BGP attribute length %lu is smaller than min len",
0b2aa3a0
PJ
1745 peer->host,
1746 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
718e3744 1747
1748 bgp_notify_send (peer,
1749 BGP_NOTIFY_UPDATE_ERR,
1750 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707 1751 return BGP_ATTR_PARSE_ERROR;
718e3744 1752 }
1753
1754 /* Fetch attribute flag and type. */
1755 startp = BGP_INPUT_PNT (peer);
2d42e68a
DO
1756 /* "The lower-order four bits of the Attribute Flags octet are
1757 unused. They MUST be zero when sent and MUST be ignored when
1758 received." */
1759 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
718e3744 1760 type = stream_getc (BGP_INPUT (peer));
1761
370b64a2
PJ
1762 /* Check whether Extended-Length applies and is in bounds */
1763 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1764 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1765 {
1766 zlog (peer->log, LOG_WARNING,
d68ab100 1767 "%s: Extended length set, but just %lu bytes of attr header",
370b64a2
PJ
1768 peer->host,
1769 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1770
1771 bgp_notify_send (peer,
1772 BGP_NOTIFY_UPDATE_ERR,
1773 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707 1774 return BGP_ATTR_PARSE_ERROR;
370b64a2 1775 }
835315bf 1776
718e3744 1777 /* Check extended attribue length bit. */
1778 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1779 length = stream_getw (BGP_INPUT (peer));
1780 else
1781 length = stream_getc (BGP_INPUT (peer));
1782
1783 /* If any attribute appears more than once in the UPDATE
1784 message, then the Error Subcode is set to Malformed Attribute
1785 List. */
1786
1787 if (CHECK_BITMAP (seen, type))
1788 {
1789 zlog (peer->log, LOG_WARNING,
d68ab100 1790 "%s: error BGP attribute type %d appears twice in a message",
718e3744 1791 peer->host, type);
1792
1793 bgp_notify_send (peer,
1794 BGP_NOTIFY_UPDATE_ERR,
1795 BGP_NOTIFY_UPDATE_MAL_ATTR);
b881c707 1796 return BGP_ATTR_PARSE_ERROR;
718e3744 1797 }
1798
1799 /* Set type to bitmap to check duplicate attribute. `type' is
1800 unsigned char so it never overflow bitmap range. */
1801
1802 SET_BITMAP (seen, type);
1803
1804 /* Overflow check. */
1805 attr_endp = BGP_INPUT_PNT (peer) + length;
1806
1807 if (attr_endp > endp)
1808 {
1809 zlog (peer->log, LOG_WARNING,
d68ab100 1810 "%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);
718e3744 1811 bgp_notify_send (peer,
1812 BGP_NOTIFY_UPDATE_ERR,
1813 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707 1814 return BGP_ATTR_PARSE_ERROR;
718e3744 1815 }
835315bf
PJ
1816
1817 struct bgp_attr_parser_args attr_args = {
1818 .peer = peer,
1819 .length = length,
1820 .attr = attr,
1821 .type = type,
1822 .flags = flag,
1823 .startp = startp,
1824 .total = attr_endp - startp,
1825 };
1826
1827
1828 /* If any recognized attribute has Attribute Flags that conflict
1829 with the Attribute Type Code, then the Error Subcode is set to
1830 Attribute Flags Error. The Data field contains the erroneous
1831 attribute (type, length and value). */
1832 if (bgp_attr_flag_invalid (&attr_args))
fa61e16d
PJ
1833 {
1834 bgp_attr_parse_ret_t ret;
1835 ret = bgp_attr_malformed (&attr_args,
1836 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1837 attr_args.total);
1838 if (ret == BGP_ATTR_PARSE_PROCEED)
1839 continue;
1840 return ret;
1841 }
718e3744 1842
1843 /* OK check attribute and store it's value. */
1844 switch (type)
1845 {
1846 case BGP_ATTR_ORIGIN:
835315bf 1847 ret = bgp_attr_origin (&attr_args);
718e3744 1848 break;
1849 case BGP_ATTR_AS_PATH:
835315bf 1850 ret = bgp_attr_aspath (&attr_args);
718e3744 1851 break;
0b2aa3a0 1852 case BGP_ATTR_AS4_PATH:
835315bf 1853 ret = bgp_attr_as4_path (&attr_args, &as4_path);
0b2aa3a0 1854 break;
718e3744 1855 case BGP_ATTR_NEXT_HOP:
835315bf 1856 ret = bgp_attr_nexthop (&attr_args);
718e3744 1857 break;
1858 case BGP_ATTR_MULTI_EXIT_DISC:
835315bf 1859 ret = bgp_attr_med (&attr_args);
718e3744 1860 break;
1861 case BGP_ATTR_LOCAL_PREF:
835315bf 1862 ret = bgp_attr_local_pref (&attr_args);
718e3744 1863 break;
1864 case BGP_ATTR_ATOMIC_AGGREGATE:
835315bf 1865 ret = bgp_attr_atomic (&attr_args);
718e3744 1866 break;
1867 case BGP_ATTR_AGGREGATOR:
835315bf 1868 ret = bgp_attr_aggregator (&attr_args);
718e3744 1869 break;
0b2aa3a0 1870 case BGP_ATTR_AS4_AGGREGATOR:
835315bf
PJ
1871 ret = bgp_attr_as4_aggregator (&attr_args,
1872 &as4_aggregator,
1873 &as4_aggregator_addr);
0b2aa3a0 1874 break;
718e3744 1875 case BGP_ATTR_COMMUNITIES:
835315bf 1876 ret = bgp_attr_community (&attr_args);
718e3744 1877 break;
1878 case BGP_ATTR_ORIGINATOR_ID:
835315bf 1879 ret = bgp_attr_originator_id (&attr_args);
718e3744 1880 break;
1881 case BGP_ATTR_CLUSTER_LIST:
835315bf 1882 ret = bgp_attr_cluster_list (&attr_args);
718e3744 1883 break;
1884 case BGP_ATTR_MP_REACH_NLRI:
835315bf 1885 ret = bgp_mp_reach_parse (&attr_args, mp_update);
718e3744 1886 break;
1887 case BGP_ATTR_MP_UNREACH_NLRI:
835315bf 1888 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
718e3744 1889 break;
1890 case BGP_ATTR_EXT_COMMUNITIES:
835315bf 1891 ret = bgp_attr_ext_communities (&attr_args);
718e3744 1892 break;
1893 default:
835315bf 1894 ret = bgp_attr_unknown (&attr_args);
718e3744 1895 break;
1896 }
b881c707
PJ
1897
1898 /* If hard error occured immediately return to the caller. */
1899 if (ret == BGP_ATTR_PARSE_ERROR)
6e4ab12f
PJ
1900 {
1901 zlog (peer->log, LOG_WARNING,
1902 "%s: Attribute %s, parse error",
1903 peer->host,
1904 LOOKUP (attr_str, type));
b881c707
PJ
1905 bgp_notify_send (peer,
1906 BGP_NOTIFY_UPDATE_ERR,
1907 BGP_NOTIFY_UPDATE_MAL_ATTR);
1908 if (as4_path)
1909 aspath_unintern (&as4_path);
1910 return ret;
6e4ab12f 1911 }
b881c707
PJ
1912 if (ret == BGP_ATTR_PARSE_WITHDRAW)
1913 {
1914
1915 zlog (peer->log, LOG_WARNING,
1916 "%s: Attribute %s, parse error - treating as withdrawal",
1917 peer->host,
1918 LOOKUP (attr_str, type));
1919 if (as4_path)
1920 aspath_unintern (&as4_path);
1921 return ret;
1922 }
1923
718e3744 1924 /* Check the fetched length. */
1925 if (BGP_INPUT_PNT (peer) != attr_endp)
1926 {
1927 zlog (peer->log, LOG_WARNING,
6e4ab12f
PJ
1928 "%s: BGP attribute %s, fetch error",
1929 peer->host, LOOKUP (attr_str, type));
718e3744 1930 bgp_notify_send (peer,
1931 BGP_NOTIFY_UPDATE_ERR,
1932 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707
PJ
1933 if (as4_path)
1934 aspath_unintern (&as4_path);
1935 return BGP_ATTR_PARSE_ERROR;
718e3744 1936 }
1937 }
1938
1939 /* Check final read pointer is same as end pointer. */
1940 if (BGP_INPUT_PNT (peer) != endp)
1941 {
1942 zlog (peer->log, LOG_WARNING,
d68ab100 1943 "%s: BGP attribute %s, length mismatch",
6e4ab12f 1944 peer->host, LOOKUP (attr_str, type));
718e3744 1945 bgp_notify_send (peer,
1946 BGP_NOTIFY_UPDATE_ERR,
1947 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707
PJ
1948 if (as4_path)
1949 aspath_unintern (&as4_path);
1950 return BGP_ATTR_PARSE_ERROR;
718e3744 1951 }
1952
0b2aa3a0
PJ
1953 /*
1954 * At this place we can see whether we got AS4_PATH and/or
1955 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
1956 * We can not do this before we've read all attributes because
1957 * the as4 handling does not say whether AS4_PATH has to be sent
1958 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
1959 * in relationship to AGGREGATOR.
1960 * So, to be defensive, we are not relying on any order and read
1961 * all attributes first, including these 32bit ones, and now,
1962 * afterwards, we look what and if something is to be done for as4.
1963 */
835315bf 1964 if (bgp_attr_munge_as4_attrs (peer, attr, as4_path,
0b2aa3a0 1965 as4_aggregator, &as4_aggregator_addr))
b881c707
PJ
1966 {
1967 if (as4_path)
1968 aspath_unintern (&as4_path);
1969 return BGP_ATTR_PARSE_ERROR;
1970 }
0b2aa3a0
PJ
1971
1972 /* At this stage, we have done all fiddling with as4, and the
1973 * resulting info is in attr->aggregator resp. attr->aspath
1974 * so we can chuck as4_aggregator and as4_path alltogether in
1975 * order to save memory
1976 */
b881c707 1977 if (as4_path)
0b2aa3a0 1978 {
f6f434b2 1979 aspath_unintern (&as4_path); /* unintern - it is in the hash */
0b2aa3a0
PJ
1980 /* The flag that we got this is still there, but that does not
1981 * do any trouble
1982 */
1983 }
1984 /*
1985 * The "rest" of the code does nothing with as4_aggregator.
1986 * there is no memory attached specifically which is not part
1987 * of the attr.
1988 * so ignoring just means do nothing.
1989 */
1990 /*
1991 * Finally do the checks on the aspath we did not do yet
1992 * because we waited for a potentially synthesized aspath.
1993 */
b881c707 1994 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
0b2aa3a0 1995 {
835315bf 1996 ret = bgp_attr_aspath_check (peer, attr);
b881c707 1997 if (ret != BGP_ATTR_PARSE_PROCEED)
0b2aa3a0
PJ
1998 return ret;
1999 }
2000
718e3744 2001 /* Finally intern unknown attribute. */
fb982c25
PJ
2002 if (attr->extra && attr->extra->transit)
2003 attr->extra->transit = transit_intern (attr->extra->transit);
718e3744 2004
b881c707 2005 return BGP_ATTR_PARSE_PROCEED;
718e3744 2006}
2007
2008/* Well-known attribute check. */
2009int
2010bgp_attr_check (struct peer *peer, struct attr *attr)
2011{
2012 u_char type = 0;
2013
2014 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2015 type = BGP_ATTR_ORIGIN;
2016
2017 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2018 type = BGP_ATTR_AS_PATH;
2019
2020 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
2021 type = BGP_ATTR_NEXT_HOP;
2022
6d85b15b 2023 if (peer->sort == BGP_PEER_IBGP
718e3744 2024 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2025 type = BGP_ATTR_LOCAL_PREF;
2026
2027 if (type)
2028 {
2029 zlog (peer->log, LOG_WARNING,
2030 "%s Missing well-known attribute %d.",
2031 peer->host, type);
2032 bgp_notify_send_with_data (peer,
2033 BGP_NOTIFY_UPDATE_ERR,
2034 BGP_NOTIFY_UPDATE_MISS_ATTR,
2035 &type, 1);
b881c707 2036 return BGP_ATTR_PARSE_ERROR;
718e3744 2037 }
b881c707 2038 return BGP_ATTR_PARSE_PROCEED;
718e3744 2039}
2040\f
2041int stream_put_prefix (struct stream *, struct prefix *);
2042
2043/* Make attribute packet. */
2044bgp_size_t
2045bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
2046 struct stream *s, struct attr *attr, struct prefix *p,
2047 afi_t afi, safi_t safi, struct peer *from,
a3b6ea56 2048 struct prefix_rd *prd, u_char *tag)
718e3744 2049{
fe69a505 2050 size_t cp;
0b2aa3a0 2051 size_t aspath_sizep;
718e3744 2052 struct aspath *aspath;
0b2aa3a0
PJ
2053 int send_as4_path = 0;
2054 int send_as4_aggregator = 0;
2055 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
718e3744 2056
2057 if (! bgp)
2058 bgp = bgp_get_default ();
2059
2060 /* Remember current pointer. */
9985f83c 2061 cp = stream_get_endp (s);
718e3744 2062
2063 /* Origin attribute. */
2064 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2065 stream_putc (s, BGP_ATTR_ORIGIN);
2066 stream_putc (s, 1);
2067 stream_putc (s, attr->origin);
2068
2069 /* AS path attribute. */
2070
2071 /* If remote-peer is EBGP */
6d85b15b 2072 if (peer->sort == BGP_PEER_EBGP
718e3744 2073 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
fe69a505 2074 || attr->aspath->segments == NULL)
fee0f4c6 2075 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
718e3744 2076 {
2077 aspath = aspath_dup (attr->aspath);
2078
2079 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2080 {
2081 /* Strip the confed info, and then stuff our path CONFED_ID
2082 on the front */
2083 aspath = aspath_delete_confed_seq (aspath);
2084 aspath = aspath_add_seq (aspath, bgp->confed_id);
2085 }
2086 else
2087 {
9d3f9705
AC
2088 if (peer->change_local_as) {
2089 /* If replace-as is specified, we only use the change_local_as when
2090 advertising routes. */
2091 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2092 aspath = aspath_add_seq (aspath, peer->local_as);
2093 }
718e3744 2094 aspath = aspath_add_seq (aspath, peer->change_local_as);
9d3f9705
AC
2095 } else {
2096 aspath = aspath_add_seq (aspath, peer->local_as);
2097 }
718e3744 2098 }
2099 }
6d85b15b 2100 else if (peer->sort == BGP_PEER_CONFED)
718e3744 2101 {
2102 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2103 aspath = aspath_dup (attr->aspath);
2104 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2105 }
2106 else
2107 aspath = attr->aspath;
2108
0b2aa3a0
PJ
2109 /* If peer is not AS4 capable, then:
2110 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2111 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2112 * types are in it (i.e. exclude them if they are there)
2113 * AND do this only if there is at least one asnum > 65535 in the path!
2114 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2115 * all ASnums > 65535 to BGP_AS_TRANS
2116 */
2117
2118 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2119 stream_putc (s, BGP_ATTR_AS_PATH);
2120 aspath_sizep = stream_get_endp (s);
2121 stream_putw (s, 0);
2122 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2123
2124 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2125 * in the path
2126 */
2127 if (!use32bit && aspath_has_as4 (aspath))
2128 send_as4_path = 1; /* we'll do this later, at the correct place */
2129
718e3744 2130 /* Nexthop attribute. */
2131 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
2132 {
2133 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2134 stream_putc (s, BGP_ATTR_NEXT_HOP);
2135 stream_putc (s, 4);
2136 if (safi == SAFI_MPLS_VPN)
2137 {
2138 if (attr->nexthop.s_addr == 0)
2139 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2140 else
2141 stream_put_ipv4 (s, attr->nexthop.s_addr);
2142 }
2143 else
2144 stream_put_ipv4 (s, attr->nexthop.s_addr);
2145 }
2146
2147 /* MED attribute. */
2148 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2149 {
2150 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2151 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2152 stream_putc (s, 4);
2153 stream_putl (s, attr->med);
2154 }
2155
2156 /* Local preference. */
6d85b15b
JBD
2157 if (peer->sort == BGP_PEER_IBGP ||
2158 peer->sort == BGP_PEER_CONFED)
718e3744 2159 {
2160 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2161 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2162 stream_putc (s, 4);
2163 stream_putl (s, attr->local_pref);
2164 }
2165
2166 /* Atomic aggregate. */
2167 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2168 {
2169 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2170 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2171 stream_putc (s, 0);
2172 }
2173
2174 /* Aggregator. */
2175 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2176 {
fb982c25 2177 assert (attr->extra);
0b2aa3a0
PJ
2178
2179 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
718e3744 2180 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2181 stream_putc (s, BGP_ATTR_AGGREGATOR);
0b2aa3a0
PJ
2182
2183 if (use32bit)
2184 {
2185 /* AS4 capable peer */
2186 stream_putc (s, 8);
2187 stream_putl (s, attr->extra->aggregator_as);
2188 }
2189 else
2190 {
2191 /* 2-byte AS peer */
2192 stream_putc (s, 6);
2193
2194 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2195 if ( attr->extra->aggregator_as > 65535 )
2196 {
2197 stream_putw (s, BGP_AS_TRANS);
2198
2199 /* we have to send AS4_AGGREGATOR, too.
2200 * we'll do that later in order to send attributes in ascending
2201 * order.
2202 */
2203 send_as4_aggregator = 1;
2204 }
2205 else
2206 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2207 }
fb982c25 2208 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
718e3744 2209 }
2210
2211 /* Community attribute. */
2212 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2213 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2214 {
2215 if (attr->community->size * 4 > 255)
2216 {
2217 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2218 stream_putc (s, BGP_ATTR_COMMUNITIES);
2219 stream_putw (s, attr->community->size * 4);
2220 }
2221 else
2222 {
2223 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2224 stream_putc (s, BGP_ATTR_COMMUNITIES);
2225 stream_putc (s, attr->community->size * 4);
2226 }
2227 stream_put (s, attr->community->val, attr->community->size * 4);
2228 }
2229
2230 /* Route Reflector. */
6d85b15b 2231 if (peer->sort == BGP_PEER_IBGP
718e3744 2232 && from
6d85b15b 2233 && from->sort == BGP_PEER_IBGP)
718e3744 2234 {
2235 /* Originator ID. */
2236 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2237 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2238 stream_putc (s, 4);
2239
2240 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
fb982c25 2241 stream_put_in_addr (s, &attr->extra->originator_id);
34c3f81b
PJ
2242 else
2243 stream_put_in_addr (s, &from->remote_id);
718e3744 2244
2245 /* Cluster list. */
2246 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2247 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2248
9eda90ce 2249 if (attr->extra && attr->extra->cluster)
718e3744 2250 {
fb982c25 2251 stream_putc (s, attr->extra->cluster->length + 4);
718e3744 2252 /* If this peer configuration's parent BGP has cluster_id. */
2253 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2254 stream_put_in_addr (s, &bgp->cluster_id);
2255 else
2256 stream_put_in_addr (s, &bgp->router_id);
fb982c25
PJ
2257 stream_put (s, attr->extra->cluster->list,
2258 attr->extra->cluster->length);
718e3744 2259 }
2260 else
2261 {
2262 stream_putc (s, 4);
2263 /* If this peer configuration's parent BGP has cluster_id. */
2264 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2265 stream_put_in_addr (s, &bgp->cluster_id);
2266 else
2267 stream_put_in_addr (s, &bgp->router_id);
2268 }
2269 }
2270
2271#ifdef HAVE_IPV6
2272 /* If p is IPv6 address put it into attribute. */
2273 if (p->family == AF_INET6)
2274 {
2275 unsigned long sizep;
fb982c25
PJ
2276 struct attr_extra *attre = attr->extra;
2277
2278 assert (attr->extra);
2279
718e3744 2280 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2281 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
9985f83c 2282 sizep = stream_get_endp (s);
fb982c25 2283 stream_putc (s, 0); /* Marker: Attribute length. */
718e3744 2284 stream_putw (s, AFI_IP6); /* AFI */
2285 stream_putc (s, safi); /* SAFI */
2286
fb982c25 2287 stream_putc (s, attre->mp_nexthop_len);
718e3744 2288
fb982c25
PJ
2289 if (attre->mp_nexthop_len == 16)
2290 stream_put (s, &attre->mp_nexthop_global, 16);
2291 else if (attre->mp_nexthop_len == 32)
718e3744 2292 {
fb982c25
PJ
2293 stream_put (s, &attre->mp_nexthop_global, 16);
2294 stream_put (s, &attre->mp_nexthop_local, 16);
718e3744 2295 }
2296
2297 /* SNPA */
2298 stream_putc (s, 0);
2299
718e3744 2300 /* Prefix write. */
2301 stream_put_prefix (s, p);
2302
2303 /* Set MP attribute length. */
9985f83c 2304 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
718e3744 2305 }
2306#endif /* HAVE_IPV6 */
2307
2308 if (p->family == AF_INET && safi == SAFI_MULTICAST)
2309 {
2310 unsigned long sizep;
718e3744 2311
2312 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2313 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
9985f83c 2314 sizep = stream_get_endp (s);
fb982c25 2315 stream_putc (s, 0); /* Marker: Attribute Length. */
718e3744 2316 stream_putw (s, AFI_IP); /* AFI */
2317 stream_putc (s, SAFI_MULTICAST); /* SAFI */
2318
2319 stream_putc (s, 4);
2320 stream_put_ipv4 (s, attr->nexthop.s_addr);
2321
2322 /* SNPA */
2323 stream_putc (s, 0);
2324
718e3744 2325 /* Prefix write. */
2326 stream_put_prefix (s, p);
2327
2328 /* Set MP attribute length. */
9985f83c 2329 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
718e3744 2330 }
2331
2332 if (p->family == AF_INET && safi == SAFI_MPLS_VPN)
2333 {
2334 unsigned long sizep;
718e3744 2335
2336 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2337 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
9985f83c 2338 sizep = stream_get_endp (s);
718e3744 2339 stream_putc (s, 0); /* Length of this attribute. */
2340 stream_putw (s, AFI_IP); /* AFI */
42e6d745 2341 stream_putc (s, SAFI_MPLS_LABELED_VPN); /* SAFI */
718e3744 2342
2343 stream_putc (s, 12);
2344 stream_putl (s, 0);
2345 stream_putl (s, 0);
fb982c25 2346 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
718e3744 2347
2348 /* SNPA */
2349 stream_putc (s, 0);
2350
718e3744 2351 /* Tag, RD, Prefix write. */
2352 stream_putc (s, p->prefixlen + 88);
2353 stream_put (s, tag, 3);
2354 stream_put (s, prd->val, 8);
2355 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2356
2357 /* Set MP attribute length. */
9985f83c 2358 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
718e3744 2359 }
2360
2361 /* Extended Communities attribute. */
2362 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2363 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2364 {
fb982c25
PJ
2365 struct attr_extra *attre = attr->extra;
2366
2367 assert (attre);
2368
6d85b15b
JBD
2369 if (peer->sort == BGP_PEER_IBGP
2370 || peer->sort == BGP_PEER_CONFED)
718e3744 2371 {
fb982c25 2372 if (attre->ecommunity->size * 8 > 255)
4372df71 2373 {
2374 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2375 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
fb982c25 2376 stream_putw (s, attre->ecommunity->size * 8);
4372df71 2377 }
2378 else
2379 {
2380 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2381 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
fb982c25 2382 stream_putc (s, attre->ecommunity->size * 8);
4372df71 2383 }
fb982c25 2384 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
718e3744 2385 }
2386 else
2387 {
5228ad27 2388 u_int8_t *pnt;
4372df71 2389 int tbit;
2390 int ecom_tr_size = 0;
2391 int i;
2392
fb982c25 2393 for (i = 0; i < attre->ecommunity->size; i++)
4372df71 2394 {
fb982c25 2395 pnt = attre->ecommunity->val + (i * 8);
4372df71 2396 tbit = *pnt;
2397
2398 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2399 continue;
2400
2401 ecom_tr_size++;
2402 }
2403
2404 if (ecom_tr_size)
2405 {
2406 if (ecom_tr_size * 8 > 255)
2407 {
2408 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2409 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2410 stream_putw (s, ecom_tr_size * 8);
2411 }
2412 else
2413 {
2414 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2415 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2416 stream_putc (s, ecom_tr_size * 8);
2417 }
2418
fb982c25 2419 for (i = 0; i < attre->ecommunity->size; i++)
4372df71 2420 {
fb982c25 2421 pnt = attre->ecommunity->val + (i * 8);
4372df71 2422 tbit = *pnt;
2423
2424 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2425 continue;
2426
2427 stream_put (s, pnt, 8);
2428 }
2429 }
718e3744 2430 }
718e3744 2431 }
0b2aa3a0
PJ
2432
2433 if ( send_as4_path )
2434 {
2435 /* If the peer is NOT As4 capable, AND */
2436 /* there are ASnums > 65535 in path THEN
2437 * give out AS4_PATH */
2438
2439 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2440 * path segments!
2441 * Hm, I wonder... confederation things *should* only be at
2442 * the beginning of an aspath, right? Then we should use
2443 * aspath_delete_confed_seq for this, because it is already
2444 * there! (JK)
2445 * Folks, talk to me: what is reasonable here!?
2446 */
2447 aspath = aspath_delete_confed_seq (aspath);
2448
2449 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2450 stream_putc (s, BGP_ATTR_AS4_PATH);
2451 aspath_sizep = stream_get_endp (s);
2452 stream_putw (s, 0);
2453 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2454 }
2455
2456 if (aspath != attr->aspath)
2457 aspath_free (aspath);
2458
2459 if ( send_as4_aggregator )
2460 {
2461 assert (attr->extra);
2462
2463 /* send AS4_AGGREGATOR, at this place */
2464 /* this section of code moved here in order to ensure the correct
2465 * *ascending* order of attributes
2466 */
2467 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2468 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2469 stream_putc (s, 8);
2470 stream_putl (s, attr->extra->aggregator_as);
2471 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2472 }
41367172 2473
718e3744 2474 /* Unknown transit attribute. */
fb982c25
PJ
2475 if (attr->extra && attr->extra->transit)
2476 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
718e3744 2477
2478 /* Return total size of attribute. */
9985f83c 2479 return stream_get_endp (s) - cp;
718e3744 2480}
2481
2482bgp_size_t
2483bgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p,
2484 afi_t afi, safi_t safi, struct prefix_rd *prd,
a3b6ea56 2485 u_char *tag)
718e3744 2486{
2487 unsigned long cp;
2488 unsigned long attrlen_pnt;
2489 bgp_size_t size;
2490
9985f83c 2491 cp = stream_get_endp (s);
718e3744 2492
2493 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2494 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2495
9985f83c 2496 attrlen_pnt = stream_get_endp (s);
718e3744 2497 stream_putc (s, 0); /* Length of this attribute. */
2498
2499 stream_putw (s, family2afi (p->family));
2500
2501 if (safi == SAFI_MPLS_VPN)
2502 {
2503 /* SAFI */
42e6d745 2504 stream_putc (s, SAFI_MPLS_LABELED_VPN);
718e3744 2505
2506 /* prefix. */
2507 stream_putc (s, p->prefixlen + 88);
2508 stream_put (s, tag, 3);
2509 stream_put (s, prd->val, 8);
2510 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2511 }
2512 else
2513 {
2514 /* SAFI */
2515 stream_putc (s, safi);
2516
2517 /* prefix */
2518 stream_put_prefix (s, p);
2519 }
2520
2521 /* Set MP attribute length. */
9985f83c 2522 size = stream_get_endp (s) - attrlen_pnt - 1;
718e3744 2523 stream_putc_at (s, attrlen_pnt, size);
2524
9985f83c 2525 return stream_get_endp (s) - cp;
718e3744 2526}
2527
2528/* Initialization of attribute. */
2529void
fe69a505 2530bgp_attr_init (void)
718e3744 2531{
718e3744 2532 aspath_init ();
2533 attrhash_init ();
2534 community_init ();
2535 ecommunity_init ();
2536 cluster_init ();
2537 transit_init ();
2538}
2539
228da428
CC
2540void
2541bgp_attr_finish (void)
2542{
2543 aspath_finish ();
2544 attrhash_finish ();
2545 community_finish ();
2546 ecommunity_finish ();
2547 cluster_finish ();
2548 transit_finish ();
2549}
2550
718e3744 2551/* Make attribute packet. */
2552void
a384592f 2553bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2554 struct prefix *prefix)
718e3744 2555{
2556 unsigned long cp;
2557 unsigned long len;
0b2aa3a0 2558 size_t aspath_lenp;
718e3744 2559 struct aspath *aspath;
2560
2561 /* Remember current pointer. */
9985f83c 2562 cp = stream_get_endp (s);
718e3744 2563
2564 /* Place holder of length. */
2565 stream_putw (s, 0);
2566
2567 /* Origin attribute. */
2568 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2569 stream_putc (s, BGP_ATTR_ORIGIN);
2570 stream_putc (s, 1);
2571 stream_putc (s, attr->origin);
2572
2573 aspath = attr->aspath;
0b2aa3a0
PJ
2574
2575 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2576 stream_putc (s, BGP_ATTR_AS_PATH);
2577 aspath_lenp = stream_get_endp (s);
2578 stream_putw (s, 0);
2579
2580 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
718e3744 2581
2582 /* Nexthop attribute. */
a384592f 2583 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2584 if(prefix != NULL
2585#ifdef HAVE_IPV6
2586 && prefix->family != AF_INET6
2587#endif /* HAVE_IPV6 */
2588 )
2589 {
2590 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2591 stream_putc (s, BGP_ATTR_NEXT_HOP);
2592 stream_putc (s, 4);
2593 stream_put_ipv4 (s, attr->nexthop.s_addr);
2594 }
718e3744 2595
2596 /* MED attribute. */
2597 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2598 {
2599 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2600 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2601 stream_putc (s, 4);
2602 stream_putl (s, attr->med);
2603 }
2604
2605 /* Local preference. */
2606 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2607 {
2608 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2609 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2610 stream_putc (s, 4);
2611 stream_putl (s, attr->local_pref);
2612 }
2613
2614 /* Atomic aggregate. */
2615 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2616 {
2617 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2618 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2619 stream_putc (s, 0);
2620 }
2621
2622 /* Aggregator. */
2623 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2624 {
fb982c25 2625 assert (attr->extra);
718e3744 2626 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2627 stream_putc (s, BGP_ATTR_AGGREGATOR);
0b2aa3a0
PJ
2628 stream_putc (s, 8);
2629 stream_putl (s, attr->extra->aggregator_as);
fb982c25 2630 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
718e3744 2631 }
2632
2633 /* Community attribute. */
2634 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2635 {
2636 if (attr->community->size * 4 > 255)
2637 {
2638 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2639 stream_putc (s, BGP_ATTR_COMMUNITIES);
2640 stream_putw (s, attr->community->size * 4);
2641 }
2642 else
2643 {
2644 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2645 stream_putc (s, BGP_ATTR_COMMUNITIES);
2646 stream_putc (s, attr->community->size * 4);
2647 }
2648 stream_put (s, attr->community->val, attr->community->size * 4);
2649 }
2650
a384592f 2651#ifdef HAVE_IPV6
2652 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
fb982c25
PJ
2653 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2654 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
a384592f 2655 {
2656 int sizep;
fb982c25
PJ
2657 struct attr_extra *attre = attr->extra;
2658
a384592f 2659 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2660 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
9985f83c 2661 sizep = stream_get_endp (s);
a384592f 2662
2663 /* MP header */
fb982c25 2664 stream_putc (s, 0); /* Marker: Attribute length. */
a384592f 2665 stream_putw(s, AFI_IP6); /* AFI */
2666 stream_putc(s, SAFI_UNICAST); /* SAFI */
2667
2668 /* Next hop */
fb982c25
PJ
2669 stream_putc(s, attre->mp_nexthop_len);
2670 stream_put(s, &attre->mp_nexthop_global, 16);
2671 if (attre->mp_nexthop_len == 32)
2672 stream_put(s, &attre->mp_nexthop_local, 16);
a384592f 2673
2674 /* SNPA */
2675 stream_putc(s, 0);
2676
2677 /* Prefix */
2678 stream_put_prefix(s, prefix);
2679
2680 /* Set MP attribute length. */
9985f83c 2681 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
a384592f 2682 }
2683#endif /* HAVE_IPV6 */
2684
718e3744 2685 /* Return total size of attribute. */
9985f83c 2686 len = stream_get_endp (s) - cp - 2;
718e3744 2687 stream_putw_at (s, cp, len);
2688}