]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_attr.c
bgpd: don't leak memory in community_regexp_include
[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};
1146static const size_t attr_flags_values_max =
1147 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
1148
1149static int
835315bf 1150bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
3ecab4c8
PJ
1151{
1152 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
835315bf
PJ
1153 const u_int8_t flags = args->flags;
1154 const u_int8_t attr_code = args->type;
3ecab4c8
PJ
1155
1156 /* there may be attributes we don't know about */
1157 if (attr_code > attr_flags_values_max)
1158 return 0;
1159 if (attr_flags_values[attr_code] == 0)
1160 return 0;
1161
1162 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1163 * 1."
1164 */
1165 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1166 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1167 {
16286195
DS
1168 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1169 LOOKUP (attr_str, attr_code), flags);
3ecab4c8
PJ
1170 return 1;
1171 }
1172
1173 /* "For well-known attributes and for optional non-transitive attributes,
1174 * the Partial bit MUST be set to 0."
1175 */
1176 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1177 {
1178 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1179 {
16286195
DS
1180 zlog_err ("%s well-known attribute "
1181 "must NOT have the partial flag set (%x)",
1182 LOOKUP (attr_str, attr_code), flags);
3ecab4c8
PJ
1183 return 1;
1184 }
1185 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1186 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1187 {
16286195
DS
1188 zlog_err ("%s optional + transitive attribute "
1189 "must NOT have the partial flag set (%x)",
1190 LOOKUP (attr_str, attr_code), flags);
3ecab4c8
PJ
1191 return 1;
1192 }
1193 }
1194
1195 /* Optional transitive attributes may go through speakers that don't
1196 * reocgnise them and set the Partial bit.
1197 */
1198 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1199 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1200 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1201
683f2b86 1202 if ((flags & ~mask)
3ecab4c8
PJ
1203 == attr_flags_values[attr_code])
1204 return 0;
1205
835315bf 1206 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
3ecab4c8
PJ
1207 return 1;
1208}
1209
718e3744 1210/* Get origin attribute of the update message. */
b881c707 1211static bgp_attr_parse_ret_t
835315bf 1212bgp_attr_origin (struct bgp_attr_parser_args *args)
718e3744 1213{
835315bf
PJ
1214 struct peer *const peer = args->peer;
1215 struct attr *const attr = args->attr;
1216 const bgp_size_t length = args->length;
1217
718e3744 1218 /* If any recognized attribute has Attribute Length that conflicts
1219 with the expected length (based on the attribute type code), then
1220 the Error Subcode is set to Attribute Length Error. The Data
1221 field contains the erroneous attribute (type, length and
1222 value). */
1223 if (length != 1)
1224 {
16286195 1225 zlog_err ("Origin attribute length is not one %d", length);
835315bf 1226 return bgp_attr_malformed (args,
b881c707 1227 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1228 args->total);
718e3744 1229 }
1230
1231 /* Fetch origin attribute. */
1232 attr->origin = stream_getc (BGP_INPUT (peer));
1233
1234 /* If the ORIGIN attribute has an undefined value, then the Error
1235 Subcode is set to Invalid Origin Attribute. The Data field
1236 contains the unrecognized attribute (type, length and value). */
1237 if ((attr->origin != BGP_ORIGIN_IGP)
1238 && (attr->origin != BGP_ORIGIN_EGP)
1239 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1240 {
16286195 1241 zlog_err ("Origin attribute value is invalid %d", attr->origin);
835315bf 1242 return bgp_attr_malformed (args,
b881c707 1243 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
835315bf 1244 args->total);
718e3744 1245 }
1246
1247 /* Set oring attribute flag. */
1248 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1249
1250 return 0;
1251}
ab005298
PJ
1252
1253/* Parse AS path information. This function is wrapper of
1254 aspath_parse. */
1255static int
835315bf 1256bgp_attr_aspath (struct bgp_attr_parser_args *args)
718e3744 1257{
835315bf
PJ
1258 struct attr *const attr = args->attr;
1259 struct peer *const peer = args->peer;
1260 const bgp_size_t length = args->length;
3ecab4c8 1261
ab005298
PJ
1262 /*
1263 * peer with AS4 => will get 4Byte ASnums
1264 * otherwise, will get 16 Bit
0b2aa3a0 1265 */
ab005298
PJ
1266 attr->aspath = aspath_parse (peer->ibuf, length,
1267 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
0b2aa3a0 1268
ab005298
PJ
1269 /* In case of IBGP, length will be zero. */
1270 if (! attr->aspath)
cddb8112 1271 {
16286195 1272 zlog_err ("Malformed AS path from %s, length is %d", peer->host, length);
835315bf 1273 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
cddb8112 1274 }
cddb8112 1275
ab005298
PJ
1276 /* Set aspath attribute flag. */
1277 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
0b2aa3a0 1278
b881c707 1279 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1280}
1281
b881c707 1282static bgp_attr_parse_ret_t
835315bf 1283bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
0b2aa3a0
PJ
1284{
1285 /* These checks were part of bgp_attr_aspath, but with
1286 * as4 we should to check aspath things when
1287 * aspath synthesizing with as4_path has already taken place.
1288 * Otherwise we check ASPATH and use the synthesized thing, and that is
1289 * not right.
1290 * So do the checks later, i.e. here
1291 */
1292 struct bgp *bgp = peer->bgp;
1293 struct aspath *aspath;
1294
ca87e1d3 1295 /* Confederation sanity check. */
6d85b15b
JBD
1296 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1297 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
ca87e1d3 1298 {
16286195 1299 zlog_err ("Malformed AS path from %s", peer->host);
835315bf
PJ
1300 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1301 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1302 return BGP_ATTR_PARSE_ERROR;
ca87e1d3
VT
1303 }
1304
718e3744 1305 /* First AS check for EBGP. */
1306 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1307 {
6d85b15b 1308 if (peer->sort == BGP_PEER_EBGP
718e3744 1309 && ! aspath_firstas_check (attr->aspath, peer->as))
1310 {
16286195 1311 zlog_err ("%s incorrect first AS (must be %u)", peer->host, peer->as);
835315bf
PJ
1312 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1313 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1314 return BGP_ATTR_PARSE_ERROR;
718e3744 1315 }
1316 }
1317
1318 /* local-as prepend */
1319 if (peer->change_local_as &&
1320 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1321 {
1322 aspath = aspath_dup (attr->aspath);
1323 aspath = aspath_add_seq (aspath, peer->change_local_as);
f6f434b2 1324 aspath_unintern (&attr->aspath);
718e3744 1325 attr->aspath = aspath_intern (aspath);
1326 }
1327
b881c707 1328 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1329}
1330
ab005298
PJ
1331/* Parse AS4 path information. This function is another wrapper of
1332 aspath_parse. */
1333static int
835315bf 1334bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
ab005298 1335{
835315bf
PJ
1336 struct peer *const peer = args->peer;
1337 struct attr *const attr = args->attr;
1338 const bgp_size_t length = args->length;
3ecab4c8 1339
ab005298
PJ
1340 *as4_path = aspath_parse (peer->ibuf, length, 1);
1341
b881c707
PJ
1342 /* In case of IBGP, length will be zero. */
1343 if (!*as4_path)
1344 {
16286195 1345 zlog_err ("Malformed AS4 path from %s, length is %d", peer->host, length);
835315bf 1346 return bgp_attr_malformed (args,
b881c707 1347 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
835315bf 1348 0);
b881c707
PJ
1349 }
1350
ab005298
PJ
1351 /* Set aspath attribute flag. */
1352 if (as4_path)
1353 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1354
b881c707 1355 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1356}
1357
718e3744 1358/* Nexthop attribute. */
b881c707 1359static bgp_attr_parse_ret_t
835315bf 1360bgp_attr_nexthop (struct bgp_attr_parser_args *args)
718e3744 1361{
835315bf
PJ
1362 struct peer *const peer = args->peer;
1363 struct attr *const attr = args->attr;
1364 const bgp_size_t length = args->length;
1365
bc3443eb 1366 in_addr_t nexthop_h, nexthop_n;
718e3744 1367
718e3744 1368 /* Check nexthop attribute length. */
1369 if (length != 4)
1370 {
16286195 1371 zlog_err ("Nexthop attribute length isn't four [%d]", length);
718e3744 1372
835315bf 1373 return bgp_attr_malformed (args,
b881c707 1374 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1375 args->total);
718e3744 1376 }
1377
58298ccd
DS
1378 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1379 attribute must result in a NOTIFICATION message (this is implemented below).
1380 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1381 logged locally (this is implemented somewhere else). The UPDATE message
1382 gets ignored in any of these cases. */
bc3443eb
DO
1383 nexthop_n = stream_get_ipv4 (peer->ibuf);
1384 nexthop_h = ntohl (nexthop_n);
cebb7440
LB
1385 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1386 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
bc3443eb
DO
1387 {
1388 char buf[INET_ADDRSTRLEN];
bb02b823 1389 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
16286195 1390 zlog_err ("Martian nexthop %s", buf);
835315bf 1391 return bgp_attr_malformed (args,
bc3443eb 1392 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
835315bf 1393 args->total);
bc3443eb
DO
1394 }
1395
1396 attr->nexthop.s_addr = nexthop_n;
718e3744 1397 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1398
b881c707 1399 return BGP_ATTR_PARSE_PROCEED;
718e3744 1400}
1401
1402/* MED atrribute. */
b881c707 1403static bgp_attr_parse_ret_t
835315bf 1404bgp_attr_med (struct bgp_attr_parser_args *args)
718e3744 1405{
835315bf
PJ
1406 struct peer *const peer = args->peer;
1407 struct attr *const attr = args->attr;
1408 const bgp_size_t length = args->length;
1409
718e3744 1410 /* Length check. */
1411 if (length != 4)
1412 {
16286195 1413 zlog_err ("MED attribute length isn't four [%d]", length);
b881c707 1414
835315bf 1415 return bgp_attr_malformed (args,
b881c707 1416 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1417 args->total);
718e3744 1418 }
1419
1420 attr->med = stream_getl (peer->ibuf);
1421
1422 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1423
b881c707 1424 return BGP_ATTR_PARSE_PROCEED;
718e3744 1425}
1426
1427/* Local preference attribute. */
b881c707 1428static bgp_attr_parse_ret_t
835315bf 1429bgp_attr_local_pref (struct bgp_attr_parser_args *args)
718e3744 1430{
835315bf
PJ
1431 struct peer *const peer = args->peer;
1432 struct attr *const attr = args->attr;
1433 const bgp_size_t length = args->length;
3ecab4c8 1434
a624cae2
DO
1435 /* Length check. */
1436 if (length != 4)
1437 {
16286195 1438 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length);
835315bf 1439 return bgp_attr_malformed (args,
a624cae2 1440 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1441 args->total);
a624cae2 1442 }
0ea968d2 1443
718e3744 1444 /* If it is contained in an UPDATE message that is received from an
1445 external peer, then this attribute MUST be ignored by the
1446 receiving speaker. */
6d85b15b 1447 if (peer->sort == BGP_PEER_EBGP)
718e3744 1448 {
9985f83c 1449 stream_forward_getp (peer->ibuf, length);
b881c707 1450 return BGP_ATTR_PARSE_PROCEED;
718e3744 1451 }
1452
a624cae2 1453 attr->local_pref = stream_getl (peer->ibuf);
718e3744 1454
1455 /* Set atomic aggregate flag. */
1456 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1457
b881c707 1458 return BGP_ATTR_PARSE_PROCEED;
718e3744 1459}
1460
1461/* Atomic aggregate. */
94f2b392 1462static int
835315bf 1463bgp_attr_atomic (struct bgp_attr_parser_args *args)
718e3744 1464{
835315bf
PJ
1465 struct attr *const attr = args->attr;
1466 const bgp_size_t length = args->length;
3ecab4c8 1467
9eba2ada 1468 /* Length check. */
718e3744 1469 if (length != 0)
1470 {
16286195 1471 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length);
835315bf 1472 return bgp_attr_malformed (args,
b881c707 1473 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1474 args->total);
718e3744 1475 }
1476
1477 /* Set atomic aggregate flag. */
1478 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1479
b881c707 1480 return BGP_ATTR_PARSE_PROCEED;
718e3744 1481}
1482
1483/* Aggregator attribute */
94f2b392 1484static int
835315bf 1485bgp_attr_aggregator (struct bgp_attr_parser_args *args)
718e3744 1486{
835315bf
PJ
1487 struct peer *const peer = args->peer;
1488 struct attr *const attr = args->attr;
1489 const bgp_size_t length = args->length;
1490
0b2aa3a0 1491 int wantedlen = 6;
fb982c25 1492 struct attr_extra *attre = bgp_attr_extra_get (attr);
3ecab4c8 1493
0b2aa3a0 1494 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
b881c707 1495 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
0b2aa3a0
PJ
1496 wantedlen = 8;
1497
1498 if (length != wantedlen)
718e3744 1499 {
16286195 1500 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen, length);
835315bf 1501 return bgp_attr_malformed (args,
b881c707 1502 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1503 args->total);
718e3744 1504 }
0b2aa3a0
PJ
1505
1506 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1507 attre->aggregator_as = stream_getl (peer->ibuf);
1508 else
1509 attre->aggregator_as = stream_getw (peer->ibuf);
fb982c25 1510 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
718e3744 1511
1512 /* Set atomic aggregate flag. */
1513 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1514
b881c707 1515 return BGP_ATTR_PARSE_PROCEED;
718e3744 1516}
1517
0b2aa3a0 1518/* New Aggregator attribute */
b881c707 1519static bgp_attr_parse_ret_t
835315bf
PJ
1520bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1521 as_t *as4_aggregator_as,
1522 struct in_addr *as4_aggregator_addr)
0b2aa3a0 1523{
835315bf
PJ
1524 struct peer *const peer = args->peer;
1525 struct attr *const attr = args->attr;
1526 const bgp_size_t length = args->length;
1527
0b2aa3a0
PJ
1528 if (length != 8)
1529 {
16286195 1530 zlog_err ("New Aggregator length is not 8 [%d]", length);
835315bf 1531 return bgp_attr_malformed (args,
b881c707 1532 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1533 0);
0b2aa3a0 1534 }
3ecab4c8 1535
0b2aa3a0
PJ
1536 *as4_aggregator_as = stream_getl (peer->ibuf);
1537 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1538
1539 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1540
b881c707 1541 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1542}
1543
1544/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1545 */
b881c707 1546static bgp_attr_parse_ret_t
835315bf
PJ
1547bgp_attr_munge_as4_attrs (struct peer *const peer,
1548 struct attr *const attr,
0b2aa3a0
PJ
1549 struct aspath *as4_path, as_t as4_aggregator,
1550 struct in_addr *as4_aggregator_addr)
1551{
1552 int ignore_as4_path = 0;
1553 struct aspath *newpath;
1554 struct attr_extra *attre = attr->extra;
bb7bef14
PJ
1555
1556 if (!attr->aspath)
1557 {
1558 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1559 * checked that all well-known, mandatory attributes were present.
1560 *
1561 * Can only be a problem with peer itself - hard error
1562 */
1563 return BGP_ATTR_PARSE_ERROR;
1564 }
1565
b881c707 1566 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
0b2aa3a0
PJ
1567 {
1568 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1569 * if given.
1570 * It is worth a warning though, because the peer really
1571 * should not send them
1572 */
1573 if (BGP_DEBUG(as4, AS4))
1574 {
1575 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1576 zlog_debug ("[AS4] %s %s AS4_PATH",
1577 peer->host, "AS4 capable peer, yet it sent");
1578
1579 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1580 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1581 peer->host, "AS4 capable peer, yet it sent");
1582 }
1583
b881c707 1584 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1585 }
1586
0b2aa3a0
PJ
1587 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1588 * because that may override AS4_PATH
1589 */
1590 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1591 {
b881c707 1592 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
0b2aa3a0 1593 {
370b64a2
PJ
1594 assert (attre);
1595
0b2aa3a0
PJ
1596 /* received both.
1597 * if the as_number in aggregator is not AS_TRANS,
1598 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1599 * and the Aggregator shall be taken as
1600 * info on the aggregating node, and the AS_PATH
1601 * shall be taken as the AS_PATH
1602 * otherwise
1603 * the Aggregator shall be ignored and the
1604 * AS4_AGGREGATOR shall be taken as the
1605 * Aggregating node and the AS_PATH is to be
1606 * constructed "as in all other cases"
1607 */
b881c707 1608 if (attre->aggregator_as != BGP_AS_TRANS)
0b2aa3a0
PJ
1609 {
1610 /* ignore */
1611 if ( BGP_DEBUG(as4, AS4))
1612 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1613 " send AGGREGATOR != AS_TRANS and"
1614 " AS4_AGGREGATOR, so ignore"
1615 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1616 ignore_as4_path = 1;
1617 }
1618 else
1619 {
1620 /* "New_aggregator shall be taken as aggregator" */
1621 attre->aggregator_as = as4_aggregator;
1622 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1623 }
1624 }
1625 else
1626 {
1627 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1628 * That is bogus - but reading the conditions
1629 * we have to handle AS4_AGGREGATOR as if it were
1630 * AGGREGATOR in that case
1631 */
1632 if ( BGP_DEBUG(as4, AS4))
1633 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1634 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1635 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
370b64a2 1636 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
0b2aa3a0
PJ
1637 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1638 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1639 }
1640 }
1641
1642 /* need to reconcile NEW_AS_PATH and AS_PATH */
b881c707 1643 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
0b2aa3a0 1644 {
bb7bef14
PJ
1645 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1646 aspath_unintern (&attr->aspath);
1647 attr->aspath = aspath_intern (newpath);
0b2aa3a0 1648 }
b881c707 1649 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1650}
1651
718e3744 1652/* Community attribute. */
b881c707 1653static bgp_attr_parse_ret_t
835315bf 1654bgp_attr_community (struct bgp_attr_parser_args *args)
718e3744 1655{
835315bf
PJ
1656 struct peer *const peer = args->peer;
1657 struct attr *const attr = args->attr;
1658 const bgp_size_t length = args->length;
b881c707 1659
718e3744 1660 if (length == 0)
b2ceea18
PJ
1661 {
1662 attr->community = NULL;
b881c707 1663 return BGP_ATTR_PARSE_PROCEED;
b2ceea18 1664 }
0c466381
PJ
1665
1666 attr->community =
1667 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1668
1669 /* XXX: fix community_parse to use stream API and remove this */
1670 stream_forward_getp (peer->ibuf, length);
718e3744 1671
0c466381 1672 if (!attr->community)
835315bf 1673 return bgp_attr_malformed (args,
b881c707 1674 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
835315bf 1675 args->total);
0c466381 1676
718e3744 1677 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1678
b881c707 1679 return BGP_ATTR_PARSE_PROCEED;
718e3744 1680}
1681
1682/* Originator ID attribute. */
b881c707 1683static bgp_attr_parse_ret_t
835315bf 1684bgp_attr_originator_id (struct bgp_attr_parser_args *args)
718e3744 1685{
835315bf
PJ
1686 struct peer *const peer = args->peer;
1687 struct attr *const attr = args->attr;
1688 const bgp_size_t length = args->length;
1689
d595b566 1690 /* Length check. */
718e3744 1691 if (length != 4)
1692 {
16286195 1693 zlog_err ("Bad originator ID length %d", length);
718e3744 1694
835315bf 1695 return bgp_attr_malformed (args,
b881c707 1696 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1697 args->total);
718e3744 1698 }
1699
fb982c25
PJ
1700 (bgp_attr_extra_get (attr))->originator_id.s_addr
1701 = stream_get_ipv4 (peer->ibuf);
718e3744 1702
1703 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1704
b881c707 1705 return BGP_ATTR_PARSE_PROCEED;
718e3744 1706}
1707
1708/* Cluster list attribute. */
b881c707 1709static bgp_attr_parse_ret_t
835315bf 1710bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
718e3744 1711{
835315bf
PJ
1712 struct peer *const peer = args->peer;
1713 struct attr *const attr = args->attr;
1714 const bgp_size_t length = args->length;
1715
718e3744 1716 /* Check length. */
1717 if (length % 4)
1718 {
16286195 1719 zlog_err ("Bad cluster list length %d", length);
718e3744 1720
835315bf
PJ
1721 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1722 args->total);
718e3744 1723 }
1724
fb982c25
PJ
1725 (bgp_attr_extra_get (attr))->cluster
1726 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
b881c707
PJ
1727
1728 /* XXX: Fix cluster_parse to use stream API and then remove this */
1729 stream_forward_getp (peer->ibuf, length);
718e3744 1730
1731 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1732
b881c707 1733 return BGP_ATTR_PARSE_PROCEED;
718e3744 1734}
1735
1736/* Multiprotocol reachability information parse. */
03292809 1737int
835315bf
PJ
1738bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1739 struct bgp_nlri *mp_update)
718e3744 1740{
4c9641ba
ML
1741 afi_t afi;
1742 safi_t safi;
718e3744 1743 bgp_size_t nlri_len;
6e4ab12f 1744 size_t start;
718e3744 1745 int ret;
d889623f 1746 int num_mp_pfx = 0;
718e3744 1747 struct stream *s;
835315bf
PJ
1748 struct peer *const peer = args->peer;
1749 struct attr *const attr = args->attr;
1750 const bgp_size_t length = args->length;
fb982c25 1751 struct attr_extra *attre = bgp_attr_extra_get(attr);
835315bf 1752
718e3744 1753 /* Set end of packet. */
6e4ab12f
PJ
1754 s = BGP_INPUT(peer);
1755 start = stream_get_getp(s);
1756
1757 /* safe to read statically sized header? */
1758#define BGP_MP_REACH_MIN_SIZE 5
03292809 1759#define LEN_LEFT (length - (stream_get_getp(s) - start))
6e4ab12f 1760 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
03292809
PJ
1761 {
1762 zlog_info ("%s: %s sent invalid length, %lu",
1763 __func__, peer->host, (unsigned long)length);
f57000c0 1764 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 1765 }
6e4ab12f 1766
718e3744 1767 /* Load AFI, SAFI. */
1768 afi = stream_getw (s);
1769 safi = stream_getc (s);
1770
1771 /* Get nexthop length. */
fb982c25 1772 attre->mp_nexthop_len = stream_getc (s);
6e4ab12f 1773
03292809
PJ
1774 if (LEN_LEFT < attre->mp_nexthop_len)
1775 {
1776 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1777 __func__, peer->host, attre->mp_nexthop_len);
f57000c0 1778 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 1779 }
6e4ab12f 1780
718e3744 1781 /* Nexthop length check. */
fb982c25 1782 switch (attre->mp_nexthop_len)
718e3744 1783 {
801a9bcc
DS
1784 case BGP_ATTR_NHLEN_IPV4:
1785 stream_get (&attre->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
66bed4f4
ML
1786 /* Probably needed for RFC 2283 */
1787 if (attr->nexthop.s_addr == 0)
801a9bcc 1788 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
718e3744 1789 break;
801a9bcc 1790 case BGP_ATTR_NHLEN_VPNV4:
9206f9ec
SH
1791 stream_getl (s); /* RD high */
1792 stream_getl (s); /* RD low */
801a9bcc 1793 stream_get (&attre->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
718e3744 1794 break;
1795#ifdef HAVE_IPV6
801a9bcc 1796 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
945c8fe9
LB
1797 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
1798 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL)
1799 {
1800 stream_getl (s); /* RD high */
1801 stream_getl (s); /* RD low */
1802 }
801a9bcc 1803 stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
718e3744 1804 break;
801a9bcc 1805 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
945c8fe9
LB
1806 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
1807 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
1808 {
1809 stream_getl (s); /* RD high */
1810 stream_getl (s); /* RD low */
1811 }
801a9bcc 1812 stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
945c8fe9
LB
1813 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
1814 {
1815 stream_getl (s); /* RD high */
1816 stream_getl (s); /* RD low */
1817 }
801a9bcc 1818 stream_get (&attre->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
fb982c25 1819 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
718e3744 1820 {
1821 char buf1[INET6_ADDRSTRLEN];
1822 char buf2[INET6_ADDRSTRLEN];
1823
3f9c7369 1824 if (bgp_debug_update(peer, NULL, NULL, 1))
3dd32081
DS
1825 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1826 peer->host,
fb982c25 1827 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
718e3744 1828 buf1, INET6_ADDRSTRLEN),
fb982c25 1829 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
718e3744 1830 buf2, INET6_ADDRSTRLEN));
1831
801a9bcc 1832 attre->mp_nexthop_len = IPV6_MAX_BYTELEN;
718e3744 1833 }
1834 break;
1835#endif /* HAVE_IPV6 */
1836 default:
03292809
PJ
1837 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1838 __func__, peer->host, attre->mp_nexthop_len);
f57000c0 1839 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
718e3744 1840 }
1841
03292809
PJ
1842 if (!LEN_LEFT)
1843 {
1844 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1845 __func__, peer->host);
f57000c0 1846 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 1847 }
718e3744 1848
6e4ab12f
PJ
1849 {
1850 u_char val;
1851 if ((val = stream_getc (s)))
1852 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1853 peer->host, val);
1854 }
1855
1856 /* must have nrli_len, what is left of the attribute */
03292809 1857 nlri_len = LEN_LEFT;
6e4ab12f 1858 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
03292809
PJ
1859 {
1860 zlog_info ("%s: (%s) Failed to read NLRI",
1861 __func__, peer->host);
f57000c0 1862 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 1863 }
718e3744 1864
42e6d745 1865 if (safi != SAFI_MPLS_LABELED_VPN)
718e3744 1866 {
a82478b9
DS
1867 ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
1868 nlri_len, &num_mp_pfx);
03292809
PJ
1869 if (ret < 0)
1870 {
1871 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1872 __func__, peer->host);
f57000c0 1873 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 1874 }
718e3744 1875 }
1876
1877 mp_update->afi = afi;
1878 mp_update->safi = safi;
1879 mp_update->nlri = stream_pnt (s);
1880 mp_update->length = nlri_len;
1881
9985f83c 1882 stream_forward_getp (s, nlri_len);
718e3744 1883
37da8fa9
DL
1884 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1885
b881c707 1886 return BGP_ATTR_PARSE_PROCEED;
03292809 1887#undef LEN_LEFT
718e3744 1888}
1889
1890/* Multiprotocol unreachable parse */
03292809 1891int
835315bf 1892bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
718e3744 1893 struct bgp_nlri *mp_withdraw)
1894{
1895 struct stream *s;
4c9641ba
ML
1896 afi_t afi;
1897 safi_t safi;
718e3744 1898 u_int16_t withdraw_len;
1899 int ret;
d889623f 1900 int num_mp_pfx = 0;
835315bf 1901 struct peer *const peer = args->peer;
37da8fa9 1902 struct attr *const attr = args->attr;
835315bf 1903 const bgp_size_t length = args->length;
718e3744 1904
1905 s = peer->ibuf;
6e4ab12f
PJ
1906
1907#define BGP_MP_UNREACH_MIN_SIZE 3
1908 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
f57000c0 1909 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
6e4ab12f 1910
718e3744 1911 afi = stream_getw (s);
1912 safi = stream_getc (s);
6e4ab12f
PJ
1913
1914 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
718e3744 1915
42e6d745 1916 if (safi != SAFI_MPLS_LABELED_VPN)
718e3744 1917 {
a82478b9
DS
1918 ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
1919 withdraw_len, &num_mp_pfx);
718e3744 1920 if (ret < 0)
f57000c0 1921 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
718e3744 1922 }
1923
1924 mp_withdraw->afi = afi;
1925 mp_withdraw->safi = safi;
1926 mp_withdraw->nlri = stream_pnt (s);
1927 mp_withdraw->length = withdraw_len;
1928
9985f83c 1929 stream_forward_getp (s, withdraw_len);
718e3744 1930
37da8fa9
DL
1931 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1932
b881c707 1933 return BGP_ATTR_PARSE_PROCEED;
718e3744 1934}
1935
1936/* Extended Community attribute. */
b881c707 1937static bgp_attr_parse_ret_t
835315bf 1938bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
718e3744 1939{
835315bf
PJ
1940 struct peer *const peer = args->peer;
1941 struct attr *const attr = args->attr;
1942 const bgp_size_t length = args->length;
b881c707 1943
718e3744 1944 if (length == 0)
fb982c25
PJ
1945 {
1946 if (attr->extra)
1947 attr->extra->ecommunity = NULL;
0c466381 1948 /* Empty extcomm doesn't seem to be invalid per se */
b881c707 1949 return BGP_ATTR_PARSE_PROCEED;
fb982c25 1950 }
0c466381
PJ
1951
1952 (bgp_attr_extra_get (attr))->ecommunity =
1953 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1954 /* XXX: fix ecommunity_parse to use stream API */
1955 stream_forward_getp (peer->ibuf, length);
1956
1957 if (!attr->extra->ecommunity)
835315bf
PJ
1958 return bgp_attr_malformed (args,
1959 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1960 args->total);
0c466381 1961
718e3744 1962 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1963
b881c707 1964 return BGP_ATTR_PARSE_PROCEED;
718e3744 1965}
1966
f4c89855
LB
1967/* Parse Tunnel Encap attribute in an UPDATE */
1968static int
1969bgp_attr_encap(
1970 uint8_t type,
1971 struct peer *peer, /* IN */
1972 bgp_size_t length, /* IN: attr's length field */
1973 struct attr *attr, /* IN: caller already allocated */
1974 u_char flag, /* IN: attr's flags field */
1975 u_char *startp)
1976{
1977 bgp_size_t total;
1978 struct attr_extra *attre = NULL;
1979 struct bgp_attr_encap_subtlv *stlv_last = NULL;
2de1475f 1980 uint16_t tunneltype = 0;
f4c89855
LB
1981
1982 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1983
1984 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1985 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1986 {
1987 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1988 bgp_notify_send_with_data (peer,
1989 BGP_NOTIFY_UPDATE_ERR,
1990 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1991 startp, total);
1992 return -1;
1993 }
1994
1995 if (BGP_ATTR_ENCAP == type) {
1996 /* read outer TLV type and length */
1997 uint16_t tlv_length;
1998
1999 if (length < 4) {
2000 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2001 bgp_notify_send_with_data(peer,
2002 BGP_NOTIFY_UPDATE_ERR,
2003 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2004 startp, total);
2005 return -1;
2006 }
2007 tunneltype = stream_getw (BGP_INPUT (peer));
2008 tlv_length = stream_getw (BGP_INPUT (peer));
2009 length -= 4;
2010
2011 if (tlv_length != length) {
2012 zlog_info ("%s: tlv_length(%d) != length(%d)",
2013 __func__, tlv_length, length);
2014 }
2015 }
2016
2017 while (length >= 4) {
0f2b4f4d 2018 uint16_t subtype = 0;
f4cafc65 2019 uint16_t sublength = 0;
f4c89855
LB
2020 struct bgp_attr_encap_subtlv *tlv;
2021
587ff0fd
LB
2022 if (BGP_ATTR_ENCAP == type) {
2023 subtype = stream_getc (BGP_INPUT (peer));
2024 sublength = stream_getc (BGP_INPUT (peer));
2025 length -= 2;
65efcfce
LB
2026#if ENABLE_BGP_VNC
2027 } else {
2028 subtype = stream_getw (BGP_INPUT (peer));
2029 sublength = stream_getw (BGP_INPUT (peer));
2030 length -= 4;
2031#endif
587ff0fd 2032 }
f4c89855
LB
2033
2034 if (sublength > length) {
2035 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2036 sublength, length);
2037 bgp_notify_send_with_data (peer,
2038 BGP_NOTIFY_UPDATE_ERR,
2039 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2040 startp, total);
2041 return -1;
2042 }
2043
2044 /* alloc and copy sub-tlv */
2045 /* TBD make sure these are freed when attributes are released */
2046 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
2047 tlv->type = subtype;
2048 tlv->length = sublength;
2049 stream_get(tlv->value, peer->ibuf, sublength);
2050 length -= sublength;
2051
2052 /* attach tlv to encap chain */
2053 if (!attre) {
2054 attre = bgp_attr_extra_get(attr);
2055 if (BGP_ATTR_ENCAP == type) {
2056 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
2057 stlv_last = stlv_last->next);
2058 if (stlv_last) {
2059 stlv_last->next = tlv;
2060 } else {
2061 attre->encap_subtlvs = tlv;
2062 }
65efcfce
LB
2063#if ENABLE_BGP_VNC
2064 } else {
2065 for (stlv_last = attre->vnc_subtlvs; stlv_last && stlv_last->next;
2066 stlv_last = stlv_last->next);
2067 if (stlv_last) {
2068 stlv_last->next = tlv;
2069 } else {
2070 attre->vnc_subtlvs = tlv;
2071 }
2072#endif
f4c89855
LB
2073 }
2074 } else {
2075 stlv_last->next = tlv;
2076 }
2077 stlv_last = tlv;
2078 }
2079
2080 if (attre && (BGP_ATTR_ENCAP == type)) {
2081 attre->encap_tunneltype = tunneltype;
2082 }
2083
2084 if (length) {
2085 /* spurious leftover data */
2086 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length);
2087 bgp_notify_send_with_data (peer,
2088 BGP_NOTIFY_UPDATE_ERR,
2089 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2090 startp, total);
2091 return -1;
2092 }
2093
2094 return 0;
2095}
2096
718e3744 2097/* BGP unknown attribute treatment. */
b881c707 2098static bgp_attr_parse_ret_t
835315bf 2099bgp_attr_unknown (struct bgp_attr_parser_args *args)
718e3744 2100{
8794e8d2 2101 bgp_size_t total = args->total;
718e3744 2102 struct transit *transit;
fb982c25 2103 struct attr_extra *attre;
835315bf
PJ
2104 struct peer *const peer = args->peer;
2105 struct attr *const attr = args->attr;
2106 u_char *const startp = args->startp;
2107 const u_char type = args->type;
2108 const u_char flag = args->flags;
2109 const bgp_size_t length = args->length;
2110
3f9c7369 2111 if (bgp_debug_update(peer, NULL, NULL, 1))
16286195
DS
2112 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2113 peer->host, type, length);
f418446b 2114
718e3744 2115 /* Forward read pointer of input stream. */
9985f83c 2116 stream_forward_getp (peer->ibuf, length);
718e3744 2117
718e3744 2118 /* If any of the mandatory well-known attributes are not recognized,
2119 then the Error Subcode is set to Unrecognized Well-known
2120 Attribute. The Data field contains the unrecognized attribute
2121 (type, length and value). */
b881c707 2122 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
718e3744 2123 {
835315bf 2124 return bgp_attr_malformed (args,
b881c707 2125 BGP_NOTIFY_UPDATE_UNREC_ATTR,
835315bf 2126 args->total);
718e3744 2127 }
2128
2129 /* Unrecognized non-transitive optional attributes must be quietly
2130 ignored and not passed along to other BGP peers. */
2131 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
b881c707 2132 return BGP_ATTR_PARSE_PROCEED;
718e3744 2133
2134 /* If a path with recognized transitive optional attribute is
2135 accepted and passed along to other BGP peers and the Partial bit
2136 in the Attribute Flags octet is set to 1 by some previous AS, it
2137 is not set back to 0 by the current AS. */
2138 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
2139
2140 /* Store transitive attribute to the end of attr->transit. */
fb982c25 2141 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
393deb9b 2142 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
718e3744 2143
fb982c25 2144 transit = attre->transit;
718e3744 2145
2146 if (transit->val)
2147 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
2148 transit->length + total);
2149 else
2150 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2151
2152 memcpy (transit->val + transit->length, startp, total);
2153 transit->length += total;
2154
b881c707 2155 return BGP_ATTR_PARSE_PROCEED;
718e3744 2156}
2157
bb7bef14
PJ
2158/* Well-known attribute check. */
2159static int
52a51fd3 2160bgp_attr_check (struct peer *peer, struct attr *attr)
bb7bef14
PJ
2161{
2162 u_char type = 0;
2163
67495ddb
PJ
2164 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2165 * empty UPDATE. */
2166 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2167 return BGP_ATTR_PARSE_PROCEED;
2168
2169 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2170 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2171 are present, it should. Check for any other attribute being present
2172 instead.
2173 */
2174 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2175 return BGP_ATTR_PARSE_PROCEED;
2176
bb7bef14
PJ
2177 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2178 type = BGP_ATTR_ORIGIN;
2179
2180 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2181 type = BGP_ATTR_AS_PATH;
2182
52a51fd3
DW
2183 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2184 * NLRI is empty. We can't easily check NLRI empty here though.
bb7bef14 2185 */
52a51fd3
DW
2186 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2187 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
2188 type = BGP_ATTR_NEXT_HOP;
bb7bef14
PJ
2189
2190 if (peer->sort == BGP_PEER_IBGP
2191 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2192 type = BGP_ATTR_LOCAL_PREF;
2193
2194 if (type)
2195 {
52a51fd3
DW
2196 zlog_warn ("%s Missing well-known attribute %s.", peer->host,
2197 LOOKUP (attr_str, type));
bb7bef14
PJ
2198 bgp_notify_send_with_data (peer,
2199 BGP_NOTIFY_UPDATE_ERR,
2200 BGP_NOTIFY_UPDATE_MISS_ATTR,
2201 &type, 1);
2202 return BGP_ATTR_PARSE_ERROR;
2203 }
2204 return BGP_ATTR_PARSE_PROCEED;
2205}
2206
718e3744 2207/* Read attribute of update packet. This function is called from
8b366b9c 2208 bgp_update_receive() in bgp_packet.c. */
b881c707 2209bgp_attr_parse_ret_t
718e3744 2210bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
52a51fd3 2211 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
718e3744 2212{
2213 int ret;
b881c707 2214 u_char flag = 0;
0b2aa3a0 2215 u_char type = 0;
718e3744 2216 bgp_size_t length;
2217 u_char *startp, *endp;
2218 u_char *attr_endp;
2219 u_char seen[BGP_ATTR_BITMAP_SIZE];
0b2aa3a0
PJ
2220 /* we need the as4_path only until we have synthesized the as_path with it */
2221 /* same goes for as4_aggregator */
2222 struct aspath *as4_path = NULL;
2223 as_t as4_aggregator = 0;
19c3598b 2224 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
718e3744 2225
2226 /* Initialize bitmap. */
2227 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2228
2229 /* End pointer of BGP attribute. */
2230 endp = BGP_INPUT_PNT (peer) + size;
b881c707 2231
718e3744 2232 /* Get attributes to the end of attribute length. */
2233 while (BGP_INPUT_PNT (peer) < endp)
2234 {
2235 /* Check remaining length check.*/
2236 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2237 {
c29fdba7 2238 /* XXX warning: long int format, int arg (arg 5) */
16286195
DS
2239 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2240 peer->host,
2241 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
718e3744 2242
2243 bgp_notify_send (peer,
2244 BGP_NOTIFY_UPDATE_ERR,
2245 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707 2246 return BGP_ATTR_PARSE_ERROR;
718e3744 2247 }
2248
2249 /* Fetch attribute flag and type. */
2250 startp = BGP_INPUT_PNT (peer);
2d42e68a
DO
2251 /* "The lower-order four bits of the Attribute Flags octet are
2252 unused. They MUST be zero when sent and MUST be ignored when
2253 received." */
2254 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
718e3744 2255 type = stream_getc (BGP_INPUT (peer));
2256
370b64a2
PJ
2257 /* Check whether Extended-Length applies and is in bounds */
2258 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2259 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2260 {
16286195
DS
2261 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2262 peer->host,
2263 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
370b64a2
PJ
2264
2265 bgp_notify_send (peer,
2266 BGP_NOTIFY_UPDATE_ERR,
2267 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707 2268 return BGP_ATTR_PARSE_ERROR;
370b64a2 2269 }
835315bf 2270
718e3744 2271 /* Check extended attribue length bit. */
2272 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2273 length = stream_getw (BGP_INPUT (peer));
2274 else
2275 length = stream_getc (BGP_INPUT (peer));
2276
2277 /* If any attribute appears more than once in the UPDATE
2278 message, then the Error Subcode is set to Malformed Attribute
2279 List. */
2280
2281 if (CHECK_BITMAP (seen, type))
2282 {
16286195
DS
2283 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2284 peer->host, type);
718e3744 2285
2286 bgp_notify_send (peer,
2287 BGP_NOTIFY_UPDATE_ERR,
2288 BGP_NOTIFY_UPDATE_MAL_ATTR);
b881c707 2289 return BGP_ATTR_PARSE_ERROR;
718e3744 2290 }
2291
2292 /* Set type to bitmap to check duplicate attribute. `type' is
2293 unsigned char so it never overflow bitmap range. */
2294
2295 SET_BITMAP (seen, type);
2296
2297 /* Overflow check. */
2298 attr_endp = BGP_INPUT_PNT (peer) + length;
2299
2300 if (attr_endp > endp)
2301 {
16286195 2302 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
2303 bgp_notify_send_with_data (peer,
2304 BGP_NOTIFY_UPDATE_ERR,
2305 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2306 startp, attr_endp - startp);
b881c707 2307 return BGP_ATTR_PARSE_ERROR;
718e3744 2308 }
835315bf
PJ
2309
2310 struct bgp_attr_parser_args attr_args = {
2311 .peer = peer,
2312 .length = length,
2313 .attr = attr,
2314 .type = type,
2315 .flags = flag,
2316 .startp = startp,
2317 .total = attr_endp - startp,
2318 };
2319
2320
2321 /* If any recognized attribute has Attribute Flags that conflict
2322 with the Attribute Type Code, then the Error Subcode is set to
2323 Attribute Flags Error. The Data field contains the erroneous
2324 attribute (type, length and value). */
2325 if (bgp_attr_flag_invalid (&attr_args))
fa61e16d
PJ
2326 {
2327 bgp_attr_parse_ret_t ret;
2328 ret = bgp_attr_malformed (&attr_args,
2329 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2330 attr_args.total);
2331 if (ret == BGP_ATTR_PARSE_PROCEED)
2332 continue;
2333 return ret;
2334 }
718e3744 2335
2336 /* OK check attribute and store it's value. */
2337 switch (type)
2338 {
2339 case BGP_ATTR_ORIGIN:
835315bf 2340 ret = bgp_attr_origin (&attr_args);
718e3744 2341 break;
2342 case BGP_ATTR_AS_PATH:
835315bf 2343 ret = bgp_attr_aspath (&attr_args);
718e3744 2344 break;
0b2aa3a0 2345 case BGP_ATTR_AS4_PATH:
835315bf 2346 ret = bgp_attr_as4_path (&attr_args, &as4_path);
0b2aa3a0 2347 break;
718e3744 2348 case BGP_ATTR_NEXT_HOP:
835315bf 2349 ret = bgp_attr_nexthop (&attr_args);
718e3744 2350 break;
2351 case BGP_ATTR_MULTI_EXIT_DISC:
835315bf 2352 ret = bgp_attr_med (&attr_args);
718e3744 2353 break;
2354 case BGP_ATTR_LOCAL_PREF:
835315bf 2355 ret = bgp_attr_local_pref (&attr_args);
718e3744 2356 break;
2357 case BGP_ATTR_ATOMIC_AGGREGATE:
835315bf 2358 ret = bgp_attr_atomic (&attr_args);
718e3744 2359 break;
2360 case BGP_ATTR_AGGREGATOR:
835315bf 2361 ret = bgp_attr_aggregator (&attr_args);
718e3744 2362 break;
0b2aa3a0 2363 case BGP_ATTR_AS4_AGGREGATOR:
835315bf
PJ
2364 ret = bgp_attr_as4_aggregator (&attr_args,
2365 &as4_aggregator,
2366 &as4_aggregator_addr);
0b2aa3a0 2367 break;
718e3744 2368 case BGP_ATTR_COMMUNITIES:
835315bf 2369 ret = bgp_attr_community (&attr_args);
718e3744 2370 break;
2371 case BGP_ATTR_ORIGINATOR_ID:
835315bf 2372 ret = bgp_attr_originator_id (&attr_args);
718e3744 2373 break;
2374 case BGP_ATTR_CLUSTER_LIST:
835315bf 2375 ret = bgp_attr_cluster_list (&attr_args);
718e3744 2376 break;
2377 case BGP_ATTR_MP_REACH_NLRI:
835315bf 2378 ret = bgp_mp_reach_parse (&attr_args, mp_update);
718e3744 2379 break;
2380 case BGP_ATTR_MP_UNREACH_NLRI:
835315bf 2381 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
718e3744 2382 break;
2383 case BGP_ATTR_EXT_COMMUNITIES:
835315bf 2384 ret = bgp_attr_ext_communities (&attr_args);
718e3744 2385 break;
65efcfce
LB
2386#if ENABLE_BGP_VNC
2387 case BGP_ATTR_VNC:
2388#endif
f4c89855
LB
2389 case BGP_ATTR_ENCAP:
2390 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2391 break;
718e3744 2392 default:
835315bf 2393 ret = bgp_attr_unknown (&attr_args);
718e3744 2394 break;
2395 }
b881c707 2396
f57000c0
DL
2397 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2398 {
2399 bgp_notify_send (peer,
2400 BGP_NOTIFY_UPDATE_ERR,
2401 BGP_NOTIFY_UPDATE_MAL_ATTR);
2402 ret = BGP_ATTR_PARSE_ERROR;
2403 }
2404
b881c707
PJ
2405 /* If hard error occured immediately return to the caller. */
2406 if (ret == BGP_ATTR_PARSE_ERROR)
6e4ab12f 2407 {
16286195
DS
2408 zlog_warn ("%s: Attribute %s, parse error",
2409 peer->host,
2410 LOOKUP (attr_str, type));
b881c707
PJ
2411 if (as4_path)
2412 aspath_unintern (&as4_path);
2413 return ret;
6e4ab12f 2414 }
b881c707
PJ
2415 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2416 {
2417
16286195
DS
2418 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2419 peer->host,
2420 LOOKUP (attr_str, type));
b881c707
PJ
2421 if (as4_path)
2422 aspath_unintern (&as4_path);
2423 return ret;
2424 }
2425
718e3744 2426 /* Check the fetched length. */
2427 if (BGP_INPUT_PNT (peer) != attr_endp)
2428 {
16286195
DS
2429 zlog_warn ("%s: BGP attribute %s, fetch error",
2430 peer->host, LOOKUP (attr_str, type));
718e3744 2431 bgp_notify_send (peer,
2432 BGP_NOTIFY_UPDATE_ERR,
2433 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707
PJ
2434 if (as4_path)
2435 aspath_unintern (&as4_path);
2436 return BGP_ATTR_PARSE_ERROR;
718e3744 2437 }
2438 }
2439
2440 /* Check final read pointer is same as end pointer. */
2441 if (BGP_INPUT_PNT (peer) != endp)
2442 {
16286195
DS
2443 zlog_warn ("%s: BGP attribute %s, length mismatch",
2444 peer->host, LOOKUP (attr_str, type));
718e3744 2445 bgp_notify_send (peer,
2446 BGP_NOTIFY_UPDATE_ERR,
2447 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707
PJ
2448 if (as4_path)
2449 aspath_unintern (&as4_path);
2450 return BGP_ATTR_PARSE_ERROR;
718e3744 2451 }
2452
bb7bef14
PJ
2453 /* Check all mandatory well-known attributes are present */
2454 {
2455 bgp_attr_parse_ret_t ret;
52a51fd3 2456 if ((ret = bgp_attr_check (peer, attr)) < 0)
bb7bef14
PJ
2457 {
2458 if (as4_path)
2459 aspath_unintern (&as4_path);
2460 return ret;
2461 }
2462 }
2463
0b2aa3a0
PJ
2464 /*
2465 * At this place we can see whether we got AS4_PATH and/or
2466 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2467 * We can not do this before we've read all attributes because
2468 * the as4 handling does not say whether AS4_PATH has to be sent
2469 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2470 * in relationship to AGGREGATOR.
2471 * So, to be defensive, we are not relying on any order and read
2472 * all attributes first, including these 32bit ones, and now,
2473 * afterwards, we look what and if something is to be done for as4.
67495ddb
PJ
2474 *
2475 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2476 * MP_UNREACH_NLRI.
0b2aa3a0 2477 */
f57000c0
DL
2478 /* actually... this doesn't ever return failure currently, but
2479 * better safe than sorry */
67495ddb
PJ
2480 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2481 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
0b2aa3a0 2482 as4_aggregator, &as4_aggregator_addr))
b881c707 2483 {
f57000c0
DL
2484 bgp_notify_send (peer,
2485 BGP_NOTIFY_UPDATE_ERR,
2486 BGP_NOTIFY_UPDATE_MAL_ATTR);
b881c707
PJ
2487 if (as4_path)
2488 aspath_unintern (&as4_path);
2489 return BGP_ATTR_PARSE_ERROR;
2490 }
0b2aa3a0
PJ
2491
2492 /* At this stage, we have done all fiddling with as4, and the
2493 * resulting info is in attr->aggregator resp. attr->aspath
2494 * so we can chuck as4_aggregator and as4_path alltogether in
2495 * order to save memory
2496 */
b881c707 2497 if (as4_path)
0b2aa3a0 2498 {
f6f434b2 2499 aspath_unintern (&as4_path); /* unintern - it is in the hash */
0b2aa3a0
PJ
2500 /* The flag that we got this is still there, but that does not
2501 * do any trouble
2502 */
2503 }
2504 /*
2505 * The "rest" of the code does nothing with as4_aggregator.
2506 * there is no memory attached specifically which is not part
2507 * of the attr.
2508 * so ignoring just means do nothing.
2509 */
2510 /*
2511 * Finally do the checks on the aspath we did not do yet
2512 * because we waited for a potentially synthesized aspath.
2513 */
b881c707 2514 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
0b2aa3a0 2515 {
835315bf 2516 ret = bgp_attr_aspath_check (peer, attr);
b881c707 2517 if (ret != BGP_ATTR_PARSE_PROCEED)
0b2aa3a0
PJ
2518 return ret;
2519 }
2520
718e3744 2521 /* Finally intern unknown attribute. */
fb982c25
PJ
2522 if (attr->extra && attr->extra->transit)
2523 attr->extra->transit = transit_intern (attr->extra->transit);
718e3744 2524
b881c707 2525 return BGP_ATTR_PARSE_PROCEED;
718e3744 2526}
2527
8c71e481 2528size_t
8a92a8a0 2529bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
3f9c7369 2530 struct bpacket_attr_vec_arr *vecarr,
8c71e481
PM
2531 struct attr *attr)
2532{
2533 size_t sizep;
2534
2535 /* Set extended bit always to encode the attribute length as 2 bytes */
2536 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2537 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2538 sizep = stream_get_endp (s);
2539 stream_putw (s, 0); /* Marker: Attribute length. */
93b73dfa
LB
2540
2541 stream_putw (s, afi);
2542 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
8c71e481
PM
2543
2544 /* Nexthop */
8a92a8a0 2545 switch (nh_afi)
8c71e481
PM
2546 {
2547 case AFI_IP:
2548 switch (safi)
2549 {
6407da5a 2550 case SAFI_UNICAST:
8c71e481 2551 case SAFI_MULTICAST:
3f9c7369 2552 bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
8c71e481
PM
2553 stream_putc (s, 4);
2554 stream_put_ipv4 (s, attr->nexthop.s_addr);
2555 break;
2556 case SAFI_MPLS_VPN:
3f9c7369 2557 bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
8c71e481 2558 stream_putc (s, 12);
93b73dfa 2559 stream_putl (s, 0); /* RD = 0, per RFC */
8c71e481
PM
2560 stream_putl (s, 0);
2561 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2562 break;
587ff0fd
LB
2563 case SAFI_ENCAP:
2564 stream_putc (s, 4);
2565 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2566 break;
8c71e481
PM
2567 default:
2568 break;
2569 }
2570 break;
2571#ifdef HAVE_IPV6
2572 case AFI_IP6:
2573 switch (safi)
2574 {
2575 case SAFI_UNICAST:
2576 case SAFI_MULTICAST:
2577 {
8c71e481
PM
2578 struct attr_extra *attre = attr->extra;
2579
2580 assert (attr->extra);
3f9c7369 2581 bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
8c71e481 2582 stream_putc (s, attre->mp_nexthop_len);
801a9bcc
DS
2583 stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
2584 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
2585 stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
8c71e481 2586 }
93b73dfa
LB
2587 break;
2588 case SAFI_MPLS_VPN:
2589 {
2590 struct attr_extra *attre = attr->extra;
2591
2592 assert (attr->extra);
6407da5a 2593 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
93b73dfa
LB
2594 stream_putc (s, 24);
2595 stream_putl (s, 0); /* RD = 0, per RFC */
2596 stream_putl (s, 0);
6407da5a 2597 stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
2598 } else if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
93b73dfa
LB
2599 stream_putc (s, 48);
2600 stream_putl (s, 0); /* RD = 0, per RFC */
2601 stream_putl (s, 0);
6407da5a 2602 stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
93b73dfa
LB
2603 stream_putl (s, 0); /* RD = 0, per RFC */
2604 stream_putl (s, 0);
6407da5a 2605 stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
93b73dfa
LB
2606 }
2607 }
2608 break;
587ff0fd
LB
2609 case SAFI_ENCAP:
2610 assert (attr->extra);
2611 stream_putc (s, IPV6_MAX_BYTELEN);
2612 stream_put (s, &attr->extra->mp_nexthop_global, IPV6_MAX_BYTELEN);
2613 break;
8c71e481
PM
2614 default:
2615 break;
2616 }
2617 break;
2618#endif /*HAVE_IPV6*/
2619 default:
2620 break;
2621 }
2622
2623 /* SNPA */
2624 stream_putc (s, 0);
2625 return sizep;
2626}
2627
2628void
2629bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2630 struct prefix *p, struct prefix_rd *prd,
adbac85e
DW
2631 u_char *tag, int addpath_encode,
2632 u_int32_t addpath_tx_id)
8c71e481 2633{
93b73dfa 2634 if (safi == SAFI_MPLS_VPN)
8c71e481 2635 {
adbac85e
DW
2636 if (addpath_encode)
2637 stream_putl(s, addpath_tx_id);
8c71e481
PM
2638 /* Tag, RD, Prefix write. */
2639 stream_putc (s, p->prefixlen + 88);
2640 stream_put (s, tag, 3);
2641 stream_put (s, prd->val, 8);
2642 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
8c71e481 2643 }
93b73dfa
LB
2644 else
2645 stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
2646}
2647
2648size_t
2649bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2650{
2651 int size = PSIZE (p->prefixlen);
2652 if (safi == SAFI_MPLS_VPN)
2653 size += 88;
2654 return size;
8c71e481
PM
2655}
2656
f4c89855 2657/*
65efcfce
LB
2658 * Encodes the tunnel encapsulation attribute,
2659 * and with ENABLE_BGP_VNC the VNC attribute which uses
2660 * almost the same TLV format
f4c89855
LB
2661 */
2662static void
2663bgp_packet_mpattr_tea(
2664 struct bgp *bgp,
2665 struct peer *peer,
2666 struct stream *s,
2667 struct attr *attr,
2668 uint8_t attrtype)
2669{
2670 unsigned int attrlenfield = 0;
587ff0fd 2671 unsigned int attrhdrlen = 0;
f4c89855
LB
2672 struct bgp_attr_encap_subtlv *subtlvs;
2673 struct bgp_attr_encap_subtlv *st;
2674 const char *attrname;
2675
2676 if (!attr || !attr->extra)
2677 return;
2678
2679 switch (attrtype) {
2680 case BGP_ATTR_ENCAP:
2681 attrname = "Tunnel Encap";
2682 subtlvs = attr->extra->encap_subtlvs;
2683
2684 /*
2685 * The tunnel encap attr has an "outer" tlv.
2686 * T = tunneltype,
2687 * L = total length of subtlvs,
2688 * V = concatenated subtlvs.
2689 */
2690 attrlenfield = 2 + 2; /* T + L */
587ff0fd 2691 attrhdrlen = 1 + 1; /* subTLV T + L */
f4c89855
LB
2692 break;
2693
65efcfce
LB
2694#if ENABLE_BGP_VNC
2695 case BGP_ATTR_VNC:
2696 attrname = "VNC";
2697 subtlvs = attr->extra->vnc_subtlvs;
2698 attrlenfield = 0; /* no outer T + L */
2699 attrhdrlen = 2 + 2; /* subTLV T + L */
2700 break;
2701#endif
2702
f4c89855
LB
2703 default:
2704 assert(0);
2705 }
2706
2707
587ff0fd
LB
2708 /* if no tlvs, don't make attr */
2709 if (subtlvs == NULL)
2710 return;
2711
f4c89855
LB
2712 /* compute attr length */
2713 for (st = subtlvs; st; st = st->next) {
587ff0fd 2714 attrlenfield += (attrhdrlen + st->length);
f4c89855
LB
2715 }
2716
f4c89855
LB
2717 if (attrlenfield > 0xffff) {
2718 zlog_info ("%s attribute is too long (length=%d), can't send it",
2719 attrname,
2720 attrlenfield);
2721 return;
2722 }
2723
2724 if (attrlenfield > 0xff) {
2725 /* 2-octet length field */
2726 stream_putc (s,
2727 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2728 stream_putc (s, attrtype);
2729 stream_putw (s, attrlenfield & 0xffff);
2730 } else {
2731 /* 1-octet length field */
2732 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2733 stream_putc (s, attrtype);
2734 stream_putc (s, attrlenfield & 0xff);
2735 }
2736
2737 if (attrtype == BGP_ATTR_ENCAP) {
2738 /* write outer T+L */
2739 stream_putw(s, attr->extra->encap_tunneltype);
2740 stream_putw(s, attrlenfield - 4);
2741 }
2742
2743 /* write each sub-tlv */
2744 for (st = subtlvs; st; st = st->next) {
587ff0fd
LB
2745 if (attrtype == BGP_ATTR_ENCAP) {
2746 stream_putc (s, st->type);
2747 stream_putc (s, st->length);
65efcfce
LB
2748#if ENABLE_BGP_VNC
2749 } else {
2750 stream_putw (s, st->type);
2751 stream_putw (s, st->length);
2752#endif
587ff0fd 2753 }
f4c89855
LB
2754 stream_put (s, st->value, st->length);
2755 }
2756}
f4c89855 2757
8c71e481
PM
2758void
2759bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2760{
2761 /* Set MP attribute length. Don't count the (2) bytes used to encode
2762 the attr length */
2763 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2764}
2765
718e3744 2766/* Make attribute packet. */
2767bgp_size_t
2768bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
8c71e481 2769 struct stream *s, struct attr *attr,
3f9c7369 2770 struct bpacket_attr_vec_arr *vecarr,
8c71e481 2771 struct prefix *p, afi_t afi, safi_t safi,
adbac85e
DW
2772 struct peer *from, struct prefix_rd *prd, u_char *tag,
2773 int addpath_encode,
2774 u_int32_t addpath_tx_id)
718e3744 2775{
fe69a505 2776 size_t cp;
0b2aa3a0 2777 size_t aspath_sizep;
718e3744 2778 struct aspath *aspath;
0b2aa3a0
PJ
2779 int send_as4_path = 0;
2780 int send_as4_aggregator = 0;
2781 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
718e3744 2782
2783 if (! bgp)
75aead62 2784 bgp = peer->bgp;
718e3744 2785
2786 /* Remember current pointer. */
9985f83c 2787 cp = stream_get_endp (s);
718e3744 2788
8a92a8a0
DS
2789 if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) &&
2790 !peer_cap_enhe(peer)))
8c71e481 2791 {
93b73dfa
LB
2792 size_t mpattrlen_pos = 0;
2793
8a92a8a0
DS
2794 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi,
2795 (peer_cap_enhe(peer) ? AFI_IP6 : afi),
2796 vecarr, attr);
adbac85e
DW
2797 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag,
2798 addpath_encode, addpath_tx_id);
8c71e481
PM
2799 bgp_packet_mpattr_end(s, mpattrlen_pos);
2800 }
2801
718e3744 2802 /* Origin attribute. */
2803 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2804 stream_putc (s, BGP_ATTR_ORIGIN);
2805 stream_putc (s, 1);
2806 stream_putc (s, attr->origin);
2807
2808 /* AS path attribute. */
2809
2810 /* If remote-peer is EBGP */
6d85b15b 2811 if (peer->sort == BGP_PEER_EBGP
718e3744 2812 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
fe69a505 2813 || attr->aspath->segments == NULL)
fee0f4c6 2814 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
718e3744 2815 {
2816 aspath = aspath_dup (attr->aspath);
2817
66b199b2
DS
2818 /* Even though we may not be configured for confederations we may have
2819 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
2820 aspath = aspath_delete_confed_seq (aspath);
2821
718e3744 2822 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2823 {
66b199b2 2824 /* Stuff our path CONFED_ID on the front */
718e3744 2825 aspath = aspath_add_seq (aspath, bgp->confed_id);
2826 }
2827 else
2828 {
9d3f9705
AC
2829 if (peer->change_local_as) {
2830 /* If replace-as is specified, we only use the change_local_as when
2831 advertising routes. */
2832 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2833 aspath = aspath_add_seq (aspath, peer->local_as);
2834 }
718e3744 2835 aspath = aspath_add_seq (aspath, peer->change_local_as);
9d3f9705
AC
2836 } else {
2837 aspath = aspath_add_seq (aspath, peer->local_as);
2838 }
718e3744 2839 }
2840 }
6d85b15b 2841 else if (peer->sort == BGP_PEER_CONFED)
718e3744 2842 {
2843 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2844 aspath = aspath_dup (attr->aspath);
2845 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2846 }
2847 else
2848 aspath = attr->aspath;
2849
0b2aa3a0
PJ
2850 /* If peer is not AS4 capable, then:
2851 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2852 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2853 * types are in it (i.e. exclude them if they are there)
2854 * AND do this only if there is at least one asnum > 65535 in the path!
2855 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2856 * all ASnums > 65535 to BGP_AS_TRANS
2857 */
2858
2859 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2860 stream_putc (s, BGP_ATTR_AS_PATH);
2861 aspath_sizep = stream_get_endp (s);
2862 stream_putw (s, 0);
2863 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2864
2865 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2866 * in the path
2867 */
2868 if (!use32bit && aspath_has_as4 (aspath))
2869 send_as4_path = 1; /* we'll do this later, at the correct place */
2870
718e3744 2871 /* Nexthop attribute. */
93b73dfa 2872 if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer))
718e3744 2873 {
8a92a8a0
DS
2874 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2875 {
2876 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2877 stream_putc (s, BGP_ATTR_NEXT_HOP);
2878 bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
2879 stream_putc (s, 4);
2880 stream_put_ipv4 (s, attr->nexthop.s_addr);
2881 }
2882 else if (safi == SAFI_UNICAST && peer_cap_enhe(from))
2883 {
2884 /*
2885 * Likely this is the case when an IPv4 prefix was received with
2886 * Extended Next-hop capability and now being advertised to
2887 * non-ENHE peers.
2888 * Setting the mandatory (ipv4) next-hop attribute here to enable
2889 * implicit next-hop self with correct (ipv4 address family).
2890 */
2891 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2892 stream_putc (s, BGP_ATTR_NEXT_HOP);
2893 bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, NULL);
2894 stream_putc (s, 4);
2895 stream_put_ipv4 (s, 0);
2896 }
718e3744 2897 }
2898
2899 /* MED attribute. */
abc920f8
DS
2900 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) ||
2901 bgp->maxmed_active)
718e3744 2902 {
2903 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2904 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2905 stream_putc (s, 4);
abc920f8 2906 stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med));
718e3744 2907 }
2908
2909 /* Local preference. */
6d85b15b
JBD
2910 if (peer->sort == BGP_PEER_IBGP ||
2911 peer->sort == BGP_PEER_CONFED)
718e3744 2912 {
2913 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2914 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2915 stream_putc (s, 4);
2916 stream_putl (s, attr->local_pref);
2917 }
2918
2919 /* Atomic aggregate. */
2920 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2921 {
2922 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2923 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2924 stream_putc (s, 0);
2925 }
2926
2927 /* Aggregator. */
2928 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2929 {
fb982c25 2930 assert (attr->extra);
0b2aa3a0
PJ
2931
2932 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
718e3744 2933 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2934 stream_putc (s, BGP_ATTR_AGGREGATOR);
0b2aa3a0
PJ
2935
2936 if (use32bit)
2937 {
2938 /* AS4 capable peer */
2939 stream_putc (s, 8);
2940 stream_putl (s, attr->extra->aggregator_as);
2941 }
2942 else
2943 {
2944 /* 2-byte AS peer */
2945 stream_putc (s, 6);
2946
2947 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2948 if ( attr->extra->aggregator_as > 65535 )
2949 {
2950 stream_putw (s, BGP_AS_TRANS);
2951
2952 /* we have to send AS4_AGGREGATOR, too.
2953 * we'll do that later in order to send attributes in ascending
2954 * order.
2955 */
2956 send_as4_aggregator = 1;
2957 }
2958 else
2959 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2960 }
fb982c25 2961 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
718e3744 2962 }
2963
2964 /* Community attribute. */
2965 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2966 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2967 {
2968 if (attr->community->size * 4 > 255)
2969 {
2970 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2971 stream_putc (s, BGP_ATTR_COMMUNITIES);
2972 stream_putw (s, attr->community->size * 4);
2973 }
2974 else
2975 {
2976 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2977 stream_putc (s, BGP_ATTR_COMMUNITIES);
2978 stream_putc (s, attr->community->size * 4);
2979 }
2980 stream_put (s, attr->community->val, attr->community->size * 4);
2981 }
2982
2983 /* Route Reflector. */
6d85b15b 2984 if (peer->sort == BGP_PEER_IBGP
718e3744 2985 && from
6d85b15b 2986 && from->sort == BGP_PEER_IBGP)
718e3744 2987 {
2988 /* Originator ID. */
2989 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2990 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2991 stream_putc (s, 4);
2992
2993 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
fb982c25 2994 stream_put_in_addr (s, &attr->extra->originator_id);
34c3f81b
PJ
2995 else
2996 stream_put_in_addr (s, &from->remote_id);
718e3744 2997
2998 /* Cluster list. */
2999 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3000 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
3001
9eda90ce 3002 if (attr->extra && attr->extra->cluster)
718e3744 3003 {
fb982c25 3004 stream_putc (s, attr->extra->cluster->length + 4);
718e3744 3005 /* If this peer configuration's parent BGP has cluster_id. */
3006 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
3007 stream_put_in_addr (s, &bgp->cluster_id);
3008 else
3009 stream_put_in_addr (s, &bgp->router_id);
fb982c25
PJ
3010 stream_put (s, attr->extra->cluster->list,
3011 attr->extra->cluster->length);
718e3744 3012 }
3013 else
3014 {
3015 stream_putc (s, 4);
3016 /* If this peer configuration's parent BGP has cluster_id. */
3017 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
3018 stream_put_in_addr (s, &bgp->cluster_id);
3019 else
3020 stream_put_in_addr (s, &bgp->router_id);
3021 }
3022 }
3023
718e3744 3024 /* Extended Communities attribute. */
3025 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
3026 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
3027 {
fb982c25
PJ
3028 struct attr_extra *attre = attr->extra;
3029
3030 assert (attre);
3031
6d85b15b
JBD
3032 if (peer->sort == BGP_PEER_IBGP
3033 || peer->sort == BGP_PEER_CONFED)
718e3744 3034 {
fb982c25 3035 if (attre->ecommunity->size * 8 > 255)
4372df71 3036 {
3037 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3038 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
fb982c25 3039 stream_putw (s, attre->ecommunity->size * 8);
4372df71 3040 }
3041 else
3042 {
3043 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3044 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
fb982c25 3045 stream_putc (s, attre->ecommunity->size * 8);
4372df71 3046 }
fb982c25 3047 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
718e3744 3048 }
3049 else
3050 {
5228ad27 3051 u_int8_t *pnt;
4372df71 3052 int tbit;
3053 int ecom_tr_size = 0;
3054 int i;
3055
fb982c25 3056 for (i = 0; i < attre->ecommunity->size; i++)
4372df71 3057 {
fb982c25 3058 pnt = attre->ecommunity->val + (i * 8);
4372df71 3059 tbit = *pnt;
3060
3061 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
3062 continue;
3063
3064 ecom_tr_size++;
3065 }
3066
3067 if (ecom_tr_size)
3068 {
3069 if (ecom_tr_size * 8 > 255)
3070 {
3071 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3072 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
3073 stream_putw (s, ecom_tr_size * 8);
3074 }
3075 else
3076 {
3077 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3078 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
3079 stream_putc (s, ecom_tr_size * 8);
3080 }
3081
fb982c25 3082 for (i = 0; i < attre->ecommunity->size; i++)
4372df71 3083 {
fb982c25 3084 pnt = attre->ecommunity->val + (i * 8);
4372df71 3085 tbit = *pnt;
3086
3087 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
3088 continue;
3089
3090 stream_put (s, pnt, 8);
3091 }
3092 }
718e3744 3093 }
718e3744 3094 }
0b2aa3a0
PJ
3095
3096 if ( send_as4_path )
3097 {
3098 /* If the peer is NOT As4 capable, AND */
3099 /* there are ASnums > 65535 in path THEN
3100 * give out AS4_PATH */
3101
3102 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3103 * path segments!
3104 * Hm, I wonder... confederation things *should* only be at
3105 * the beginning of an aspath, right? Then we should use
3106 * aspath_delete_confed_seq for this, because it is already
3107 * there! (JK)
3108 * Folks, talk to me: what is reasonable here!?
3109 */
3110 aspath = aspath_delete_confed_seq (aspath);
3111
3112 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
3113 stream_putc (s, BGP_ATTR_AS4_PATH);
3114 aspath_sizep = stream_get_endp (s);
3115 stream_putw (s, 0);
3116 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
3117 }
3118
3119 if (aspath != attr->aspath)
3120 aspath_free (aspath);
3121
3122 if ( send_as4_aggregator )
3123 {
3124 assert (attr->extra);
3125
3126 /* send AS4_AGGREGATOR, at this place */
3127 /* this section of code moved here in order to ensure the correct
3128 * *ascending* order of attributes
3129 */
3130 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3131 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
3132 stream_putc (s, 8);
3133 stream_putl (s, attr->extra->aggregator_as);
3134 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
3135 }
587ff0fd
LB
3136
3137 if ((afi == AFI_IP || afi == AFI_IP6) &&
3138 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
3139 {
3140 /* Tunnel Encap attribute */
3141 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
65efcfce
LB
3142
3143#if ENABLE_BGP_VNC
3144 /* VNC attribute */
3145 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC);
3146#endif
587ff0fd
LB
3147 }
3148
718e3744 3149 /* Unknown transit attribute. */
fb982c25
PJ
3150 if (attr->extra && attr->extra->transit)
3151 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
718e3744 3152
3153 /* Return total size of attribute. */
9985f83c 3154 return stream_get_endp (s) - cp;
718e3744 3155}
3156
8c71e481
PM
3157size_t
3158bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
718e3744 3159{
718e3744 3160 unsigned long attrlen_pnt;
718e3744 3161
8c71e481
PM
3162 /* Set extended bit always to encode the attribute length as 2 bytes */
3163 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
718e3744 3164 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
3165
9985f83c 3166 attrlen_pnt = stream_get_endp (s);
8c71e481 3167 stream_putw (s, 0); /* Length of this attribute. */
718e3744 3168
8c71e481 3169 stream_putw (s, afi);
93b73dfa 3170 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
8c71e481
PM
3171 return attrlen_pnt;
3172}
718e3744 3173
8c71e481
PM
3174void
3175bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
3176 afi_t afi, safi_t safi, struct prefix_rd *prd,
adbac85e
DW
3177 u_char *tag, int addpath_encode,
3178 u_int32_t addpath_tx_id)
8c71e481 3179{
718e3744 3180 if (safi == SAFI_MPLS_VPN)
3181 {
adbac85e
DW
3182 /* addpath TX ID */
3183 if (addpath_encode)
3184 stream_putl(s, addpath_tx_id);
3185
718e3744 3186 stream_putc (s, p->prefixlen + 88);
3187 stream_put (s, tag, 3);
3188 stream_put (s, prd->val, 8);
3189 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
3190 }
3191 else
adbac85e 3192 stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
8c71e481 3193}
718e3744 3194
8c71e481
PM
3195void
3196bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
3197{
93b73dfa 3198 bgp_packet_mpattr_end (s, attrlen_pnt);
718e3744 3199}
3200
3201/* Initialization of attribute. */
3202void
fe69a505 3203bgp_attr_init (void)
718e3744 3204{
718e3744 3205 aspath_init ();
3206 attrhash_init ();
3207 community_init ();
3208 ecommunity_init ();
3209 cluster_init ();
3210 transit_init ();
3211}
3212
228da428
CC
3213void
3214bgp_attr_finish (void)
3215{
3216 aspath_finish ();
3217 attrhash_finish ();
3218 community_finish ();
3219 ecommunity_finish ();
3220 cluster_finish ();
3221 transit_finish ();
3222}
3223
718e3744 3224/* Make attribute packet. */
3225void
a384592f 3226bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3227 struct prefix *prefix)
718e3744 3228{
3229 unsigned long cp;
3230 unsigned long len;
0b2aa3a0 3231 size_t aspath_lenp;
718e3744 3232 struct aspath *aspath;
adbac85e
DW
3233 int addpath_encode = 0;
3234 u_int32_t addpath_tx_id = 0;
718e3744 3235
3236 /* Remember current pointer. */
9985f83c 3237 cp = stream_get_endp (s);
718e3744 3238
3239 /* Place holder of length. */
3240 stream_putw (s, 0);
3241
3242 /* Origin attribute. */
3243 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3244 stream_putc (s, BGP_ATTR_ORIGIN);
3245 stream_putc (s, 1);
3246 stream_putc (s, attr->origin);
3247
3248 aspath = attr->aspath;
0b2aa3a0
PJ
3249
3250 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3251 stream_putc (s, BGP_ATTR_AS_PATH);
3252 aspath_lenp = stream_get_endp (s);
3253 stream_putw (s, 0);
3254
3255 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
718e3744 3256
3257 /* Nexthop attribute. */
a384592f 3258 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3259 if(prefix != NULL
3260#ifdef HAVE_IPV6
3261 && prefix->family != AF_INET6
3262#endif /* HAVE_IPV6 */
3263 )
3264 {
3265 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3266 stream_putc (s, BGP_ATTR_NEXT_HOP);
3267 stream_putc (s, 4);
3268 stream_put_ipv4 (s, attr->nexthop.s_addr);
3269 }
718e3744 3270
3271 /* MED attribute. */
3272 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3273 {
3274 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3275 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3276 stream_putc (s, 4);
3277 stream_putl (s, attr->med);
3278 }
3279
3280 /* Local preference. */
3281 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3282 {
3283 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3284 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3285 stream_putc (s, 4);
3286 stream_putl (s, attr->local_pref);
3287 }
3288
3289 /* Atomic aggregate. */
3290 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3291 {
3292 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3293 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3294 stream_putc (s, 0);
3295 }
3296
3297 /* Aggregator. */
3298 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3299 {
fb982c25 3300 assert (attr->extra);
718e3744 3301 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3302 stream_putc (s, BGP_ATTR_AGGREGATOR);
0b2aa3a0
PJ
3303 stream_putc (s, 8);
3304 stream_putl (s, attr->extra->aggregator_as);
fb982c25 3305 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
718e3744 3306 }
3307
3308 /* Community attribute. */
3309 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3310 {
3311 if (attr->community->size * 4 > 255)
3312 {
3313 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3314 stream_putc (s, BGP_ATTR_COMMUNITIES);
3315 stream_putw (s, attr->community->size * 4);
3316 }
3317 else
3318 {
3319 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3320 stream_putc (s, BGP_ATTR_COMMUNITIES);
3321 stream_putc (s, attr->community->size * 4);
3322 }
3323 stream_put (s, attr->community->val, attr->community->size * 4);
3324 }
3325
a384592f 3326#ifdef HAVE_IPV6
3327 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
fb982c25 3328 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
801a9bcc
DS
3329 (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL ||
3330 attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) )
a384592f 3331 {
3332 int sizep;
fb982c25
PJ
3333 struct attr_extra *attre = attr->extra;
3334
a384592f 3335 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3336 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
9985f83c 3337 sizep = stream_get_endp (s);
a384592f 3338
3339 /* MP header */
fb982c25 3340 stream_putc (s, 0); /* Marker: Attribute length. */
a384592f 3341 stream_putw(s, AFI_IP6); /* AFI */
3342 stream_putc(s, SAFI_UNICAST); /* SAFI */
3343
3344 /* Next hop */
fb982c25 3345 stream_putc(s, attre->mp_nexthop_len);
801a9bcc
DS
3346 stream_put(s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
3347 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3348 stream_put(s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
a384592f 3349
3350 /* SNPA */
3351 stream_putc(s, 0);
3352
3353 /* Prefix */
adbac85e 3354 stream_put_prefix_addpath (s, prefix, addpath_encode, addpath_tx_id);
a384592f 3355
3356 /* Set MP attribute length. */
9985f83c 3357 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
a384592f 3358 }
3359#endif /* HAVE_IPV6 */
3360
718e3744 3361 /* Return total size of attribute. */
9985f83c 3362 len = stream_get_endp (s) - cp - 2;
718e3744 3363 stream_putw_at (s, cp, len);
3364}