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