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