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