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