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