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