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