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