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