]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_attr.c
Merge pull request #12492 from kuldeepkash/update_assert_msg
[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"
e496b420 35#include "srv6.h"
a5c6a9b1 36#include "frrstr.h"
718e3744 37
38#include "bgpd/bgpd.h"
39#include "bgpd/bgp_attr.h"
40#include "bgpd/bgp_route.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_community.h"
43#include "bgpd/bgp_debug.h"
14454c9f 44#include "bgpd/bgp_errors.h"
9bedbb1e 45#include "bgpd/bgp_label.h"
718e3744 46#include "bgpd/bgp_packet.h"
47#include "bgpd/bgp_ecommunity.h"
57d187bc 48#include "bgpd/bgp_lcommunity.h"
3f9c7369 49#include "bgpd/bgp_updgrp.h"
6407da5a 50#include "bgpd/bgp_encap_types.h"
1e20238a 51#ifdef ENABLE_BGP_VNC
d62a17ae 52#include "bgpd/rfapi/bgp_rfapi_cfg.h"
53#include "bgp_encap_types.h"
54#include "bgp_vnc_types.h"
65efcfce 55#endif
b18825eb 56#include "bgp_evpn.h"
7c40bf39 57#include "bgp_flowspec_private.h"
eee353c5 58#include "bgp_mac.h"
6b0655a2 59
718e3744 60/* Attribute strings for logging. */
d62a17ae 61static const struct message attr_str[] = {
62 {BGP_ATTR_ORIGIN, "ORIGIN"},
63 {BGP_ATTR_AS_PATH, "AS_PATH"},
64 {BGP_ATTR_NEXT_HOP, "NEXT_HOP"},
65 {BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC"},
66 {BGP_ATTR_LOCAL_PREF, "LOCAL_PREF"},
67 {BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE"},
68 {BGP_ATTR_AGGREGATOR, "AGGREGATOR"},
69 {BGP_ATTR_COMMUNITIES, "COMMUNITY"},
70 {BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID"},
71 {BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST"},
d62a17ae 72 {BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI"},
73 {BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI"},
74 {BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES"},
75 {BGP_ATTR_AS4_PATH, "AS4_PATH"},
76 {BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR"},
a21bd7a3 77 {BGP_ATTR_PMSI_TUNNEL, "PMSI_TUNNEL_ATTRIBUTE"},
d62a17ae 78 {BGP_ATTR_ENCAP, "ENCAP"},
d864dd9e 79 {BGP_ATTR_OTC, "OTC"},
1e20238a 80#ifdef ENABLE_BGP_VNC_ATTR
d62a17ae 81 {BGP_ATTR_VNC, "VNC"},
65efcfce 82#endif
d62a17ae 83 {BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY"},
84 {BGP_ATTR_PREFIX_SID, "PREFIX_SID"},
9a659715 85 {BGP_ATTR_IPV6_EXT_COMMUNITIES, "IPV6_EXT_COMMUNITIES"},
97a52c82 86 {BGP_ATTR_AIGP, "AIGP"},
d62a17ae 87 {0}};
afcb7679 88
996c9314
LB
89static const struct message attr_flag_str[] = {
90 {BGP_ATTR_FLAG_OPTIONAL, "Optional"},
91 {BGP_ATTR_FLAG_TRANS, "Transitive"},
92 {BGP_ATTR_FLAG_PARTIAL, "Partial"},
93 /* bgp_attr_flags_diagnose() relies on this bit being last in
94 this list */
95 {BGP_ATTR_FLAG_EXTLEN, "Extended Length"},
96 {0}};
6b0655a2 97
9bddac4b 98static struct hash *cluster_hash;
718e3744 99
d62a17ae 100static void *cluster_hash_alloc(void *p)
718e3744 101{
d62a17ae 102 const struct cluster_list *val = (const struct cluster_list *)p;
103 struct cluster_list *cluster;
718e3744 104
d62a17ae 105 cluster = XMALLOC(MTYPE_CLUSTER, sizeof(struct cluster_list));
106 cluster->length = val->length;
718e3744 107
d62a17ae 108 if (cluster->length) {
109 cluster->list = XMALLOC(MTYPE_CLUSTER_VAL, val->length);
110 memcpy(cluster->list, val->list, val->length);
111 } else
112 cluster->list = NULL;
718e3744 113
d62a17ae 114 cluster->refcnt = 0;
718e3744 115
d62a17ae 116 return cluster;
718e3744 117}
118
119/* Cluster list related functions. */
d62a17ae 120static struct cluster_list *cluster_parse(struct in_addr *pnt, int length)
718e3744 121{
628565c7 122 struct cluster_list tmp = {};
d62a17ae 123 struct cluster_list *cluster;
718e3744 124
d62a17ae 125 tmp.length = length;
628565c7 126 tmp.list = length == 0 ? NULL : pnt;
718e3744 127
d62a17ae 128 cluster = hash_get(cluster_hash, &tmp, cluster_hash_alloc);
129 cluster->refcnt++;
130 return cluster;
718e3744 131}
132
3dc339cd 133bool cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
718e3744 134{
d62a17ae 135 int i;
136
137 for (i = 0; i < cluster->length / 4; i++)
138 if (cluster->list[i].s_addr == originator.s_addr)
3dc339cd
DA
139 return true;
140 return false;
718e3744 141}
142
d8b87afe 143static unsigned int cluster_hash_key_make(const void *p)
718e3744 144{
d62a17ae 145 const struct cluster_list *cluster = p;
718e3744 146
d62a17ae 147 return jhash(cluster->list, cluster->length, 0);
718e3744 148}
149
74df8d6d 150static bool cluster_hash_cmp(const void *p1, const void *p2)
718e3744 151{
d62a17ae 152 const struct cluster_list *cluster1 = p1;
153 const struct cluster_list *cluster2 = p2;
923de654 154
f22ed884
QY
155 if (cluster1->list == cluster2->list)
156 return true;
157
158 if (!cluster1->list || !cluster2->list)
159 return false;
160
161 if (cluster1->length != cluster2->length)
162 return false;
163
164 return (memcmp(cluster1->list, cluster2->list, cluster1->length) == 0);
718e3744 165}
166
d62a17ae 167static void cluster_free(struct cluster_list *cluster)
718e3744 168{
0a22ddfb 169 XFREE(MTYPE_CLUSTER_VAL, cluster->list);
d62a17ae 170 XFREE(MTYPE_CLUSTER, cluster);
718e3744 171}
172
d62a17ae 173static struct cluster_list *cluster_intern(struct cluster_list *cluster)
718e3744 174{
d62a17ae 175 struct cluster_list *find;
718e3744 176
d62a17ae 177 find = hash_get(cluster_hash, cluster, cluster_hash_alloc);
178 find->refcnt++;
718e3744 179
d62a17ae 180 return find;
718e3744 181}
182
628565c7 183static void cluster_unintern(struct cluster_list **cluster)
718e3744 184{
628565c7
QY
185 if ((*cluster)->refcnt)
186 (*cluster)->refcnt--;
187
188 if ((*cluster)->refcnt == 0) {
189 void *p = hash_release(cluster_hash, *cluster);
190 assert(p == *cluster);
191 cluster_free(*cluster);
192 *cluster = NULL;
d62a17ae 193 }
718e3744 194}
195
d62a17ae 196static void cluster_init(void)
718e3744 197{
996c9314 198 cluster_hash = hash_create(cluster_hash_key_make, cluster_hash_cmp,
3f65c5b1 199 "BGP Cluster");
718e3744 200}
228da428 201
d62a17ae 202static void cluster_finish(void)
228da428 203{
d62a17ae 204 hash_clean(cluster_hash, (void (*)(void *))cluster_free);
205 hash_free(cluster_hash);
206 cluster_hash = NULL;
228da428 207}
6b0655a2 208
bede7744 209static struct hash *encap_hash = NULL;
1e20238a 210#ifdef ENABLE_BGP_VNC
bede7744
LB
211static struct hash *vnc_hash = NULL;
212#endif
e496b420
HS
213static struct hash *srv6_l3vpn_hash;
214static struct hash *srv6_vpn_hash;
bede7744 215
d62a17ae 216struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
f4c89855 217{
d62a17ae 218 struct bgp_attr_encap_subtlv *new;
219 struct bgp_attr_encap_subtlv *tail;
220 struct bgp_attr_encap_subtlv *p;
f4c89855 221
d62a17ae 222 for (p = orig, tail = new = NULL; p; p = p->next) {
12f70478 223 int size = sizeof(struct bgp_attr_encap_subtlv) + p->length;
d62a17ae 224 if (tail) {
225 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
226 tail = tail->next;
227 } else {
228 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
229 }
230 assert(tail);
231 memcpy(tail, p, size);
232 tail->next = NULL;
f4c89855 233 }
f4c89855 234
d62a17ae 235 return new;
f4c89855
LB
236}
237
d62a17ae 238static void encap_free(struct bgp_attr_encap_subtlv *p)
f4c89855 239{
d62a17ae 240 struct bgp_attr_encap_subtlv *next;
241 while (p) {
242 next = p->next;
243 p->next = NULL;
244 XFREE(MTYPE_ENCAP_TLV, p);
245 p = next;
246 }
f4c89855
LB
247}
248
d62a17ae 249void bgp_attr_flush_encap(struct attr *attr)
f4c89855 250{
d62a17ae 251 if (!attr)
252 return;
f4c89855 253
d62a17ae 254 if (attr->encap_subtlvs) {
255 encap_free(attr->encap_subtlvs);
256 attr->encap_subtlvs = NULL;
257 }
1e20238a 258#ifdef ENABLE_BGP_VNC
91ebf12c
DS
259 struct bgp_attr_encap_subtlv *vnc_subtlvs =
260 bgp_attr_get_vnc_subtlvs(attr);
261
262 if (vnc_subtlvs) {
263 encap_free(vnc_subtlvs);
264 bgp_attr_set_vnc_subtlvs(attr, NULL);
d62a17ae 265 }
65efcfce 266#endif
f4c89855
LB
267}
268
269/*
270 * Compare encap sub-tlv chains
271 *
272 * 1 = equivalent
273 * 0 = not equivalent
274 *
275 * This algorithm could be made faster if needed
276 */
3dc339cd
DA
277static bool encap_same(const struct bgp_attr_encap_subtlv *h1,
278 const struct bgp_attr_encap_subtlv *h2)
f4c89855 279{
36de6e0e
A
280 const struct bgp_attr_encap_subtlv *p;
281 const struct bgp_attr_encap_subtlv *q;
f4c89855 282
d62a17ae 283 if (h1 == h2)
3dc339cd 284 return true;
d62a17ae 285 if (h1 == NULL || h2 == NULL)
3dc339cd 286 return false;
f4c89855 287
d62a17ae 288 for (p = h1; p; p = p->next) {
289 for (q = h2; q; q = q->next) {
290 if ((p->type == q->type) && (p->length == q->length)
291 && !memcmp(p->value, q->value, p->length)) {
f4c89855 292
d62a17ae 293 break;
294 }
295 }
296 if (!q)
3dc339cd 297 return false;
f4c89855 298 }
f4c89855 299
d62a17ae 300 for (p = h2; p; p = p->next) {
301 for (q = h1; q; q = q->next) {
302 if ((p->type == q->type) && (p->length == q->length)
303 && !memcmp(p->value, q->value, p->length)) {
f4c89855 304
d62a17ae 305 break;
306 }
307 }
308 if (!q)
3dc339cd 309 return false;
f4c89855 310 }
f4c89855 311
3dc339cd 312 return true;
f4c89855
LB
313}
314
d62a17ae 315static void *encap_hash_alloc(void *p)
bede7744 316{
d62a17ae 317 /* Encap structure is already allocated. */
318 return p;
bede7744
LB
319}
320
d62a17ae 321typedef enum {
322 ENCAP_SUBTLV_TYPE,
1e20238a 323#ifdef ENABLE_BGP_VNC
d62a17ae 324 VNC_SUBTLV_TYPE
bede7744
LB
325#endif
326} encap_subtlv_type;
327
328static struct bgp_attr_encap_subtlv *
d62a17ae 329encap_intern(struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type)
bede7744 330{
d62a17ae 331 struct bgp_attr_encap_subtlv *find;
332 struct hash *hash = encap_hash;
1e20238a 333#ifdef ENABLE_BGP_VNC
d62a17ae 334 if (type == VNC_SUBTLV_TYPE)
335 hash = vnc_hash;
bede7744
LB
336#endif
337
d62a17ae 338 find = hash_get(hash, encap, encap_hash_alloc);
339 if (find != encap)
340 encap_free(encap);
341 find->refcnt++;
bede7744 342
d62a17ae 343 return find;
bede7744
LB
344}
345
d62a17ae 346static void encap_unintern(struct bgp_attr_encap_subtlv **encapp,
347 encap_subtlv_type type)
bede7744 348{
d62a17ae 349 struct bgp_attr_encap_subtlv *encap = *encapp;
350 if (encap->refcnt)
351 encap->refcnt--;
bede7744 352
d62a17ae 353 if (encap->refcnt == 0) {
354 struct hash *hash = encap_hash;
1e20238a 355#ifdef ENABLE_BGP_VNC
d62a17ae 356 if (type == VNC_SUBTLV_TYPE)
357 hash = vnc_hash;
bede7744 358#endif
d62a17ae 359 hash_release(hash, encap);
360 encap_free(encap);
361 *encapp = NULL;
362 }
bede7744
LB
363}
364
d8b87afe 365static unsigned int encap_hash_key_make(const void *p)
bede7744 366{
d62a17ae 367 const struct bgp_attr_encap_subtlv *encap = p;
bede7744 368
d62a17ae 369 return jhash(encap->value, encap->length, 0);
bede7744
LB
370}
371
74df8d6d 372static bool encap_hash_cmp(const void *p1, const void *p2)
bede7744 373{
36de6e0e
A
374 return encap_same((const struct bgp_attr_encap_subtlv *)p1,
375 (const struct bgp_attr_encap_subtlv *)p2);
bede7744
LB
376}
377
d62a17ae 378static void encap_init(void)
bede7744 379{
996c9314 380 encap_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
3f65c5b1 381 "BGP Encap Hash");
1e20238a 382#ifdef ENABLE_BGP_VNC
996c9314 383 vnc_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
3f65c5b1 384 "BGP VNC Hash");
bede7744
LB
385#endif
386}
387
d62a17ae 388static void encap_finish(void)
bede7744 389{
d62a17ae 390 hash_clean(encap_hash, (void (*)(void *))encap_free);
391 hash_free(encap_hash);
392 encap_hash = NULL;
1e20238a 393#ifdef ENABLE_BGP_VNC
d62a17ae 394 hash_clean(vnc_hash, (void (*)(void *))encap_free);
395 hash_free(vnc_hash);
396 vnc_hash = NULL;
bede7744
LB
397#endif
398}
399
d62a17ae 400static bool overlay_index_same(const struct attr *a1, const struct attr *a2)
684a7227 401{
d62a17ae 402 if (!a1 && a2)
403 return false;
404 if (!a2 && a1)
405 return false;
406 if (!a1 && !a2)
407 return true;
6c924775 408
761cc919
IS
409 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1),
410 bgp_attr_get_evpn_overlay(a2));
684a7227
PG
411}
412
718e3744 413/* Unknown transit attribute. */
9bddac4b 414static struct hash *transit_hash;
718e3744 415
d62a17ae 416static void transit_free(struct transit *transit)
718e3744 417{
0a22ddfb 418 XFREE(MTYPE_TRANSIT_VAL, transit->val);
d62a17ae 419 XFREE(MTYPE_TRANSIT, transit);
718e3744 420}
421
d62a17ae 422static void *transit_hash_alloc(void *p)
718e3744 423{
d62a17ae 424 /* Transit structure is already allocated. */
425 return p;
718e3744 426}
427
d62a17ae 428static struct transit *transit_intern(struct transit *transit)
718e3744 429{
d62a17ae 430 struct transit *find;
718e3744 431
d62a17ae 432 find = hash_get(transit_hash, transit, transit_hash_alloc);
433 if (find != transit)
434 transit_free(transit);
435 find->refcnt++;
718e3744 436
d62a17ae 437 return find;
718e3744 438}
439
547357c4 440static void transit_unintern(struct transit **transit)
718e3744 441{
547357c4
QY
442 if ((*transit)->refcnt)
443 (*transit)->refcnt--;
718e3744 444
547357c4
QY
445 if ((*transit)->refcnt == 0) {
446 hash_release(transit_hash, *transit);
447 transit_free(*transit);
448 *transit = NULL;
d62a17ae 449 }
718e3744 450}
451
97a52c82
DA
452static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt, int length,
453 uint64_t *aigp)
454{
455 uint8_t *data = pnt;
456 uint8_t tlv_type;
457 uint16_t tlv_length;
458
459 while (length) {
460 tlv_type = *data;
461 ptr_get_be16(data + 1, &tlv_length);
462 (void)data;
463
464 /* The value field of the AIGP TLV is always 8 octets
465 * long and its value is interpreted as an unsigned 64-bit
466 * integer.
467 */
468 if (tlv_type == BGP_AIGP_TLV_METRIC) {
469 (void)ptr_get_be64(data + 3, aigp);
470
471 /* If an AIGP attribute is received and its first AIGP
472 * TLV contains the maximum value 0xffffffffffffffff,
473 * the attribute SHOULD be considered to be malformed
474 * and SHOULD be discarded as specified in this section.
475 */
476 if (*aigp == BGP_AIGP_TLV_METRIC_MAX) {
477 zlog_err("Bad AIGP TLV (%s) length: %llu",
478 BGP_AIGP_TLV_METRIC_DESC,
479 BGP_AIGP_TLV_METRIC_MAX);
480 return false;
481 }
482
483 return true;
484 }
485
486 data += tlv_length;
487 length -= tlv_length;
488 }
489
490 return false;
491}
492
493static uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
494{
495 uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr);
496
497 if (bpi->nexthop)
498 return aigp + bpi->nexthop->metric;
499 else
500 return aigp;
501}
502
503static void stream_put_bgp_aigp_tlv_metric(struct stream *s,
504 struct bgp_path_info *bpi)
505{
506 stream_putc(s, BGP_AIGP_TLV_METRIC);
507 stream_putw(s, BGP_AIGP_TLV_METRIC_LEN);
508 stream_putq(s, bgp_aigp_metric_total(bpi));
509}
510
511static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
512{
513 uint8_t *data = pnt;
514 uint8_t tlv_type;
515 uint16_t tlv_length;
516
517 if (length < 3) {
518 zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
519 length);
520 return false;
521 }
522
523 while (length) {
524 tlv_type = *data;
525 ptr_get_be16(data + 1, &tlv_length);
526 (void)data;
527
528 if (length < tlv_length) {
529 zlog_err(
530 "Bad AIGP attribute length: %u, but TLV length: %u",
531 length, tlv_length);
532 return false;
533 }
534
535 if (tlv_length < 3) {
536 zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
537 tlv_length);
538 return false;
539 }
540
541 /* AIGP TLV, Length: 11 */
542 if (tlv_type == BGP_AIGP_TLV_METRIC &&
543 tlv_length != BGP_AIGP_TLV_METRIC_LEN) {
544 zlog_err("Bad AIGP TLV (%s) length: %u",
545 BGP_AIGP_TLV_METRIC_DESC, tlv_length);
546 return false;
547 }
548
549 data += tlv_length;
550 length -= tlv_length;
551 }
552
553 return true;
554}
555
e496b420
HS
556static void *srv6_l3vpn_hash_alloc(void *p)
557{
558 return p;
559}
560
561static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn *l3vpn)
562{
563 XFREE(MTYPE_BGP_SRV6_L3VPN, l3vpn);
564}
565
566static struct bgp_attr_srv6_l3vpn *
567srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn *l3vpn)
568{
569 struct bgp_attr_srv6_l3vpn *find;
570
571 find = hash_get(srv6_l3vpn_hash, l3vpn, srv6_l3vpn_hash_alloc);
572 if (find != l3vpn)
573 srv6_l3vpn_free(l3vpn);
574 find->refcnt++;
575 return find;
576}
577
578static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn **l3vpnp)
579{
580 struct bgp_attr_srv6_l3vpn *l3vpn = *l3vpnp;
581
582 if (l3vpn->refcnt)
583 l3vpn->refcnt--;
584
585 if (l3vpn->refcnt == 0) {
586 hash_release(srv6_l3vpn_hash, l3vpn);
587 srv6_l3vpn_free(l3vpn);
588 *l3vpnp = NULL;
589 }
590}
591
592static void *srv6_vpn_hash_alloc(void *p)
593{
594 return p;
595}
596
597static void srv6_vpn_free(struct bgp_attr_srv6_vpn *vpn)
598{
599 XFREE(MTYPE_BGP_SRV6_VPN, vpn);
600}
601
602static struct bgp_attr_srv6_vpn *srv6_vpn_intern(struct bgp_attr_srv6_vpn *vpn)
603{
604 struct bgp_attr_srv6_vpn *find;
605
606 find = hash_get(srv6_vpn_hash, vpn, srv6_vpn_hash_alloc);
607 if (find != vpn)
608 srv6_vpn_free(vpn);
609 find->refcnt++;
610 return find;
611}
612
613static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn **vpnp)
614{
615 struct bgp_attr_srv6_vpn *vpn = *vpnp;
616
617 if (vpn->refcnt)
618 vpn->refcnt--;
619
620 if (vpn->refcnt == 0) {
621 hash_release(srv6_vpn_hash, vpn);
622 srv6_vpn_free(vpn);
623 *vpnp = NULL;
624 }
625}
626
627static uint32_t srv6_l3vpn_hash_key_make(const void *p)
628{
629 const struct bgp_attr_srv6_l3vpn *l3vpn = p;
630 uint32_t key = 0;
631
632 key = jhash(&l3vpn->sid, 16, key);
633 key = jhash_1word(l3vpn->sid_flags, key);
634 key = jhash_1word(l3vpn->endpoint_behavior, key);
9299fd00
RS
635 key = jhash_1word(l3vpn->loc_block_len, key);
636 key = jhash_1word(l3vpn->loc_node_len, key);
637 key = jhash_1word(l3vpn->func_len, key);
638 key = jhash_1word(l3vpn->arg_len, key);
639 key = jhash_1word(l3vpn->transposition_len, key);
640 key = jhash_1word(l3vpn->transposition_offset, key);
e496b420
HS
641 return key;
642}
643
644static bool srv6_l3vpn_hash_cmp(const void *p1, const void *p2)
645{
646 const struct bgp_attr_srv6_l3vpn *l3vpn1 = p1;
647 const struct bgp_attr_srv6_l3vpn *l3vpn2 = p2;
648
649 return sid_same(&l3vpn1->sid, &l3vpn2->sid)
650 && l3vpn1->sid_flags == l3vpn2->sid_flags
9299fd00
RS
651 && l3vpn1->endpoint_behavior == l3vpn2->endpoint_behavior
652 && l3vpn1->loc_block_len == l3vpn2->loc_block_len
653 && l3vpn1->loc_node_len == l3vpn2->loc_node_len
654 && l3vpn1->func_len == l3vpn2->func_len
655 && l3vpn1->arg_len == l3vpn2->arg_len
656 && l3vpn1->transposition_len == l3vpn2->transposition_len
657 && l3vpn1->transposition_offset == l3vpn2->transposition_offset;
e496b420
HS
658}
659
660static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn *h1,
661 const struct bgp_attr_srv6_l3vpn *h2)
662{
663 if (h1 == h2)
664 return true;
665 else if (h1 == NULL || h2 == NULL)
666 return false;
667 else
668 return srv6_l3vpn_hash_cmp((const void *)h1, (const void *)h2);
669}
670
671static unsigned int srv6_vpn_hash_key_make(const void *p)
672{
673 const struct bgp_attr_srv6_vpn *vpn = p;
674 uint32_t key = 0;
675
676 key = jhash(&vpn->sid, 16, key);
677 key = jhash_1word(vpn->sid_flags, key);
678 return key;
679}
680
681static bool srv6_vpn_hash_cmp(const void *p1, const void *p2)
682{
683 const struct bgp_attr_srv6_vpn *vpn1 = p1;
684 const struct bgp_attr_srv6_vpn *vpn2 = p2;
685
686 return sid_same(&vpn1->sid, &vpn2->sid)
687 && vpn1->sid_flags == vpn2->sid_flags;
688}
689
690static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn *h1,
691 const struct bgp_attr_srv6_vpn *h2)
692{
693 if (h1 == h2)
694 return true;
695 else if (h1 == NULL || h2 == NULL)
696 return false;
697 else
698 return srv6_vpn_hash_cmp((const void *)h1, (const void *)h2);
699}
700
701static void srv6_init(void)
702{
703 srv6_l3vpn_hash =
704 hash_create(srv6_l3vpn_hash_key_make, srv6_l3vpn_hash_cmp,
705 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
706 srv6_vpn_hash = hash_create(srv6_vpn_hash_key_make, srv6_vpn_hash_cmp,
707 "BGP Prefix-SID SRv6-VPN-Service-TLV");
708}
709
710static void srv6_finish(void)
711{
712 hash_clean(srv6_l3vpn_hash, (void (*)(void *))srv6_l3vpn_free);
713 hash_free(srv6_l3vpn_hash);
714 srv6_l3vpn_hash = NULL;
715 hash_clean(srv6_vpn_hash, (void (*)(void *))srv6_vpn_free);
716 hash_free(srv6_vpn_hash);
717 srv6_vpn_hash = NULL;
718}
719
d8b87afe 720static unsigned int transit_hash_key_make(const void *p)
718e3744 721{
d62a17ae 722 const struct transit *transit = p;
718e3744 723
d62a17ae 724 return jhash(transit->val, transit->length, 0);
718e3744 725}
726
74df8d6d 727static bool transit_hash_cmp(const void *p1, const void *p2)
718e3744 728{
d62a17ae 729 const struct transit *transit1 = p1;
730 const struct transit *transit2 = p2;
923de654 731
d62a17ae 732 return (transit1->length == transit2->length
733 && memcmp(transit1->val, transit2->val, transit1->length) == 0);
718e3744 734}
735
d62a17ae 736static void transit_init(void)
718e3744 737{
996c9314 738 transit_hash = hash_create(transit_hash_key_make, transit_hash_cmp,
3f65c5b1 739 "BGP Transit Hash");
718e3744 740}
228da428 741
d62a17ae 742static void transit_finish(void)
228da428 743{
d62a17ae 744 hash_clean(transit_hash, (void (*)(void *))transit_free);
745 hash_free(transit_hash);
746 transit_hash = NULL;
228da428 747}
6b0655a2 748
718e3744 749/* Attribute hash routines. */
9bddac4b 750static struct hash *attrhash;
718e3744 751
d62a17ae 752unsigned long int attr_count(void)
cbdfbaa5 753{
d62a17ae 754 return attrhash->count;
cbdfbaa5
PJ
755}
756
d62a17ae 757unsigned long int attr_unknown_count(void)
cbdfbaa5 758{
d62a17ae 759 return transit_hash->count;
cbdfbaa5
PJ
760}
761
d8b87afe 762unsigned int attrhash_key_make(const void *p)
718e3744 763{
d62a17ae 764 const struct attr *attr = (struct attr *)p;
765 uint32_t key = 0;
c8e7b895 766#define MIX(val) key = jhash_1word(val, key)
0d0268a6 767#define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
c8e7b895 768
0d0268a6 769 MIX3(attr->origin, attr->nexthop.s_addr, attr->med);
996c9314
LB
770 MIX3(attr->local_pref, attr->aggregator_as,
771 attr->aggregator_addr.s_addr);
0d0268a6
LB
772 MIX3(attr->weight, attr->mp_nexthop_global_in.s_addr,
773 attr->originator_id.s_addr);
774 MIX3(attr->tag, attr->label, attr->label_index);
d62a17ae 775
776 if (attr->aspath)
777 MIX(aspath_key_make(attr->aspath));
9a706b42
DA
778 if (bgp_attr_get_community(attr))
779 MIX(community_hash_make(bgp_attr_get_community(attr)));
1bcf3a96
DA
780 if (bgp_attr_get_lcommunity(attr))
781 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr)));
b53e67a3
DA
782 if (bgp_attr_get_ecommunity(attr))
783 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr)));
d04ac434
DS
784 if (bgp_attr_get_ipv6_ecommunity(attr))
785 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr)));
779fee93
DS
786 if (bgp_attr_get_cluster(attr))
787 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr)));
04fb21e2
DS
788 if (bgp_attr_get_transit(attr))
789 MIX(transit_hash_key_make(bgp_attr_get_transit(attr)));
d62a17ae 790 if (attr->encap_subtlvs)
791 MIX(encap_hash_key_make(attr->encap_subtlvs));
b83127e1
HS
792 if (attr->srv6_l3vpn)
793 MIX(srv6_l3vpn_hash_key_make(attr->srv6_l3vpn));
794 if (attr->srv6_vpn)
795 MIX(srv6_vpn_hash_key_make(attr->srv6_vpn));
1e20238a 796#ifdef ENABLE_BGP_VNC
91ebf12c
DS
797 struct bgp_attr_encap_subtlv *vnc_subtlvs =
798 bgp_attr_get_vnc_subtlvs(attr);
799 if (vnc_subtlvs)
800 MIX(encap_hash_key_make(vnc_subtlvs));
bede7744 801#endif
d62a17ae 802 MIX(attr->mp_nexthop_len);
803 key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key);
804 key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key);
7b7d48e5 805 MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance);
951745bd 806 MIX(attr->rmap_table_id);
0789eb69
KM
807 MIX(attr->nh_type);
808 MIX(attr->bh_type);
d864dd9e 809 MIX(attr->otc);
97a52c82 810 MIX(bgp_attr_get_aigp_metric(attr));
d62a17ae 811
812 return key;
813}
814
74df8d6d 815bool attrhash_cmp(const void *p1, const void *p2)
d62a17ae 816{
817 const struct attr *attr1 = p1;
818 const struct attr *attr2 = p2;
819
820 if (attr1->flag == attr2->flag && attr1->origin == attr2->origin
821 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
822 && attr1->aspath == attr2->aspath
9a706b42
DA
823 && bgp_attr_get_community(attr1)
824 == bgp_attr_get_community(attr2)
825 && attr1->med == attr2->med
d62a17ae 826 && attr1->local_pref == attr2->local_pref
827 && attr1->rmap_change_flags == attr2->rmap_change_flags) {
2bb8b49c
DS
828 if (attr1->aggregator_as == attr2->aggregator_as
829 && attr1->aggregator_addr.s_addr
830 == attr2->aggregator_addr.s_addr
831 && attr1->weight == attr2->weight
832 && attr1->tag == attr2->tag
833 && attr1->label_index == attr2->label_index
834 && attr1->mp_nexthop_len == attr2->mp_nexthop_len
835 && bgp_attr_get_ecommunity(attr1)
836 == bgp_attr_get_ecommunity(attr2)
837 && bgp_attr_get_ipv6_ecommunity(attr1)
838 == bgp_attr_get_ipv6_ecommunity(attr2)
839 && bgp_attr_get_lcommunity(attr1)
840 == bgp_attr_get_lcommunity(attr2)
841 && bgp_attr_get_cluster(attr1)
842 == bgp_attr_get_cluster(attr2)
843 && bgp_attr_get_transit(attr1)
844 == bgp_attr_get_transit(attr2)
845 && bgp_attr_get_aigp_metric(attr1)
846 == bgp_attr_get_aigp_metric(attr2)
847 && attr1->rmap_table_id == attr2->rmap_table_id
848 && (attr1->encap_tunneltype == attr2->encap_tunneltype)
849 && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
1e20238a 850#ifdef ENABLE_BGP_VNC
91ebf12c
DS
851 && encap_same(bgp_attr_get_vnc_subtlvs(attr1),
852 bgp_attr_get_vnc_subtlvs(attr2))
65efcfce 853#endif
0d0268a6 854 && IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
2bb8b49c
DS
855 &attr2->mp_nexthop_global)
856 && IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
857 &attr2->mp_nexthop_local)
858 && IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
859 &attr2->mp_nexthop_global_in)
860 && IPV4_ADDR_SAME(&attr1->originator_id,
861 &attr2->originator_id)
862 && overlay_index_same(attr1, attr2)
863 && !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t))
864 && attr1->es_flags == attr2->es_flags
865 && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum
866 && attr1->df_pref == attr2->df_pref
867 && attr1->df_alg == attr2->df_alg
868 && attr1->nh_ifindex == attr2->nh_ifindex
869 && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex
870 && attr1->distance == attr2->distance
871 && srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn)
872 && srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn)
873 && attr1->srte_color == attr2->srte_color
874 && attr1->nh_type == attr2->nh_type
875 && attr1->bh_type == attr2->bh_type
876 && attr1->otc == attr2->otc)
74df8d6d 877 return true;
d62a17ae 878 }
aadc0905 879
74df8d6d 880 return false;
718e3744 881}
882
d62a17ae 883static void attrhash_init(void)
718e3744 884{
996c9314
LB
885 attrhash =
886 hash_create(attrhash_key_make, attrhash_cmp, "BGP Attributes");
718e3744 887}
888
289d2501
LB
889/*
890 * special for hash_clean below
891 */
d62a17ae 892static void attr_vfree(void *attr)
289d2501 893{
d62a17ae 894 XFREE(MTYPE_ATTR, attr);
289d2501
LB
895}
896
d62a17ae 897static void attrhash_finish(void)
228da428 898{
d62a17ae 899 hash_clean(attrhash, attr_vfree);
900 hash_free(attrhash);
901 attrhash = NULL;
228da428
CC
902}
903
e3b78da8 904static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty)
718e3744 905{
e3b78da8 906 struct attr *attr = bucket->data;
42d1ca39
DA
907 struct in6_addr *sid = NULL;
908
909 if (attr->srv6_l3vpn)
910 sid = &attr->srv6_l3vpn->sid;
911 else if (attr->srv6_vpn)
912 sid = &attr->srv6_vpn->sid;
718e3744 913
23d0a753 914 vty_out(vty, "attr[%ld] nexthop %pI4\n", attr->refcnt, &attr->nexthop);
e496b420 915
e496b420 916 vty_out(vty,
07380148
DA
917 "\tflags: %" PRIu64
918 " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
957f74c3 919 attr->flag, attr->distance, attr->med, attr->local_pref,
42d1ca39 920 attr->origin, attr->weight, attr->label, sid);
718e3744 921}
922
d62a17ae 923void attr_show_all(struct vty *vty)
718e3744 924{
e3b78da8 925 hash_iterate(attrhash, (void (*)(struct hash_bucket *,
9d303b37
DL
926 void *))attr_show_all_iterator,
927 vty);
718e3744 928}
929
d62a17ae 930static void *bgp_attr_hash_alloc(void *p)
718e3744 931{
d62a17ae 932 struct attr *val = (struct attr *)p;
933 struct attr *attr;
718e3744 934
d62a17ae 935 attr = XMALLOC(MTYPE_ATTR, sizeof(struct attr));
936 *attr = *val;
937 if (val->encap_subtlvs) {
938 val->encap_subtlvs = NULL;
939 }
1e20238a 940#ifdef ENABLE_BGP_VNC
91ebf12c
DS
941 struct bgp_attr_encap_subtlv *vnc_subtlvs =
942 bgp_attr_get_vnc_subtlvs(val);
943
944 if (vnc_subtlvs)
945 bgp_attr_set_vnc_subtlvs(val, NULL);
65efcfce 946#endif
e496b420 947
d62a17ae 948 attr->refcnt = 0;
949 return attr;
718e3744 950}
951
952/* Internet argument attribute. */
d62a17ae 953struct attr *bgp_attr_intern(struct attr *attr)
954{
955 struct attr *find;
b53e67a3
DA
956 struct ecommunity *ecomm = NULL;
957 struct ecommunity *ipv6_ecomm = NULL;
1bcf3a96 958 struct lcommunity *lcomm = NULL;
9a706b42 959 struct community *comm = NULL;
d62a17ae 960
544be979 961 /* Intern referenced structure. */
d62a17ae 962 if (attr->aspath) {
963 if (!attr->aspath->refcnt)
964 attr->aspath = aspath_intern(attr->aspath);
965 else
966 attr->aspath->refcnt++;
967 }
9a706b42
DA
968
969 comm = bgp_attr_get_community(attr);
970 if (comm) {
971 if (!comm->refcnt)
972 bgp_attr_set_community(attr, community_intern(comm));
d62a17ae 973 else
9a706b42 974 comm->refcnt++;
d62a17ae 975 }
976
b53e67a3 977 ecomm = bgp_attr_get_ecommunity(attr);
d04ac434
DS
978 if (ecomm) {
979 if (!ecomm->refcnt)
b53e67a3 980 bgp_attr_set_ecommunity(attr, ecommunity_intern(ecomm));
9a659715 981 else
d04ac434 982 ecomm->refcnt++;
9a659715
PG
983 }
984
b53e67a3
DA
985 ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
986 if (ipv6_ecomm) {
987 if (!ipv6_ecomm->refcnt)
988 bgp_attr_set_ipv6_ecommunity(
989 attr, ecommunity_intern(ipv6_ecomm));
990 else
991 ipv6_ecomm->refcnt++;
992 }
993
1bcf3a96
DA
994 lcomm = bgp_attr_get_lcommunity(attr);
995 if (lcomm) {
996 if (!lcomm->refcnt)
997 bgp_attr_set_lcommunity(attr, lcommunity_intern(lcomm));
d62a17ae 998 else
1bcf3a96 999 lcomm->refcnt++;
d62a17ae 1000 }
779fee93
DS
1001
1002 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
1003
1004 if (cluster) {
1005 if (!cluster->refcnt)
1006 bgp_attr_set_cluster(attr, cluster_intern(cluster));
d62a17ae 1007 else
779fee93 1008 cluster->refcnt++;
d62a17ae 1009 }
04fb21e2
DS
1010
1011 struct transit *transit = bgp_attr_get_transit(attr);
1012
1013 if (transit) {
1014 if (!transit->refcnt)
1015 bgp_attr_set_transit(attr, transit_intern(transit));
d62a17ae 1016 else
04fb21e2 1017 transit->refcnt++;
d62a17ae 1018 }
1019 if (attr->encap_subtlvs) {
1020 if (!attr->encap_subtlvs->refcnt)
1021 attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
1022 ENCAP_SUBTLV_TYPE);
1023 else
1024 attr->encap_subtlvs->refcnt++;
1025 }
e496b420
HS
1026 if (attr->srv6_l3vpn) {
1027 if (!attr->srv6_l3vpn->refcnt)
1028 attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
1029 else
1030 attr->srv6_l3vpn->refcnt++;
1031 }
1032 if (attr->srv6_vpn) {
1033 if (!attr->srv6_vpn->refcnt)
1034 attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
1035 else
1036 attr->srv6_vpn->refcnt++;
1037 }
1e20238a 1038#ifdef ENABLE_BGP_VNC
91ebf12c
DS
1039 struct bgp_attr_encap_subtlv *vnc_subtlvs =
1040 bgp_attr_get_vnc_subtlvs(attr);
1041
1042 if (vnc_subtlvs) {
1043 if (!vnc_subtlvs->refcnt)
1044 bgp_attr_set_vnc_subtlvs(
1045 attr,
1046 encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
d62a17ae 1047 else
91ebf12c 1048 vnc_subtlvs->refcnt++;
d62a17ae 1049 }
aadc0905 1050#endif
bede7744 1051
dbbac180
DL
1052 /* At this point, attr only contains intern'd pointers. that means
1053 * if we find it in attrhash, it has all the same pointers and we
1054 * correctly updated the refcounts on these.
1055 * If we don't find it, we need to allocate a one because in all
1056 * cases this returns a new reference to a hashed attr, but the input
1057 * wasn't on hash. */
d62a17ae 1058 find = (struct attr *)hash_get(attrhash, attr, bgp_attr_hash_alloc);
1059 find->refcnt++;
1060
1061 return find;
718e3744 1062}
1063
1064/* Make network statement's attribute. */
0f05ea43
DA
1065struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,
1066 uint8_t origin)
718e3744 1067{
d62a17ae 1068 memset(attr, 0, sizeof(struct attr));
03e214c8 1069
d62a17ae 1070 attr->origin = origin;
1071 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1072 attr->aspath = aspath_empty();
1073 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1074 attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
1075 attr->tag = 0;
1076 attr->label_index = BGP_INVALID_LABEL_INDEX;
1077 attr->label = MPLS_INVALID_LABEL;
1078 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1079 attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
0f05ea43 1080 attr->local_pref = bgp->default_local_pref;
d62a17ae 1081
1082 return attr;
718e3744 1083}
1084
b5d58c32 1085/* Create the attributes for an aggregate */
5f040085
DS
1086struct attr *bgp_attr_aggregate_intern(
1087 struct bgp *bgp, uint8_t origin, struct aspath *aspath,
1088 struct community *community, struct ecommunity *ecommunity,
1089 struct lcommunity *lcommunity, struct bgp_aggregate *aggregate,
1090 uint8_t atomic_aggregate, const struct prefix *p)
d62a17ae 1091{
1092 struct attr attr;
1093 struct attr *new;
fd283bd2 1094 route_map_result_t ret;
d62a17ae 1095
6006b807 1096 memset(&attr, 0, sizeof(attr));
d62a17ae 1097
1098 /* Origin attribute. */
1099 attr.origin = origin;
1100 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1101
59136db5
DA
1102 /* MED */
1103 attr.med = 0;
1104 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1105
d62a17ae 1106 /* AS path attribute. */
1107 if (aspath)
1108 attr.aspath = aspath_intern(aspath);
1109 else
1110 attr.aspath = aspath_empty();
1111 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1112
1113 /* Next hop attribute. */
1114 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1115
1116 if (community) {
d7c0a89a 1117 uint32_t gshut = COMMUNITY_GSHUT;
7f323236
DW
1118
1119 /* If we are not shutting down ourselves and we are
1120 * aggregating a route that contains the GSHUT community we
1121 * need to remove that community when creating the aggregate */
637e5ba4 1122 if (!bgp_in_graceful_shutdown(bgp)
996c9314 1123 && community_include(community, gshut)) {
7f323236
DW
1124 community_del_val(community, &gshut);
1125 }
1126
9a706b42 1127 bgp_attr_set_community(&attr, community);
d62a17ae 1128 }
1129
58cf5c08 1130 if (ecommunity)
b53e67a3 1131 bgp_attr_set_ecommunity(&attr, ecommunity);
3da2cc32 1132
9d34440b 1133 if (lcommunity)
1bcf3a96 1134 bgp_attr_set_lcommunity(&attr, lcommunity);
dd18c5a9 1135
637e5ba4 1136 if (bgp_in_graceful_shutdown(bgp))
7f323236 1137 bgp_attr_add_gshut_community(&attr);
7f323236 1138
d62a17ae 1139 attr.label_index = BGP_INVALID_LABEL_INDEX;
1140 attr.label = MPLS_INVALID_LABEL;
1141 attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
1142 attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
20894f50 1143 if (!aggregate->as_set || atomic_aggregate)
d62a17ae 1144 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1145 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
1146 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
1147 attr.aggregator_as = bgp->confed_id;
1148 else
1149 attr.aggregator_as = bgp->as;
1150 attr.aggregator_addr = bgp->router_id;
d62a17ae 1151
20894f50
DA
1152 /* Apply route-map */
1153 if (aggregate->rmap.name) {
1154 struct attr attr_tmp = attr;
1155 struct bgp_path_info rmap_path;
1156
6006b807 1157 memset(&rmap_path, 0, sizeof(rmap_path));
20894f50
DA
1158 rmap_path.peer = bgp->peer_self;
1159 rmap_path.attr = &attr_tmp;
1160
1161 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1162
1782514f 1163 ret = route_map_apply(aggregate->rmap.map, p, &rmap_path);
20894f50
DA
1164
1165 bgp->peer_self->rmap_type = 0;
1166
1167 if (ret == RMAP_DENYMATCH) {
1168 /* Free uninterned attribute. */
1169 bgp_attr_flush(&attr_tmp);
1170
1171 /* Unintern original. */
1172 aspath_unintern(&attr.aspath);
1173 return NULL;
1174 }
1175
637e5ba4 1176 if (bgp_in_graceful_shutdown(bgp))
20894f50
DA
1177 bgp_attr_add_gshut_community(&attr_tmp);
1178
1179 new = bgp_attr_intern(&attr_tmp);
1180 } else {
1181
637e5ba4 1182 if (bgp_in_graceful_shutdown(bgp))
20894f50
DA
1183 bgp_attr_add_gshut_community(&attr);
1184
1185 new = bgp_attr_intern(&attr);
1186 }
d62a17ae 1187
8bd0d3b1
RZ
1188 /* Always release the 'intern()'ed AS Path. */
1189 aspath_unintern(&attr.aspath);
1190
d62a17ae 1191 return new;
718e3744 1192}
1193
b881c707 1194/* Unintern just the sub-components of the attr, but not the attr */
d62a17ae 1195void bgp_attr_unintern_sub(struct attr *attr)
1196{
b53e67a3
DA
1197 struct ecommunity *ecomm = NULL;
1198 struct ecommunity *ipv6_ecomm = NULL;
779fee93 1199 struct cluster_list *cluster;
1bcf3a96 1200 struct lcommunity *lcomm = NULL;
9a706b42 1201 struct community *comm = NULL;
d04ac434 1202
d62a17ae 1203 /* aspath refcount shoud be decrement. */
b7b3e63c 1204 aspath_unintern(&attr->aspath);
d62a17ae 1205 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
1206
9a706b42
DA
1207 comm = bgp_attr_get_community(attr);
1208 community_unintern(&comm);
9a706b42 1209 bgp_attr_set_community(attr, NULL);
d62a17ae 1210
b53e67a3
DA
1211 ecomm = bgp_attr_get_ecommunity(attr);
1212 ecommunity_unintern(&ecomm);
b53e67a3 1213 bgp_attr_set_ecommunity(attr, NULL);
d62a17ae 1214
b53e67a3
DA
1215 ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1216 ecommunity_unintern(&ipv6_ecomm);
d04ac434 1217 bgp_attr_set_ipv6_ecommunity(attr, NULL);
9a659715 1218
1bcf3a96
DA
1219 lcomm = bgp_attr_get_lcommunity(attr);
1220 lcommunity_unintern(&lcomm);
1bcf3a96 1221 bgp_attr_set_lcommunity(attr, NULL);
d62a17ae 1222
779fee93
DS
1223 cluster = bgp_attr_get_cluster(attr);
1224 if (cluster) {
1225 cluster_unintern(&cluster);
1226 bgp_attr_set_cluster(attr, cluster);
1227 }
d62a17ae 1228 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
1229
04fb21e2
DS
1230 struct transit *transit = bgp_attr_get_transit(attr);
1231
1232 if (transit) {
1233 transit_unintern(&transit);
1234 bgp_attr_set_transit(attr, transit);
1235 }
d62a17ae 1236
1237 if (attr->encap_subtlvs)
1238 encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
bede7744 1239
1e20238a 1240#ifdef ENABLE_BGP_VNC
91ebf12c
DS
1241 struct bgp_attr_encap_subtlv *vnc_subtlvs =
1242 bgp_attr_get_vnc_subtlvs(attr);
1243
1244 if (vnc_subtlvs) {
1245 encap_unintern(&vnc_subtlvs, VNC_SUBTLV_TYPE);
1246 bgp_attr_set_vnc_subtlvs(attr, vnc_subtlvs);
1247 }
bede7744 1248#endif
e496b420
HS
1249
1250 if (attr->srv6_l3vpn)
1251 srv6_l3vpn_unintern(&attr->srv6_l3vpn);
1252
1253 if (attr->srv6_vpn)
1254 srv6_vpn_unintern(&attr->srv6_vpn);
b881c707
PJ
1255}
1256
718e3744 1257/* Free bgp attribute and aspath. */
d62a17ae 1258void bgp_attr_unintern(struct attr **pattr)
1259{
1260 struct attr *attr = *pattr;
1261 struct attr *ret;
1262 struct attr tmp;
1263
1264 /* Decrement attribute reference. */
1265 attr->refcnt--;
1266
1267 tmp = *attr;
1268
1269 /* If reference becomes zero then free attribute object. */
1270 if (attr->refcnt == 0) {
1271 ret = hash_release(attrhash, attr);
1272 assert(ret != NULL);
1273 XFREE(MTYPE_ATTR, attr);
1274 *pattr = NULL;
1275 }
1276
1277 bgp_attr_unintern_sub(&tmp);
1278}
1279
1280void bgp_attr_flush(struct attr *attr)
1281{
d04ac434 1282 struct ecommunity *ecomm;
b53e67a3 1283 struct ecommunity *ipv6_ecomm;
779fee93 1284 struct cluster_list *cluster;
1bcf3a96 1285 struct lcommunity *lcomm;
9a706b42 1286 struct community *comm;
d04ac434 1287
d62a17ae 1288 if (attr->aspath && !attr->aspath->refcnt) {
1289 aspath_free(attr->aspath);
1290 attr->aspath = NULL;
1291 }
9a706b42
DA
1292 comm = bgp_attr_get_community(attr);
1293 if (comm && !comm->refcnt)
1294 community_free(&comm);
1295 bgp_attr_set_community(attr, NULL);
1296
b53e67a3 1297 ecomm = bgp_attr_get_ecommunity(attr);
d04ac434
DS
1298 if (ecomm && !ecomm->refcnt)
1299 ecommunity_free(&ecomm);
b53e67a3 1300 bgp_attr_set_ecommunity(attr, NULL);
9a706b42 1301
b53e67a3
DA
1302 ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1303 if (ipv6_ecomm && !ipv6_ecomm->refcnt)
1304 ecommunity_free(&ipv6_ecomm);
d04ac434 1305 bgp_attr_set_ipv6_ecommunity(attr, NULL);
9a706b42 1306
1bcf3a96
DA
1307 lcomm = bgp_attr_get_lcommunity(attr);
1308 if (lcomm && !lcomm->refcnt)
1309 lcommunity_free(&lcomm);
1310 bgp_attr_set_lcommunity(attr, NULL);
779fee93
DS
1311
1312 cluster = bgp_attr_get_cluster(attr);
1313 if (cluster && !cluster->refcnt) {
1314 cluster_free(cluster);
1315 bgp_attr_set_cluster(attr, NULL);
d62a17ae 1316 }
04fb21e2
DS
1317
1318 struct transit *transit = bgp_attr_get_transit(attr);
1319
1320 if (transit && !transit->refcnt) {
1321 transit_free(transit);
1322 bgp_attr_set_transit(attr, NULL);
d62a17ae 1323 }
1324 if (attr->encap_subtlvs && !attr->encap_subtlvs->refcnt) {
1325 encap_free(attr->encap_subtlvs);
1326 attr->encap_subtlvs = NULL;
1327 }
b83127e1
HS
1328 if (attr->srv6_l3vpn && !attr->srv6_l3vpn->refcnt) {
1329 srv6_l3vpn_free(attr->srv6_l3vpn);
1330 attr->srv6_l3vpn = NULL;
1331 }
1332 if (attr->srv6_vpn && !attr->srv6_vpn->refcnt) {
1333 srv6_vpn_free(attr->srv6_vpn);
1334 attr->srv6_vpn = NULL;
1335 }
1e20238a 1336#ifdef ENABLE_BGP_VNC
91ebf12c
DS
1337 struct bgp_attr_encap_subtlv *vnc_subtlvs =
1338 bgp_attr_get_vnc_subtlvs(attr);
1339
1340 if (vnc_subtlvs && !vnc_subtlvs->refcnt) {
1341 encap_free(vnc_subtlvs);
1342 bgp_attr_set_vnc_subtlvs(attr, NULL);
d62a17ae 1343 }
aadc0905 1344#endif
718e3744 1345}
1346
b881c707
PJ
1347/* Implement draft-scudder-idr-optional-transitive behaviour and
1348 * avoid resetting sessions for malformed attributes which are
1349 * are partial/optional and hence where the error likely was not
1350 * introduced by the sending neighbour.
1351 */
79288e4c 1352static enum bgp_attr_parse_ret
d7c0a89a 1353bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
d62a17ae 1354 bgp_size_t length)
1355{
1356 struct peer *const peer = args->peer;
599f7b33 1357 struct attr *const attr = args->attr;
d7c0a89a 1358 const uint8_t flags = args->flags;
d62a17ae 1359 /* startp and length must be special-cased, as whether or not to
1360 * send the attribute data with the NOTIFY depends on the error,
1361 * the caller therefore signals this with the seperate length argument
1362 */
d7c0a89a 1363 uint8_t *notify_datap = (length > 0 ? args->startp : NULL);
d62a17ae 1364
599f7b33
DA
1365 if (bgp_debug_update(peer, NULL, NULL, 1)) {
1366 char attr_str[BUFSIZ] = {0};
1367
99ab4d23 1368 bgp_dump_attr(attr, attr_str, sizeof(attr_str));
599f7b33
DA
1369
1370 zlog_debug("%s: attributes: %s", __func__, attr_str);
1371 }
1372
d62a17ae 1373 /* Only relax error handling for eBGP peers */
1374 if (peer->sort != BGP_PEER_EBGP) {
1375 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
1376 notify_datap, length);
1377 return BGP_ATTR_PARSE_ERROR;
1378 }
1379
1380 /* Adjust the stream getp to the end of the attribute, in case we can
1381 * still proceed but the caller hasn't read all the attribute.
1382 */
1383 stream_set_getp(BGP_INPUT(peer),
1384 (args->startp - STREAM_DATA(BGP_INPUT(peer)))
1385 + args->total);
1386
1387 switch (args->type) {
1388 /* where an attribute is relatively inconsequential, e.g. it does not
1389 * affect route selection, and can be safely ignored, then any such
1390 * attributes which are malformed should just be ignored and the route
1391 * processed as normal.
1392 */
1393 case BGP_ATTR_AS4_AGGREGATOR:
1394 case BGP_ATTR_AGGREGATOR:
1395 case BGP_ATTR_ATOMIC_AGGREGATE:
1396 return BGP_ATTR_PARSE_PROCEED;
1397
1398 /* Core attributes, particularly ones which may influence route
4ba5a9c5 1399 * selection, should be treat-as-withdraw.
d62a17ae 1400 */
1401 case BGP_ATTR_ORIGIN:
1402 case BGP_ATTR_AS_PATH:
1403 case BGP_ATTR_NEXT_HOP:
1404 case BGP_ATTR_MULTI_EXIT_DISC:
1405 case BGP_ATTR_LOCAL_PREF:
1406 case BGP_ATTR_COMMUNITIES:
4ba5a9c5 1407 case BGP_ATTR_EXT_COMMUNITIES:
9a659715 1408 case BGP_ATTR_IPV6_EXT_COMMUNITIES:
4ba5a9c5 1409 case BGP_ATTR_LARGE_COMMUNITIES:
d62a17ae 1410 case BGP_ATTR_ORIGINATOR_ID:
1411 case BGP_ATTR_CLUSTER_LIST:
adc1c459 1412 case BGP_ATTR_OTC:
4ba5a9c5 1413 return BGP_ATTR_PARSE_WITHDRAW;
d62a17ae 1414 case BGP_ATTR_MP_REACH_NLRI:
1415 case BGP_ATTR_MP_UNREACH_NLRI:
d62a17ae 1416 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
1417 notify_datap, length);
1418 return BGP_ATTR_PARSE_ERROR;
1419 }
1420
1421 /* Partial optional attributes that are malformed should not cause
1422 * the whole session to be reset. Instead treat it as a withdrawal
1423 * of the routes, if possible.
1424 */
1425 if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)
1426 && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1427 && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
1428 return BGP_ATTR_PARSE_WITHDRAW;
1429
1430 /* default to reset */
1431 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
b881c707
PJ
1432}
1433
afcb7679
DO
1434/* Find out what is wrong with the path attribute flag bits and log the error.
1435 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1436 Extended Length. Checking O/T/P bits at once implies, that the attribute
1437 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1438 non-transitive" attribute. */
1439static void
d62a17ae 1440bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args,
d7c0a89a
QY
1441 uint8_t desired_flags /* how RFC says it must be */
1442)
d62a17ae 1443{
d7c0a89a
QY
1444 uint8_t seen = 0, i;
1445 uint8_t real_flags = args->flags;
1446 const uint8_t attr_code = args->type;
d62a17ae 1447
1448 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1449 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1450 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
1451 if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1452 != CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
1c50c1c0
QY
1453 flog_err(EC_BGP_ATTR_FLAG,
1454 "%s attribute must%s be flagged as \"%s\"",
1455 lookup_msg(attr_str, attr_code, NULL),
1456 CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1457 ? ""
1458 : " not",
1459 attr_flag_str[i].str);
d62a17ae 1460 seen = 1;
1461 }
1462 if (!seen) {
1463 zlog_debug(
3efd0893 1464 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
d62a17ae 1465 __func__, lookup_msg(attr_str, attr_code, NULL),
1466 real_flags, desired_flags);
1467 }
afcb7679
DO
1468}
1469
3ecab4c8
PJ
1470/* Required flags for attributes. EXTLEN will be masked off when testing,
1471 * as will PARTIAL for optional+transitive attributes.
1472 */
d7c0a89a
QY
1473const uint8_t attr_flags_values[] = {
1474 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
1475 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
1476 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
1477 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
1478 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
1479 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
1480 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1481 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1482 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
1483 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1484 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1485 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1486 [BGP_ATTR_EXT_COMMUNITIES] =
1487 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1488 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1489 [BGP_ATTR_AS4_AGGREGATOR] =
1490 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1491 [BGP_ATTR_PMSI_TUNNEL] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1492 [BGP_ATTR_LARGE_COMMUNITIES] =
1493 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
d864dd9e 1494 [BGP_ATTR_OTC] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
d7c0a89a 1495 [BGP_ATTR_PREFIX_SID] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
9a659715
PG
1496 [BGP_ATTR_IPV6_EXT_COMMUNITIES] =
1497 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
97a52c82 1498 [BGP_ATTR_AIGP] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
3ecab4c8 1499};
099111ef 1500static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
3ecab4c8 1501
3dc339cd 1502static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
d62a17ae 1503{
d7c0a89a
QY
1504 uint8_t mask = BGP_ATTR_FLAG_EXTLEN;
1505 const uint8_t flags = args->flags;
1506 const uint8_t attr_code = args->type;
d62a17ae 1507
1508 /* there may be attributes we don't know about */
1509 if (attr_code > attr_flags_values_max)
3dc339cd 1510 return false;
d62a17ae 1511 if (attr_flags_values[attr_code] == 0)
3dc339cd 1512 return false;
d62a17ae 1513
1514 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1515 * to
1516 * 1."
1517 */
1518 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL, flags)
1519 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS, flags)) {
af4c2728 1520 flog_err(
e50f7cfd 1521 EC_BGP_ATTR_FLAG,
d62a17ae 1522 "%s well-known attributes must have transitive flag set (%x)",
1523 lookup_msg(attr_str, attr_code, NULL), flags);
3dc339cd 1524 return true;
d62a17ae 1525 }
1526
1527 /* "For well-known attributes and for optional non-transitive
1528 * attributes,
1529 * the Partial bit MUST be set to 0."
1530 */
1531 if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) {
1532 if (!CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)) {
e50f7cfd 1533 flog_err(EC_BGP_ATTR_FLAG,
3efd0893 1534 "%s well-known attribute must NOT have the partial flag set (%x)",
1c50c1c0 1535 lookup_msg(attr_str, attr_code, NULL), flags);
3dc339cd 1536 return true;
d62a17ae 1537 }
1538 if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1539 && !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) {
e50f7cfd 1540 flog_err(EC_BGP_ATTR_FLAG,
3efd0893 1541 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1c50c1c0 1542 lookup_msg(attr_str, attr_code, NULL), flags);
3dc339cd 1543 return true;
d62a17ae 1544 }
1545 }
1546
1547 /* Optional transitive attributes may go through speakers that don't
1548 * reocgnise them and set the Partial bit.
1549 */
1550 if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1551 && CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS))
1552 SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
1553
1554 if ((flags & ~mask) == attr_flags_values[attr_code])
3dc339cd 1555 return false;
d62a17ae 1556
1557 bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
3dc339cd 1558 return true;
3ecab4c8
PJ
1559}
1560
718e3744 1561/* Get origin attribute of the update message. */
79288e4c
DA
1562static enum bgp_attr_parse_ret
1563bgp_attr_origin(struct bgp_attr_parser_args *args)
d62a17ae 1564{
1565 struct peer *const peer = args->peer;
1566 struct attr *const attr = args->attr;
1567 const bgp_size_t length = args->length;
1568
1569 /* If any recognized attribute has Attribute Length that conflicts
1570 with the expected length (based on the attribute type code), then
1571 the Error Subcode is set to Attribute Length Error. The Data
1572 field contains the erroneous attribute (type, length and
1573 value). */
1574 if (length != 1) {
e50f7cfd 1575 flog_err(EC_BGP_ATTR_LEN,
1c50c1c0 1576 "Origin attribute length is not one %d", length);
d62a17ae 1577 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1578 args->total);
1579 }
1580
1581 /* Fetch origin attribute. */
1582 attr->origin = stream_getc(BGP_INPUT(peer));
1583
1584 /* If the ORIGIN attribute has an undefined value, then the Error
1585 Subcode is set to Invalid Origin Attribute. The Data field
1586 contains the unrecognized attribute (type, length and value). */
1587 if ((attr->origin != BGP_ORIGIN_IGP) && (attr->origin != BGP_ORIGIN_EGP)
1588 && (attr->origin != BGP_ORIGIN_INCOMPLETE)) {
e50f7cfd 1589 flog_err(EC_BGP_ATTR_ORIGIN,
1c50c1c0 1590 "Origin attribute value is invalid %d", attr->origin);
d62a17ae 1591 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1592 args->total);
1593 }
1594
1595 /* Set oring attribute flag. */
1596 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1597
1598 return 0;
718e3744 1599}
ab005298
PJ
1600
1601/* Parse AS path information. This function is wrapper of
1602 aspath_parse. */
d62a17ae 1603static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
1604{
1605 struct attr *const attr = args->attr;
1606 struct peer *const peer = args->peer;
1607 const bgp_size_t length = args->length;
1608
1609 /*
1610 * peer with AS4 => will get 4Byte ASnums
1611 * otherwise, will get 16 Bit
1612 */
8cff42ad
DA
1613 attr->aspath = aspath_parse(
1614 peer->curr, length,
1615 CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1616 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV));
d62a17ae 1617
1618 /* In case of IBGP, length will be zero. */
1619 if (!attr->aspath) {
e50f7cfd 1620 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1c50c1c0
QY
1621 "Malformed AS path from %s, length is %d", peer->host,
1622 length);
d62a17ae 1623 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1624 0);
1625 }
0b2aa3a0 1626
1bd36763
DA
1627 /* Conformant BGP speakers SHOULD NOT send BGP
1628 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1629 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1630 * withdraw" error handling behavior as per [RFC7606].
1631 */
1632 if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
1633 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1634 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1635 peer);
1636 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1637 0);
1638 }
1639
d62a17ae 1640 /* Set aspath attribute flag. */
1641 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1642
1643 return BGP_ATTR_PARSE_PROCEED;
1644}
1645
79288e4c
DA
1646static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
1647 struct attr *const attr)
d62a17ae 1648{
1649 /* These checks were part of bgp_attr_aspath, but with
1650 * as4 we should to check aspath things when
1651 * aspath synthesizing with as4_path has already taken place.
1652 * Otherwise we check ASPATH and use the synthesized thing, and that is
1653 * not right.
1654 * So do the checks later, i.e. here
1655 */
d62a17ae 1656 struct aspath *aspath;
1657
1658 /* Confederation sanity check. */
1659 if ((peer->sort == BGP_PEER_CONFED
1660 && !aspath_left_confed_check(attr->aspath))
1661 || (peer->sort == BGP_PEER_EBGP
1662 && aspath_confed_check(attr->aspath))) {
e50f7cfd 1663 flog_err(EC_BGP_ATTR_MAL_AS_PATH, "Malformed AS path from %s",
1c50c1c0 1664 peer->host);
4ba5a9c5 1665 return BGP_ATTR_PARSE_WITHDRAW;
d62a17ae 1666 }
cddb8112 1667
d62a17ae 1668 /* First AS check for EBGP. */
47cbc09b 1669 if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
d62a17ae 1670 if (peer->sort == BGP_PEER_EBGP
1671 && !aspath_firstas_check(attr->aspath, peer->as)) {
e50f7cfd 1672 flog_err(EC_BGP_ATTR_FIRST_AS,
1c50c1c0
QY
1673 "%s incorrect first AS (must be %u)",
1674 peer->host, peer->as);
4ba5a9c5 1675 return BGP_ATTR_PARSE_WITHDRAW;
d62a17ae 1676 }
1677 }
0b2aa3a0 1678
88cc0ce4
DA
1679 /* Codification of AS 0 Processing */
1680 if (peer->sort == BGP_PEER_EBGP && aspath_check_as_zero(attr->aspath)) {
1681 flog_err(
1682 EC_BGP_ATTR_MAL_AS_PATH,
1683 "Malformed AS path, AS number is 0 in the path from %s",
1684 peer->host);
1685 return BGP_ATTR_PARSE_WITHDRAW;
1686 }
1687
d62a17ae 1688 /* local-as prepend */
1689 if (peer->change_local_as
1690 && !CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) {
1691 aspath = aspath_dup(attr->aspath);
1692 aspath = aspath_add_seq(aspath, peer->change_local_as);
1693 aspath_unintern(&attr->aspath);
1694 attr->aspath = aspath_intern(aspath);
1695 }
0b2aa3a0 1696
d62a17ae 1697 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1698}
1699
ab005298
PJ
1700/* Parse AS4 path information. This function is another wrapper of
1701 aspath_parse. */
d62a17ae 1702static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
1703 struct aspath **as4_path)
ab005298 1704{
d62a17ae 1705 struct peer *const peer = args->peer;
1706 struct attr *const attr = args->attr;
1707 const bgp_size_t length = args->length;
ab005298 1708
424ab01d 1709 *as4_path = aspath_parse(peer->curr, length, 1);
b881c707 1710
d62a17ae 1711 /* In case of IBGP, length will be zero. */
1712 if (!*as4_path) {
e50f7cfd 1713 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1c50c1c0
QY
1714 "Malformed AS4 path from %s, length is %d", peer->host,
1715 length);
d62a17ae 1716 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1717 0);
1718 }
ab005298 1719
1bd36763
DA
1720 /* Conformant BGP speakers SHOULD NOT send BGP
1721 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1722 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1723 * withdraw" error handling behavior as per [RFC7606].
1724 */
1725 if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
1726 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1727 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1728 peer);
1729 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1730 0);
1731 }
1732
d62a17ae 1733 /* Set aspath attribute flag. */
1734 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
1735
1736 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1737}
1738
9738e9aa 1739/*
1740 * Check that the nexthop attribute is valid.
1741 */
79288e4c
DA
1742enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
1743 struct attr *attr)
9738e9aa 1744{
8666265e 1745 struct bgp *bgp = peer->bgp;
9738e9aa 1746
70632160 1747 if (ipv4_martian(&attr->nexthop) && !bgp->allow_martian) {
7decb30c 1748 uint8_t data[7]; /* type(2) + length(1) + nhop(4) */
9738e9aa 1749
07380148
DA
1750 flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %pI4",
1751 &attr->nexthop);
7decb30c
DS
1752 data[0] = BGP_ATTR_FLAG_TRANS;
1753 data[1] = BGP_ATTR_NEXT_HOP;
1754 data[2] = BGP_ATTR_NHLEN_IPV4;
1755 memcpy(&data[3], &attr->nexthop.s_addr, BGP_ATTR_NHLEN_IPV4);
1756 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
1757 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
1758 data, 7);
9738e9aa 1759 return BGP_ATTR_PARSE_ERROR;
1760 }
1761
1762 return BGP_ATTR_PARSE_PROCEED;
1763}
1764
718e3744 1765/* Nexthop attribute. */
79288e4c
DA
1766static enum bgp_attr_parse_ret
1767bgp_attr_nexthop(struct bgp_attr_parser_args *args)
d62a17ae 1768{
1769 struct peer *const peer = args->peer;
1770 struct attr *const attr = args->attr;
1771 const bgp_size_t length = args->length;
1772
d62a17ae 1773 /* Check nexthop attribute length. */
1774 if (length != 4) {
e50f7cfd 1775 flog_err(EC_BGP_ATTR_LEN,
1c50c1c0 1776 "Nexthop attribute length isn't four [%d]", length);
d62a17ae 1777
1778 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1779 args->total);
1780 }
1781
88f33d66 1782 attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
d62a17ae 1783 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1784
1785 return BGP_ATTR_PARSE_PROCEED;
718e3744 1786}
1787
1788/* MED atrribute. */
79288e4c 1789static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
718e3744 1790{
d62a17ae 1791 struct peer *const peer = args->peer;
1792 struct attr *const attr = args->attr;
1793 const bgp_size_t length = args->length;
b881c707 1794
d62a17ae 1795 /* Length check. */
1796 if (length != 4) {
e50f7cfd 1797 flog_err(EC_BGP_ATTR_LEN,
1c50c1c0 1798 "MED attribute length isn't four [%d]", length);
718e3744 1799
d62a17ae 1800 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1801 args->total);
1802 }
1803
424ab01d 1804 attr->med = stream_getl(peer->curr);
718e3744 1805
d62a17ae 1806 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
718e3744 1807
d62a17ae 1808 return BGP_ATTR_PARSE_PROCEED;
718e3744 1809}
1810
1811/* Local preference attribute. */
79288e4c 1812static enum bgp_attr_parse_ret
d62a17ae 1813bgp_attr_local_pref(struct bgp_attr_parser_args *args)
1814{
1815 struct peer *const peer = args->peer;
1816 struct attr *const attr = args->attr;
1817 const bgp_size_t length = args->length;
1818
4ba5a9c5
DA
1819 /* if received from an internal neighbor, it SHALL be considered
1820 * malformed if its length is not equal to 4. If malformed, the
1821 * UPDATE message SHALL be handled using the approach of "treat-as-
1822 * withdraw".
1823 */
1824 if (peer->sort == BGP_PEER_IBGP && length != 4) {
e50f7cfd 1825 flog_err(EC_BGP_ATTR_LEN,
1c50c1c0 1826 "LOCAL_PREF attribute length isn't 4 [%u]", length);
d62a17ae 1827 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1828 args->total);
1829 }
1830
1831 /* If it is contained in an UPDATE message that is received from an
1832 external peer, then this attribute MUST be ignored by the
1833 receiving speaker. */
1834 if (peer->sort == BGP_PEER_EBGP) {
ad61f778 1835 STREAM_FORWARD_GETP(peer->curr, length);
d62a17ae 1836 return BGP_ATTR_PARSE_PROCEED;
1837 }
1838
ad61f778 1839 STREAM_GETL(peer->curr, attr->local_pref);
d62a17ae 1840
7f323236 1841 /* Set the local-pref flag. */
d62a17ae 1842 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1843
1844 return BGP_ATTR_PARSE_PROCEED;
ad61f778
QY
1845
1846stream_failure:
1847 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1848 args->total);
718e3744 1849}
1850
1851/* Atomic aggregate. */
d62a17ae 1852static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
718e3744 1853{
a5c6a9b1 1854 struct peer *const peer = args->peer;
d62a17ae 1855 struct attr *const attr = args->attr;
1856 const bgp_size_t length = args->length;
1857
1858 /* Length check. */
1859 if (length != 0) {
e50f7cfd 1860 flog_err(EC_BGP_ATTR_LEN,
1c50c1c0
QY
1861 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1862 length);
d62a17ae 1863 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1864 args->total);
1865 }
718e3744 1866
a5c6a9b1
DA
1867 if (peer->discard_attrs[args->type])
1868 goto atomic_ignore;
1869
d62a17ae 1870 /* Set atomic aggregate flag. */
1871 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
718e3744 1872
d62a17ae 1873 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
1874
1875atomic_ignore:
1876 stream_forward_getp(peer->curr, length);
1877
1878 if (bgp_debug_update(peer, NULL, NULL, 1))
1879 zlog_debug("%pBP: Ignoring attribute %s", peer,
1880 lookup_msg(attr_str, args->type, NULL));
1881
1882 return BGP_ATTR_PARSE_PROCEED;
718e3744 1883}
1884
1885/* Aggregator attribute */
d62a17ae 1886static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
1887{
1888 struct peer *const peer = args->peer;
1889 struct attr *const attr = args->attr;
1890 const bgp_size_t length = args->length;
33d022bc 1891 as_t aggregator_as;
d62a17ae 1892
1893 int wantedlen = 6;
1894
1895 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
4ba5a9c5
DA
1896 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1897 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV))
d62a17ae 1898 wantedlen = 8;
1899
1900 if (length != wantedlen) {
e50f7cfd 1901 flog_err(EC_BGP_ATTR_LEN,
1c50c1c0
QY
1902 "AGGREGATOR attribute length isn't %u [%u]", wantedlen,
1903 length);
d62a17ae 1904 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1905 args->total);
1906 }
1907
a5c6a9b1
DA
1908 if (peer->discard_attrs[args->type])
1909 goto aggregator_ignore;
1910
d62a17ae 1911 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV))
33d022bc 1912 aggregator_as = stream_getl(peer->curr);
d62a17ae 1913 else
33d022bc
DA
1914 aggregator_as = stream_getw(peer->curr);
1915
e8364238
DA
1916 attr->aggregator_as = aggregator_as;
1917 attr->aggregator_addr.s_addr = stream_get_ipv4(peer->curr);
1918
33d022bc 1919 /* Codification of AS 0 Processing */
4877b70b 1920 if (aggregator_as == BGP_AS_ZERO) {
33d022bc 1921 flog_err(EC_BGP_ATTR_LEN,
8085c9a7
DA
1922 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1923 peer->host, aspath_print(attr->aspath));
4877b70b
DA
1924
1925 if (bgp_debug_update(peer, NULL, NULL, 1)) {
1926 char attr_str[BUFSIZ] = {0};
1927
1928 bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1929
1930 zlog_debug("%s: attributes: %s", __func__, attr_str);
1931 }
1932 } else {
8085c9a7 1933 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
4877b70b 1934 }
33d022bc 1935
d62a17ae 1936 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
1937
1938aggregator_ignore:
1939 stream_forward_getp(peer->curr, length);
1940
1941 if (bgp_debug_update(peer, NULL, NULL, 1))
1942 zlog_debug("%pBP: Ignoring attribute %s", peer,
1943 lookup_msg(attr_str, args->type, NULL));
1944
1945 return BGP_ATTR_PARSE_PROCEED;
718e3744 1946}
1947
0b2aa3a0 1948/* New Aggregator attribute */
79288e4c 1949static enum bgp_attr_parse_ret
d62a17ae 1950bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
1951 as_t *as4_aggregator_as,
1952 struct in_addr *as4_aggregator_addr)
1953{
1954 struct peer *const peer = args->peer;
1955 struct attr *const attr = args->attr;
1956 const bgp_size_t length = args->length;
33d022bc 1957 as_t aggregator_as;
d62a17ae 1958
1959 if (length != 8) {
1c50c1c0
QY
1960 flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
1961 length);
d62a17ae 1962 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1963 0);
1964 }
1965
a5c6a9b1
DA
1966 if (peer->discard_attrs[args->type])
1967 goto as4_aggregator_ignore;
1968
33d022bc 1969 aggregator_as = stream_getl(peer->curr);
0f2a703d 1970
e8364238
DA
1971 *as4_aggregator_as = aggregator_as;
1972 as4_aggregator_addr->s_addr = stream_get_ipv4(peer->curr);
1973
0f2a703d 1974 /* Codification of AS 0 Processing */
4877b70b 1975 if (aggregator_as == BGP_AS_ZERO) {
33d022bc 1976 flog_err(EC_BGP_ATTR_LEN,
8085c9a7
DA
1977 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1978 peer->host, aspath_print(attr->aspath));
4877b70b
DA
1979
1980 if (bgp_debug_update(peer, NULL, NULL, 1)) {
1981 char attr_str[BUFSIZ] = {0};
1982
1983 bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1984
1985 zlog_debug("%s: attributes: %s", __func__, attr_str);
1986 }
1987 } else {
8085c9a7 1988 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
4877b70b 1989 }
33d022bc 1990
d62a17ae 1991 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
1992
1993as4_aggregator_ignore:
1994 stream_forward_getp(peer->curr, length);
1995
1996 if (bgp_debug_update(peer, NULL, NULL, 1))
1997 zlog_debug("%pBP: Ignoring attribute %s", peer,
1998 lookup_msg(attr_str, args->type, NULL));
1999
2000 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
2001}
2002
2003/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
2004 */
79288e4c 2005static enum bgp_attr_parse_ret
d62a17ae 2006bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
2007 struct aspath *as4_path, as_t as4_aggregator,
2008 struct in_addr *as4_aggregator_addr)
2009{
2010 int ignore_as4_path = 0;
2011 struct aspath *newpath;
2012
2013 if (!attr->aspath) {
2014 /* NULL aspath shouldn't be possible as bgp_attr_parse should
2015 * have
2016 * checked that all well-known, mandatory attributes were
2017 * present.
2018 *
2019 * Can only be a problem with peer itself - hard error
2020 */
2021 return BGP_ATTR_PARSE_ERROR;
2022 }
2023
2024 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) {
2025 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
2026 * if given.
2027 * It is worth a warning though, because the peer really
2028 * should not send them
2029 */
2030 if (BGP_DEBUG(as4, AS4)) {
2031 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
2032 zlog_debug("[AS4] %s %s AS4_PATH", peer->host,
2033 "AS4 capable peer, yet it sent");
2034
2035 if (attr->flag
2036 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
2037 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2038 peer->host,
2039 "AS4 capable peer, yet it sent");
2040 }
2041
2042 return BGP_ATTR_PARSE_PROCEED;
2043 }
2044
2045 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2046 * because that may override AS4_PATH
2047 */
2048 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) {
2049 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
2050 /* received both.
2051 * if the as_number in aggregator is not AS_TRANS,
2052 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2053 * and the Aggregator shall be taken as
2054 * info on the aggregating node, and the AS_PATH
2055 * shall be taken as the AS_PATH
2056 * otherwise
2057 * the Aggregator shall be ignored and the
2058 * AS4_AGGREGATOR shall be taken as the
2059 * Aggregating node and the AS_PATH is to be
2060 * constructed "as in all other cases"
2061 */
2062 if (attr->aggregator_as != BGP_AS_TRANS) {
2063 /* ignore */
2064 if (BGP_DEBUG(as4, AS4))
2065 zlog_debug(
3efd0893 2066 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
d62a17ae 2067 peer->host);
2068 ignore_as4_path = 1;
2069 } else {
2070 /* "New_aggregator shall be taken as aggregator"
2071 */
2072 attr->aggregator_as = as4_aggregator;
2073 attr->aggregator_addr.s_addr =
2074 as4_aggregator_addr->s_addr;
2075 }
2076 } else {
2077 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2078 * That is bogus - but reading the conditions
2079 * we have to handle AS4_AGGREGATOR as if it were
2080 * AGGREGATOR in that case
2081 */
2082 if (BGP_DEBUG(as4, AS4))
2083 zlog_debug(
3efd0893 2084 "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there",
d62a17ae 2085 peer->host);
2086 attr->aggregator_as = as4_aggregator;
2087 /* sweep it under the carpet and simulate a "good"
2088 * AGGREGATOR */
2089 attr->flag |= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
2090 }
2091 }
2092
2093 /* need to reconcile NEW_AS_PATH and AS_PATH */
2094 if (!ignore_as4_path
2095 && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) {
2096 newpath = aspath_reconcile_as4(attr->aspath, as4_path);
e8a3a0a0 2097 if (!newpath)
2098 return BGP_ATTR_PARSE_ERROR;
2099
d62a17ae 2100 aspath_unintern(&attr->aspath);
2101 attr->aspath = aspath_intern(newpath);
2102 }
2103 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
2104}
2105
718e3744 2106/* Community attribute. */
79288e4c 2107static enum bgp_attr_parse_ret
d62a17ae 2108bgp_attr_community(struct bgp_attr_parser_args *args)
2109{
2110 struct peer *const peer = args->peer;
2111 struct attr *const attr = args->attr;
2112 const bgp_size_t length = args->length;
2113
2114 if (length == 0) {
9a706b42 2115 bgp_attr_set_community(attr, NULL);
6680b550
DA
2116 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2117 args->total);
d62a17ae 2118 }
2119
a5c6a9b1
DA
2120 if (peer->discard_attrs[args->type])
2121 goto community_ignore;
2122
9a706b42
DA
2123 bgp_attr_set_community(
2124 attr,
2125 community_parse((uint32_t *)stream_pnt(peer->curr), length));
d62a17ae 2126
2127 /* XXX: fix community_parse to use stream API and remove this */
424ab01d 2128 stream_forward_getp(peer->curr, length);
d62a17ae 2129
4ba5a9c5
DA
2130 /* The Community attribute SHALL be considered malformed if its
2131 * length is not a non-zero multiple of 4.
2132 */
9a706b42 2133 if (!bgp_attr_get_community(attr))
d62a17ae 2134 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2135 args->total);
2136
d62a17ae 2137 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
2138
2139community_ignore:
2140 stream_forward_getp(peer->curr, length);
2141
2142 if (bgp_debug_update(peer, NULL, NULL, 1))
2143 zlog_debug("%pBP: Ignoring attribute %s", peer,
2144 lookup_msg(attr_str, args->type, NULL));
2145
2146 return BGP_ATTR_PARSE_PROCEED;
718e3744 2147}
2148
2149/* Originator ID attribute. */
79288e4c 2150static enum bgp_attr_parse_ret
d62a17ae 2151bgp_attr_originator_id(struct bgp_attr_parser_args *args)
718e3744 2152{
d62a17ae 2153 struct peer *const peer = args->peer;
2154 struct attr *const attr = args->attr;
2155 const bgp_size_t length = args->length;
718e3744 2156
4ba5a9c5
DA
2157 /* if received from an internal neighbor, it SHALL be considered
2158 * malformed if its length is not equal to 4. If malformed, the
2159 * UPDATE message SHALL be handled using the approach of "treat-as-
2160 * withdraw".
2161 */
d62a17ae 2162 if (length != 4) {
e50f7cfd 2163 flog_err(EC_BGP_ATTR_LEN, "Bad originator ID length %d",
1c50c1c0 2164 length);
718e3744 2165
d62a17ae 2166 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2167 args->total);
2168 }
2169
a5c6a9b1
DA
2170 if (peer->discard_attrs[args->type])
2171 goto originator_id_ignore;
2172
424ab01d 2173 attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
718e3744 2174
d62a17ae 2175 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
718e3744 2176
d62a17ae 2177 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
2178
2179originator_id_ignore:
2180 stream_forward_getp(peer->curr, length);
2181
2182 if (bgp_debug_update(peer, NULL, NULL, 1))
2183 zlog_debug("%pBP: Ignoring attribute %s", peer,
2184 lookup_msg(attr_str, args->type, NULL));
2185
2186 return BGP_ATTR_PARSE_PROCEED;
718e3744 2187}
2188
2189/* Cluster list attribute. */
79288e4c 2190static enum bgp_attr_parse_ret
d62a17ae 2191bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
718e3744 2192{
d62a17ae 2193 struct peer *const peer = args->peer;
2194 struct attr *const attr = args->attr;
2195 const bgp_size_t length = args->length;
2196
4ba5a9c5
DA
2197 /* if received from an internal neighbor, it SHALL be considered
2198 * malformed if its length is not a non-zero multiple of 4. If
2199 * malformed, the UPDATE message SHALL be handled using the approach
2200 * of "treat-as-withdraw".
2201 */
33ba22c2 2202 if (length == 0 || length % 4) {
1c50c1c0 2203 flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
718e3744 2204
d62a17ae 2205 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2206 args->total);
2207 }
2208
a5c6a9b1
DA
2209 if (peer->discard_attrs[args->type])
2210 goto cluster_list_ignore;
2211
779fee93
DS
2212 bgp_attr_set_cluster(
2213 attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
2214 length));
718e3744 2215
d62a17ae 2216 /* XXX: Fix cluster_parse to use stream API and then remove this */
424ab01d 2217 stream_forward_getp(peer->curr, length);
718e3744 2218
d62a17ae 2219 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
718e3744 2220
d62a17ae 2221 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
2222
2223cluster_list_ignore:
2224 stream_forward_getp(peer->curr, length);
2225
2226 if (bgp_debug_update(peer, NULL, NULL, 1))
2227 zlog_debug("%pBP: Ignoring attribute %s", peer,
2228 lookup_msg(attr_str, args->type, NULL));
2229
2230 return BGP_ATTR_PARSE_PROCEED;
718e3744 2231}
2232
2233/* Multiprotocol reachability information parse. */
d62a17ae 2234int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
2235 struct bgp_nlri *mp_update)
2236{
2237 iana_afi_t pkt_afi;
2238 afi_t afi;
5c525538
RW
2239 iana_safi_t pkt_safi;
2240 safi_t safi;
d62a17ae 2241 bgp_size_t nlri_len;
2242 size_t start;
2243 struct stream *s;
2244 struct peer *const peer = args->peer;
2245 struct attr *const attr = args->attr;
2246 const bgp_size_t length = args->length;
2247
2248 /* Set end of packet. */
2249 s = BGP_INPUT(peer);
2250 start = stream_get_getp(s);
2251
2252/* safe to read statically sized header? */
6e4ab12f 2253#define BGP_MP_REACH_MIN_SIZE 5
03292809 2254#define LEN_LEFT (length - (stream_get_getp(s) - start))
d62a17ae 2255 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) {
4cb5e18b
NT
2256 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2257 __func__, peer->host, (unsigned long)length);
d62a17ae 2258 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2259 }
2260
2261 /* Load AFI, SAFI. */
2262 pkt_afi = stream_getw(s);
2263 pkt_safi = stream_getc(s);
2264
2265 /* Convert AFI, SAFI to internal values, check. */
2266 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2267 /* Log if AFI or SAFI is unrecognized. This is not an error
2268 * unless
2269 * the attribute is otherwise malformed.
2270 */
2271 if (bgp_debug_update(peer, NULL, NULL, 0))
2272 zlog_debug(
4cb5e18b 2273 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
748a041f
DS
2274 peer->host, iana_afi2str(pkt_afi),
2275 iana_safi2str(pkt_safi));
d62a17ae 2276 return BGP_ATTR_PARSE_ERROR;
2277 }
2278
2279 /* Get nexthop length. */
2280 attr->mp_nexthop_len = stream_getc(s);
2281
2282 if (LEN_LEFT < attr->mp_nexthop_len) {
2283 zlog_info(
4cb5e18b 2284 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
d62a17ae 2285 __func__, peer->host, attr->mp_nexthop_len);
2286 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2287 }
2288
2289 /* Nexthop length check. */
2290 switch (attr->mp_nexthop_len) {
7c40bf39 2291 case 0:
2292 if (safi != SAFI_FLOWSPEC) {
4cb5e18b 2293 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
7c40bf39 2294 __func__, peer->host, attr->mp_nexthop_len);
2295 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2296 }
2297 break;
b6453163
LB
2298 case BGP_ATTR_NHLEN_VPNV4:
2299 stream_getl(s); /* RD high */
2300 stream_getl(s); /* RD low */
996c9314
LB
2301 /*
2302 * NOTE: intentional fall through
2303 * - for consistency in rx processing
2304 *
2305 * The following comment is to signal GCC this intention
0437e105 2306 * and suppress the warning
996c9314
LB
2307 */
2308 /* FALLTHRU */
d62a17ae 2309 case BGP_ATTR_NHLEN_IPV4:
2310 stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
2311 /* Probably needed for RFC 2283 */
975a328e 2312 if (attr->nexthop.s_addr == INADDR_ANY)
d62a17ae 2313 memcpy(&attr->nexthop.s_addr,
2314 &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
2315 break;
d62a17ae 2316 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2317 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2318 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) {
2319 stream_getl(s); /* RD high */
2320 stream_getl(s); /* RD low */
2321 }
2322 stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
17cdd31e
DS
2323 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2324 if (!peer->nexthop.ifp) {
4cb5e18b 2325 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
17cdd31e
DS
2326 peer->host);
2327 return BGP_ATTR_PARSE_WITHDRAW;
2328 }
77e62f2b 2329 attr->nh_ifindex = peer->nexthop.ifp->ifindex;
17cdd31e 2330 }
d62a17ae 2331 break;
2332 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2333 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
2334 if (attr->mp_nexthop_len
2335 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2336 stream_getl(s); /* RD high */
2337 stream_getl(s); /* RD low */
2338 }
2339 stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
17cdd31e
DS
2340 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2341 if (!peer->nexthop.ifp) {
4cb5e18b 2342 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
17cdd31e
DS
2343 peer->host);
2344 return BGP_ATTR_PARSE_WITHDRAW;
2345 }
77e62f2b 2346 attr->nh_ifindex = peer->nexthop.ifp->ifindex;
17cdd31e 2347 }
d62a17ae 2348 if (attr->mp_nexthop_len
2349 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2350 stream_getl(s); /* RD high */
2351 stream_getl(s); /* RD low */
2352 }
2353 stream_get(&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
2354 if (!IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) {
d62a17ae 2355 if (bgp_debug_update(peer, NULL, NULL, 1))
2356 zlog_debug(
c0d72166
DS
2357 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2358 peer->host, &attr->mp_nexthop_global,
2359 &attr->mp_nexthop_local);
d62a17ae 2360
2361 attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
2362 }
17cdd31e 2363 if (!peer->nexthop.ifp) {
4cb5e18b 2364 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
17cdd31e
DS
2365 peer->host);
2366 return BGP_ATTR_PARSE_WITHDRAW;
2367 }
77e62f2b 2368 attr->nh_lla_ifindex = peer->nexthop.ifp->ifindex;
d62a17ae 2369 break;
2370 default:
4cb5e18b 2371 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
d62a17ae 2372 __func__, peer->host, attr->mp_nexthop_len);
2373 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2374 }
2375
2376 if (!LEN_LEFT) {
4cb5e18b
NT
2377 zlog_info("%s: %s sent SNPA which couldn't be read",
2378 __func__, peer->host);
d62a17ae 2379 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2380 }
2381
718e3744 2382 {
d7c0a89a 2383 uint8_t val;
d62a17ae 2384 if ((val = stream_getc(s)))
ade6974d 2385 flog_warn(
e50f7cfd 2386 EC_BGP_DEFUNCT_SNPA_LEN,
ade6974d
QY
2387 "%s sent non-zero value, %u, for defunct SNPA-length field",
2388 peer->host, val);
d62a17ae 2389 }
2390
2391 /* must have nrli_len, what is left of the attribute */
2392 nlri_len = LEN_LEFT;
9b9df989 2393 if (nlri_len > STREAM_READABLE(s)) {
4cb5e18b
NT
2394 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2395 __func__, peer->host);
d62a17ae 2396 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2397 }
2398
9b9df989 2399 if (!nlri_len) {
4cb5e18b 2400 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
9b9df989
DS
2401 __func__, peer->host);
2402
2403 mp_update->afi = afi;
2404 mp_update->safi = safi;
2405 return BGP_ATTR_PARSE_EOR;
2406 }
2407
d62a17ae 2408 mp_update->afi = afi;
2409 mp_update->safi = safi;
2410 mp_update->nlri = stream_pnt(s);
2411 mp_update->length = nlri_len;
2412
2413 stream_forward_getp(s, nlri_len);
2414
2415 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
2416
2417 return BGP_ATTR_PARSE_PROCEED;
03292809 2418#undef LEN_LEFT
718e3744 2419}
2420
2421/* Multiprotocol unreachable parse */
d62a17ae 2422int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
2423 struct bgp_nlri *mp_withdraw)
2424{
2425 struct stream *s;
2426 iana_afi_t pkt_afi;
2427 afi_t afi;
5c525538
RW
2428 iana_safi_t pkt_safi;
2429 safi_t safi;
d7c0a89a 2430 uint16_t withdraw_len;
d62a17ae 2431 struct peer *const peer = args->peer;
2432 struct attr *const attr = args->attr;
2433 const bgp_size_t length = args->length;
9cabb64b 2434
424ab01d 2435 s = peer->curr;
9cabb64b 2436
d62a17ae 2437#define BGP_MP_UNREACH_MIN_SIZE 3
2438 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
2439 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2440
2441 pkt_afi = stream_getw(s);
2442 pkt_safi = stream_getc(s);
2443
2444 /* Convert AFI, SAFI to internal values, check. */
2445 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2446 /* Log if AFI or SAFI is unrecognized. This is not an error
2447 * unless
2448 * the attribute is otherwise malformed.
2449 */
2450 if (bgp_debug_update(peer, NULL, NULL, 0))
2451 zlog_debug(
748a041f
DS
2452 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2453 peer->host, iana_afi2str(pkt_afi),
2454 iana_safi2str(pkt_safi));
d62a17ae 2455 return BGP_ATTR_PARSE_ERROR;
2456 }
718e3744 2457
d62a17ae 2458 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
718e3744 2459
d62a17ae 2460 mp_withdraw->afi = afi;
2461 mp_withdraw->safi = safi;
2462 mp_withdraw->nlri = stream_pnt(s);
2463 mp_withdraw->length = withdraw_len;
718e3744 2464
d62a17ae 2465 stream_forward_getp(s, withdraw_len);
37da8fa9 2466
d62a17ae 2467 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI);
2468
2469 return BGP_ATTR_PARSE_PROCEED;
718e3744 2470}
2471
57d187bc 2472/* Large Community attribute. */
79288e4c 2473static enum bgp_attr_parse_ret
d62a17ae 2474bgp_attr_large_community(struct bgp_attr_parser_args *args)
2475{
2476 struct peer *const peer = args->peer;
2477 struct attr *const attr = args->attr;
2478 const bgp_size_t length = args->length;
2479
2480 /*
2481 * Large community follows new attribute format.
2482 */
2483 if (length == 0) {
1bcf3a96 2484 bgp_attr_set_lcommunity(attr, NULL);
d62a17ae 2485 /* Empty extcomm doesn't seem to be invalid per se */
6680b550
DA
2486 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2487 args->total);
d62a17ae 2488 }
57d187bc 2489
a5c6a9b1
DA
2490 if (peer->discard_attrs[args->type])
2491 goto large_community_ignore;
2492
1bcf3a96
DA
2493 bgp_attr_set_lcommunity(
2494 attr, lcommunity_parse(stream_pnt(peer->curr), length));
d62a17ae 2495 /* XXX: fix ecommunity_parse to use stream API */
424ab01d 2496 stream_forward_getp(peer->curr, length);
57d187bc 2497
1bcf3a96 2498 if (!bgp_attr_get_lcommunity(attr))
d62a17ae 2499 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2500 args->total);
57d187bc 2501
d62a17ae 2502 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
2503
2504large_community_ignore:
2505 stream_forward_getp(peer->curr, length);
2506
2507 if (bgp_debug_update(peer, NULL, NULL, 1))
2508 zlog_debug("%pBP: Ignoring attribute %s", peer,
2509 lookup_msg(attr_str, args->type, NULL));
2510
2511 return BGP_ATTR_PARSE_PROCEED;
57d187bc
JS
2512}
2513
718e3744 2514/* Extended Community attribute. */
79288e4c 2515static enum bgp_attr_parse_ret
d62a17ae 2516bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
2517{
2518 struct peer *const peer = args->peer;
2519 struct attr *const attr = args->attr;
2520 const bgp_size_t length = args->length;
d7c0a89a 2521 uint8_t sticky = 0;
7904e9fd 2522 bool proxy = false;
b53e67a3 2523 struct ecommunity *ecomm;
d62a17ae 2524
2525 if (length == 0) {
b53e67a3 2526 bgp_attr_set_ecommunity(attr, NULL);
d62a17ae 2527 /* Empty extcomm doesn't seem to be invalid per se */
6680b550
DA
2528 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2529 args->total);
d62a17ae 2530 }
2531
b53e67a3 2532 ecomm = ecommunity_parse(
27aa23a4
DA
2533 stream_pnt(peer->curr), length,
2534 CHECK_FLAG(peer->flags,
2535 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
b53e67a3 2536 bgp_attr_set_ecommunity(attr, ecomm);
d62a17ae 2537 /* XXX: fix ecommunity_parse to use stream API */
424ab01d 2538 stream_forward_getp(peer->curr, length);
d62a17ae 2539
4ba5a9c5
DA
2540 /* The Extended Community attribute SHALL be considered malformed if
2541 * its length is not a non-zero multiple of 8.
2542 */
b53e67a3 2543 if (!bgp_attr_get_ecommunity(attr))
d62a17ae 2544 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2545 args->total);
2546
74e2bd89
AK
2547 /* Extract DF election preference and mobility sequence number */
2548 attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
2549
d62a17ae 2550 /* Extract MAC mobility sequence number, if any. */
2551 attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
2552 attr->sticky = sticky;
2553
ead40654
MK
2554 /* Check if this is a Gateway MAC-IP advertisement */
2555 attr->default_gw = bgp_attr_default_gw(attr);
2556
68e33151
CS
2557 /* Handle scenario where router flag ecommunity is not
2558 * set but default gw ext community is present.
2559 * Use default gateway, set and propogate R-bit.
2560 */
2561 if (attr->default_gw)
2562 attr->router_flag = 1;
2563
2564 /* Check EVPN Neighbor advertisement flags, R-bit */
7904e9fd
AK
2565 bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy);
2566 if (proxy)
2567 attr->es_flags |= ATTR_ES_PROXY_ADVERT;
68e33151 2568
bc59a672 2569 /* Extract the Rmac, if any */
eee353c5 2570 if (bgp_attr_rmac(attr, &attr->rmac)) {
c0d72166
DS
2571 if (bgp_debug_update(peer, NULL, NULL, 1)
2572 && bgp_mac_exist(&attr->rmac))
2573 zlog_debug("%s: router mac %pEA is self mac", __func__,
2574 &attr->rmac);
eee353c5 2575 }
bc59a672 2576
f4bd90c5
LK
2577 /* Get the tunnel type from encap extended community */
2578 bgp_attr_extcom_tunnel_type(attr,
2579 (bgp_encap_types *)&attr->encap_tunneltype);
2580
d901dc13 2581 /* Extract link bandwidth, if any. */
b53e67a3
DA
2582 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr),
2583 &attr->link_bw);
d901dc13 2584
d62a17ae 2585 return BGP_ATTR_PARSE_PROCEED;
718e3744 2586}
2587
9a659715 2588/* IPv6 Extended Community attribute. */
79288e4c 2589static enum bgp_attr_parse_ret
9a659715
PG
2590bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
2591{
2592 struct peer *const peer = args->peer;
2593 struct attr *const attr = args->attr;
2594 const bgp_size_t length = args->length;
d04ac434 2595 struct ecommunity *ipv6_ecomm = NULL;
9a659715
PG
2596
2597 if (length == 0) {
d04ac434 2598 bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
c6423c31
PG
2599 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2600 args->total);
9a659715
PG
2601 }
2602
a5c6a9b1
DA
2603 if (peer->discard_attrs[args->type])
2604 goto ipv6_ext_community_ignore;
2605
27aa23a4
DA
2606 ipv6_ecomm = ecommunity_parse_ipv6(
2607 stream_pnt(peer->curr), length,
2608 CHECK_FLAG(peer->flags,
2609 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
d04ac434
DS
2610 bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2611
9a659715
PG
2612 /* XXX: fix ecommunity_parse to use stream API */
2613 stream_forward_getp(peer->curr, length);
2614
d04ac434 2615 if (!ipv6_ecomm)
9a659715
PG
2616 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2617 args->total);
2618
9a659715 2619 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
2620
2621ipv6_ext_community_ignore:
2622 stream_forward_getp(peer->curr, length);
2623
2624 if (bgp_debug_update(peer, NULL, NULL, 1))
2625 zlog_debug("%pBP: Ignoring attribute %s", peer,
2626 lookup_msg(attr_str, args->type, NULL));
2627
2628 return BGP_ATTR_PARSE_PROCEED;
9a659715
PG
2629}
2630
f4c89855 2631/* Parse Tunnel Encap attribute in an UPDATE */
d62a17ae 2632static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
2633 bgp_size_t length, /* IN: attr's length field */
2634 struct attr *attr, /* IN: caller already allocated */
d7c0a89a
QY
2635 uint8_t flag, /* IN: attr's flags field */
2636 uint8_t *startp)
d62a17ae 2637{
2638 bgp_size_t total;
d62a17ae 2639 uint16_t tunneltype = 0;
2640
2641 total = length + (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
2642
2643 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
2644 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
2645 zlog_info(
2646 "Tunnel Encap attribute flag isn't optional and transitive %d",
2647 flag);
2648 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
2649 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2650 startp, total);
2651 return -1;
2652 }
2653
2654 if (BGP_ATTR_ENCAP == type) {
2655 /* read outer TLV type and length */
2656 uint16_t tlv_length;
2657
2658 if (length < 4) {
2659 zlog_info(
2660 "Tunnel Encap attribute not long enough to contain outer T,L");
2661 bgp_notify_send_with_data(
2662 peer, BGP_NOTIFY_UPDATE_ERR,
2663 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
2664 return -1;
2665 }
2666 tunneltype = stream_getw(BGP_INPUT(peer));
2667 tlv_length = stream_getw(BGP_INPUT(peer));
2668 length -= 4;
2669
2670 if (tlv_length != length) {
4cb5e18b
NT
2671 zlog_info("%s: tlv_length(%d) != length(%d)",
2672 __func__, tlv_length, length);
d62a17ae 2673 }
2674 }
2675
2676 while (length >= 4) {
2677 uint16_t subtype = 0;
2678 uint16_t sublength = 0;
2679 struct bgp_attr_encap_subtlv *tlv;
2680
2681 if (BGP_ATTR_ENCAP == type) {
2682 subtype = stream_getc(BGP_INPUT(peer));
2683 sublength = stream_getc(BGP_INPUT(peer));
2684 length -= 2;
1e20238a 2685#ifdef ENABLE_BGP_VNC
d62a17ae 2686 } else {
2687 subtype = stream_getw(BGP_INPUT(peer));
2688 sublength = stream_getw(BGP_INPUT(peer));
2689 length -= 4;
65efcfce 2690#endif
d62a17ae 2691 }
2692
2693 if (sublength > length) {
2694 zlog_info(
2695 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2696 sublength, length);
2697 bgp_notify_send_with_data(
2698 peer, BGP_NOTIFY_UPDATE_ERR,
2699 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
2700 return -1;
2701 }
2702
2703 /* alloc and copy sub-tlv */
2704 /* TBD make sure these are freed when attributes are released */
2705 tlv = XCALLOC(MTYPE_ENCAP_TLV,
996c9314 2706 sizeof(struct bgp_attr_encap_subtlv) + sublength);
d62a17ae 2707 tlv->type = subtype;
2708 tlv->length = sublength;
424ab01d 2709 stream_get(tlv->value, peer->curr, sublength);
d62a17ae 2710 length -= sublength;
2711
2712 /* attach tlv to encap chain */
2713 if (BGP_ATTR_ENCAP == type) {
e4002056 2714 struct bgp_attr_encap_subtlv *stlv_last;
d62a17ae 2715 for (stlv_last = attr->encap_subtlvs;
2716 stlv_last && stlv_last->next;
2717 stlv_last = stlv_last->next)
2718 ;
2719 if (stlv_last) {
2720 stlv_last->next = tlv;
2721 } else {
2722 attr->encap_subtlvs = tlv;
2723 }
1e20238a 2724#ifdef ENABLE_BGP_VNC
d62a17ae 2725 } else {
e4002056 2726 struct bgp_attr_encap_subtlv *stlv_last;
91ebf12c
DS
2727 struct bgp_attr_encap_subtlv *vnc_subtlvs =
2728 bgp_attr_get_vnc_subtlvs(attr);
2729
2730 for (stlv_last = vnc_subtlvs;
d62a17ae 2731 stlv_last && stlv_last->next;
2732 stlv_last = stlv_last->next)
2733 ;
91ebf12c 2734 if (stlv_last)
d62a17ae 2735 stlv_last->next = tlv;
91ebf12c
DS
2736 else
2737 bgp_attr_set_vnc_subtlvs(attr, tlv);
aadc0905 2738#endif
d62a17ae 2739 }
d62a17ae 2740 }
f4c89855 2741
d62a17ae 2742 if (BGP_ATTR_ENCAP == type) {
2743 attr->encap_tunneltype = tunneltype;
2744 }
f4c89855 2745
d62a17ae 2746 if (length) {
2747 /* spurious leftover data */
2748 zlog_info(
2749 "Tunnel Encap attribute length is bad: %d leftover octets",
2750 length);
2751 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
2752 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2753 startp, total);
2754 return -1;
2755 }
f4c89855 2756
d62a17ae 2757 return 0;
f4c89855
LB
2758}
2759
73604f82
RS
2760
2761/* SRv6 Service Data Sub-Sub-TLV attribute
2762 * draft-ietf-bess-srv6-services-07
2763 */
79288e4c 2764static enum bgp_attr_parse_ret
73604f82
RS
2765bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
2766{
2767 struct peer *const peer = args->peer;
9299fd00 2768 struct attr *const attr = args->attr;
73604f82
RS
2769 uint8_t type, loc_block_len, loc_node_len, func_len, arg_len,
2770 transposition_len, transposition_offset;
2771 uint16_t length;
2772 size_t headersz = sizeof(type) + sizeof(length);
2773
2774 if (STREAM_READABLE(peer->curr) < headersz) {
2775 flog_err(
2776 EC_BGP_ATTR_LEN,
2777 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2778 headersz, STREAM_READABLE(peer->curr));
2779 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2780 args->total);
2781 }
2782
2783 type = stream_getc(peer->curr);
2784 length = stream_getw(peer->curr);
2785
2786 if (STREAM_READABLE(peer->curr) < length) {
2787 flog_err(
2788 EC_BGP_ATTR_LEN,
2789 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2790 length, STREAM_READABLE(peer->curr));
2791 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2792 args->total);
2793 }
2794
5c111a25
DS
2795 if (length < BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2796 flog_err(
2797 EC_BGP_ATTR_LEN,
c5fa4459 2798 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
5c111a25
DS
2799 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2800 length);
2801 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2802 args->total);
2803 }
2804
73604f82 2805 if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
bc32d950
DS
2806 if (STREAM_READABLE(peer->curr) <
2807 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2808 flog_err(
2809 EC_BGP_ATTR_LEN,
2810 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2811 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2812 STREAM_READABLE(peer->curr));
2813 return bgp_attr_malformed(
2814 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2815 args->total);
2816 }
2817
73604f82
RS
2818 loc_block_len = stream_getc(peer->curr);
2819 loc_node_len = stream_getc(peer->curr);
2820 func_len = stream_getc(peer->curr);
2821 arg_len = stream_getc(peer->curr);
2822 transposition_len = stream_getc(peer->curr);
2823 transposition_offset = stream_getc(peer->curr);
2824
2825 /* Log SRv6 Service Data Sub-Sub-TLV */
2826 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
2827 zlog_debug(
2828 "%s: srv6-l3-srv-data loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u, transposition-len=%u, transposition-offset=%u",
2829 __func__, loc_block_len, loc_node_len, func_len,
2830 arg_len, transposition_len,
2831 transposition_offset);
2832 }
9299fd00
RS
2833
2834 attr->srv6_l3vpn->loc_block_len = loc_block_len;
2835 attr->srv6_l3vpn->loc_node_len = loc_node_len;
2836 attr->srv6_l3vpn->func_len = func_len;
2837 attr->srv6_l3vpn->arg_len = arg_len;
2838 attr->srv6_l3vpn->transposition_len = transposition_len;
2839 attr->srv6_l3vpn->transposition_offset = transposition_offset;
73604f82
RS
2840 }
2841
2842 else {
2843 if (bgp_debug_update(peer, NULL, NULL, 1))
2844 zlog_debug(
2845 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2846 peer->host, type);
2847
2848 stream_forward_getp(peer->curr, length);
2849 }
2850
2851 return BGP_ATTR_PARSE_PROCEED;
2852}
2853
2854/* SRv6 Service Sub-TLV attribute
2855 * draft-ietf-bess-srv6-services-07
2856 */
79288e4c 2857static enum bgp_attr_parse_ret
73604f82
RS
2858bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
2859{
2860 struct peer *const peer = args->peer;
2861 struct attr *const attr = args->attr;
2862 struct in6_addr ipv6_sid;
2863 uint8_t type, sid_flags;
2864 uint16_t length, endpoint_behavior;
2865 size_t headersz = sizeof(type) + sizeof(length);
79288e4c 2866 enum bgp_attr_parse_ret err;
73604f82
RS
2867
2868 if (STREAM_READABLE(peer->curr) < headersz) {
2869 flog_err(
2870 EC_BGP_ATTR_LEN,
2871 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2872 headersz, STREAM_READABLE(peer->curr));
2873 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2874 args->total);
2875 }
2876
2877 type = stream_getc(peer->curr);
2878 length = stream_getw(peer->curr);
2879
2880 if (STREAM_READABLE(peer->curr) < length) {
2881 flog_err(
2882 EC_BGP_ATTR_LEN,
2883 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2884 length, STREAM_READABLE(peer->curr));
2885 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2886 args->total);
2887 }
2888
2889 if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
bc32d950
DS
2890 if (STREAM_READABLE(peer->curr) <
2891 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2892 flog_err(
2893 EC_BGP_ATTR_LEN,
2894 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2895 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH,
2896 STREAM_READABLE(peer->curr));
2897 return bgp_attr_malformed(
2898 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2899 args->total);
2900 }
73604f82
RS
2901 stream_getc(peer->curr);
2902 stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
2903 sid_flags = stream_getc(peer->curr);
2904 endpoint_behavior = stream_getw(peer->curr);
2905 stream_getc(peer->curr);
2906
2907 /* Log SRv6 Service Sub-TLV */
07380148 2908 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
73604f82 2909 zlog_debug(
07380148
DA
2910 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2911 __func__, &ipv6_sid, sid_flags,
2912 endpoint_behavior);
73604f82
RS
2913
2914 /* Configure from Info */
2915 if (attr->srv6_l3vpn) {
2916 flog_err(EC_BGP_ATTRIBUTE_REPEATED,
2917 "Prefix SID SRv6 L3VPN field repeated");
2918 return bgp_attr_malformed(
2919 args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
2920 }
2921 attr->srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
2922 sizeof(struct bgp_attr_srv6_l3vpn));
9299fd00 2923 sid_copy(&attr->srv6_l3vpn->sid, &ipv6_sid);
73604f82
RS
2924 attr->srv6_l3vpn->sid_flags = sid_flags;
2925 attr->srv6_l3vpn->endpoint_behavior = endpoint_behavior;
9299fd00
RS
2926 attr->srv6_l3vpn->loc_block_len = 0;
2927 attr->srv6_l3vpn->loc_node_len = 0;
2928 attr->srv6_l3vpn->func_len = 0;
2929 attr->srv6_l3vpn->arg_len = 0;
2930 attr->srv6_l3vpn->transposition_len = 0;
2931 attr->srv6_l3vpn->transposition_offset = 0;
73604f82
RS
2932
2933 // Sub-Sub-TLV found
9299fd00
RS
2934 if (length > BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2935 err = bgp_attr_srv6_service_data(args);
2936
2937 if (err != BGP_ATTR_PARSE_PROCEED)
2938 return err;
2939 }
2940
2941 attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
73604f82
RS
2942 }
2943
2944 /* Placeholder code for unsupported type */
2945 else {
2946 if (bgp_debug_update(peer, NULL, NULL, 1))
2947 zlog_debug(
2948 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2949 peer->host, type);
2950
2951 stream_forward_getp(peer->curr, length);
2952 }
2953
2954 return BGP_ATTR_PARSE_PROCEED;
2955}
2956
30adbd4e
DS
2957/*
2958 * Read an individual SID value returning how much data we have read
2959 * Returns 0 if there was an error that needs to be passed up the stack
c5a543b4 2960 */
79288e4c
DA
2961static enum bgp_attr_parse_ret
2962bgp_attr_psid_sub(uint8_t type, uint16_t length,
2963 struct bgp_attr_parser_args *args)
d62a17ae 2964{
2965 struct peer *const peer = args->peer;
2966 struct attr *const attr = args->attr;
d7c0a89a 2967 uint32_t label_index;
d62a17ae 2968 struct in6_addr ipv6_sid;
d7c0a89a
QY
2969 uint32_t srgb_base;
2970 uint32_t srgb_range;
d62a17ae 2971 int srgb_count;
e496b420 2972 uint8_t sid_type, sid_flags;
d62a17ae 2973
d62a17ae 2974 if (type == BGP_PREFIX_SID_LABEL_INDEX) {
f69aeb76
QY
2975 if (STREAM_READABLE(peer->curr) < length
2976 || length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
2977 flog_err(EC_BGP_ATTR_LEN,
6cde4b45 2978 "Prefix SID label index length is %hu instead of %u",
f69aeb76 2979 length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
30adbd4e
DS
2980 return bgp_attr_malformed(args,
2981 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2982 args->total);
d62a17ae 2983 }
2984
2985 /* Ignore flags and reserved */
424ab01d
QY
2986 stream_getc(peer->curr);
2987 stream_getw(peer->curr);
d62a17ae 2988
2989 /* Fetch the label index and see if it is valid. */
424ab01d 2990 label_index = stream_getl(peer->curr);
d62a17ae 2991 if (label_index == BGP_INVALID_LABEL_INDEX)
30adbd4e
DS
2992 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2993 args->total);
d62a17ae 2994
2995 /* Store label index; subsequently, we'll check on
2996 * address-family */
2997 attr->label_index = label_index;
d62a17ae 2998 }
2999
3000 /* Placeholder code for the IPv6 SID type */
3001 else if (type == BGP_PREFIX_SID_IPV6) {
f69aeb76
QY
3002 if (STREAM_READABLE(peer->curr) < length
3003 || length != BGP_PREFIX_SID_IPV6_LENGTH) {
e50f7cfd 3004 flog_err(EC_BGP_ATTR_LEN,
6cde4b45 3005 "Prefix SID IPv6 length is %hu instead of %u",
1c50c1c0 3006 length, BGP_PREFIX_SID_IPV6_LENGTH);
30adbd4e
DS
3007 return bgp_attr_malformed(args,
3008 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3009 args->total);
d62a17ae 3010 }
3011
3012 /* Ignore reserved */
424ab01d
QY
3013 stream_getc(peer->curr);
3014 stream_getw(peer->curr);
d62a17ae 3015
424ab01d 3016 stream_get(&ipv6_sid, peer->curr, 16);
d62a17ae 3017 }
3018
3019 /* Placeholder code for the Originator SRGB type */
3020 else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
473046ee
QY
3021 /*
3022 * ietf-idr-bgp-prefix-sid-05:
3023 * Length is the total length of the value portion of the
3024 * TLV: 2 + multiple of 6.
3025 *
3026 * peer->curr stream readp should be at the beginning of the 16
3027 * bit flag field at this point in the code.
3028 */
d62a17ae 3029
473046ee
QY
3030 /*
3031 * Check that the TLV length field is sane: at least 2 bytes of
3032 * flag, and at least 1 SRGB (these are 6 bytes each)
3033 */
3034 if (length < (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH)) {
3035 flog_err(
3036 EC_BGP_ATTR_LEN,
6cde4b45 3037 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
473046ee
QY
3038 length,
3039 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
3040 return bgp_attr_malformed(
3041 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3042 args->total);
3043 }
d62a17ae 3044
473046ee
QY
3045 /*
3046 * Check that we actually have at least as much data as
3047 * specified by the length field
3048 */
3049 if (STREAM_READABLE(peer->curr) < length) {
f69aeb76 3050 flog_err(EC_BGP_ATTR_LEN,
6cde4b45 3051 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
473046ee 3052 length, STREAM_READABLE(peer->curr));
f69aeb76
QY
3053 return bgp_attr_malformed(
3054 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3055 args->total);
3056 }
3057
473046ee
QY
3058 /*
3059 * Check that the portion of the TLV containing the sequence of
3060 * SRGBs corresponds to a multiple of the SRGB size; to get
3061 * that length, we skip the 16 bit flags field
3062 */
424ab01d 3063 stream_getw(peer->curr);
d62a17ae 3064 length -= 2;
d62a17ae 3065 if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) {
af4c2728 3066 flog_err(
e50f7cfd 3067 EC_BGP_ATTR_LEN,
6cde4b45 3068 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
d62a17ae 3069 length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
3070 return bgp_attr_malformed(
3071 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3072 args->total);
3073 }
3074
3075 srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH;
3076
3077 for (int i = 0; i < srgb_count; i++) {
424ab01d
QY
3078 stream_get(&srgb_base, peer->curr, 3);
3079 stream_get(&srgb_range, peer->curr, 3);
d62a17ae 3080 }
3081 }
3082
e496b420
HS
3083 /* Placeholder code for the VPN-SID Service type */
3084 else if (type == BGP_PREFIX_SID_VPN_SID) {
3085 if (STREAM_READABLE(peer->curr) < length
3086 || length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
3087 flog_err(EC_BGP_ATTR_LEN,
6cde4b45 3088 "Prefix SID VPN SID length is %hu instead of %u",
e496b420
HS
3089 length, BGP_PREFIX_SID_VPN_SID_LENGTH);
3090 return bgp_attr_malformed(args,
3091 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3092 args->total);
3093 }
3094
3095 /* Parse VPN-SID Sub-TLV */
3096 stream_getc(peer->curr); /* reserved */
3097 sid_type = stream_getc(peer->curr); /* sid_type */
3098 sid_flags = stream_getc(peer->curr); /* sid_flags */
3099 stream_get(&ipv6_sid, peer->curr,
3100 sizeof(ipv6_sid)); /* sid_value */
3101
3102 /* Log VPN-SID Sub-TLV */
07380148 3103 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
e496b420 3104 zlog_debug(
07380148
DA
3105 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3106 __func__, &ipv6_sid, sid_type, sid_flags);
e496b420
HS
3107
3108 /* Configure from Info */
b502ca11
QY
3109 if (attr->srv6_vpn) {
3110 flog_err(EC_BGP_ATTRIBUTE_REPEATED,
3111 "Prefix SID SRv6 VPN field repeated");
3112 return bgp_attr_malformed(
3113 args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
3114 }
340594a9 3115 attr->srv6_vpn = XCALLOC(MTYPE_BGP_SRV6_VPN,
e496b420 3116 sizeof(struct bgp_attr_srv6_vpn));
e496b420
HS
3117 attr->srv6_vpn->sid_flags = sid_flags;
3118 sid_copy(&attr->srv6_vpn->sid, &ipv6_sid);
b83127e1 3119 attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
e496b420
HS
3120 }
3121
3122 /* Placeholder code for the SRv6 L3 Service type */
3123 else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
73604f82
RS
3124 if (STREAM_READABLE(peer->curr) < length) {
3125 flog_err(
3126 EC_BGP_ATTR_LEN,
3127 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3128 length, STREAM_READABLE(peer->curr));
e496b420
HS
3129 return bgp_attr_malformed(args,
3130 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3131 args->total);
3132 }
3133
73604f82
RS
3134 /* ignore reserved */
3135 stream_getc(peer->curr);
e496b420 3136
73604f82 3137 return bgp_attr_srv6_service(args);
e496b420
HS
3138 }
3139
3140 /* Placeholder code for Unsupported TLV */
3141 else {
f69aeb76
QY
3142
3143 if (STREAM_READABLE(peer->curr) < length) {
3144 flog_err(
3145 EC_BGP_ATTR_LEN,
6cde4b45 3146 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
f69aeb76
QY
3147 length, STREAM_READABLE(peer->curr));
3148 return bgp_attr_malformed(
3149 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3150 args->total);
3151 }
3152
c6ca155d
HS
3153 if (bgp_debug_update(peer, NULL, NULL, 1))
3154 zlog_debug(
3155 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3156 peer->host, type);
f69aeb76
QY
3157
3158 stream_forward_getp(peer->curr, length);
c6ca155d
HS
3159 }
3160
d62a17ae 3161 return BGP_ATTR_PARSE_PROCEED;
6cf48acc
VV
3162}
3163
30adbd4e
DS
3164/* Prefix SID attribute
3165 * draft-ietf-idr-bgp-prefix-sid-05
3166 */
79288e4c 3167enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
30adbd4e
DS
3168{
3169 struct peer *const peer = args->peer;
3170 struct attr *const attr = args->attr;
79288e4c 3171 enum bgp_attr_parse_ret ret;
30adbd4e
DS
3172
3173 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
3174
f69aeb76
QY
3175 uint8_t type;
3176 uint16_t length;
3177 size_t headersz = sizeof(type) + sizeof(length);
38774fc5 3178 size_t psid_parsed_length = 0;
30adbd4e 3179
38774fc5
HS
3180 while (STREAM_READABLE(peer->curr) > 0
3181 && psid_parsed_length < args->length) {
30adbd4e 3182
f69aeb76
QY
3183 if (STREAM_READABLE(peer->curr) < headersz) {
3184 flog_err(
3185 EC_BGP_ATTR_LEN,
3186 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3187 headersz, STREAM_READABLE(peer->curr));
3188 return bgp_attr_malformed(
3189 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3190 args->total);
3191 }
30adbd4e 3192
f69aeb76
QY
3193 type = stream_getc(peer->curr);
3194 length = stream_getw(peer->curr);
30adbd4e 3195
f69aeb76 3196 if (STREAM_READABLE(peer->curr) < length) {
af4c2728 3197 flog_err(
e50f7cfd 3198 EC_BGP_ATTR_LEN,
6cde4b45 3199 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
f69aeb76 3200 length, STREAM_READABLE(peer->curr));
30adbd4e
DS
3201 return bgp_attr_malformed(args,
3202 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3203 args->total);
3204 }
f69aeb76 3205
45a06b11 3206 ret = bgp_attr_psid_sub(type, length, args);
f69aeb76
QY
3207
3208 if (ret != BGP_ATTR_PARSE_PROCEED)
3209 return ret;
38774fc5
HS
3210
3211 psid_parsed_length += length + headersz;
3212
3213 if (psid_parsed_length > args->length) {
3214 flog_err(
3215 EC_BGP_ATTR_LEN,
3efd0893 3216 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
38774fc5
HS
3217 length + headersz, psid_parsed_length - (length + headersz));
3218 return bgp_attr_malformed(
3219 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3220 args->total);
3221 }
30adbd4e
DS
3222 }
3223
3224 return BGP_ATTR_PARSE_PROCEED;
3225}
3226
7fd077aa 3227/* PMSI tunnel attribute (RFC 6514)
3228 * Basic validation checks done here.
3229 */
79288e4c 3230static enum bgp_attr_parse_ret
7fd077aa 3231bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
3232{
3233 struct peer *const peer = args->peer;
3234 struct attr *const attr = args->attr;
3235 const bgp_size_t length = args->length;
d7c0a89a 3236 uint8_t tnl_type;
355f3c11 3237 int attr_parse_len = 2 + BGP_LABEL_BYTES;
7fd077aa 3238
3239 /* Verify that the receiver is expecting "ingress replication" as we
3240 * can only support that.
3241 */
355f3c11 3242 if (length < attr_parse_len) {
1c50c1c0
QY
3243 flog_err(EC_BGP_ATTR_LEN, "Bad PMSI tunnel attribute length %d",
3244 length);
7fd077aa 3245 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3246 args->total);
3247 }
3248 stream_getc(peer->curr); /* Flags */
3249 tnl_type = stream_getc(peer->curr);
3250 if (tnl_type > PMSI_TNLTYPE_MAX) {
e50f7cfd 3251 flog_err(EC_BGP_ATTR_PMSI_TYPE,
1c50c1c0 3252 "Invalid PMSI tunnel attribute type %d", tnl_type);
7fd077aa 3253 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
3254 args->total);
3255 }
3256 if (tnl_type == PMSI_TNLTYPE_INGR_REPL) {
3257 if (length != 9) {
e50f7cfd 3258 flog_err(EC_BGP_ATTR_PMSI_LEN,
1c50c1c0
QY
3259 "Bad PMSI tunnel attribute length %d for IR",
3260 length);
052ea98b 3261 return bgp_attr_malformed(
3262 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3263 args->total);
7fd077aa 3264 }
3265 }
3266
3267 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
2a3f51cf 3268 bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
355f3c11 3269 stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES);
7fd077aa 3270
3271 /* Forward read pointer of input stream. */
355f3c11 3272 stream_forward_getp(peer->curr, length - attr_parse_len);
7fd077aa 3273
3274 return BGP_ATTR_PARSE_PROCEED;
3275}
3276
97a52c82
DA
3277/* AIGP attribute (rfc7311) */
3278static enum bgp_attr_parse_ret bgp_attr_aigp(struct bgp_attr_parser_args *args)
3279{
3280 struct peer *const peer = args->peer;
3281 struct attr *const attr = args->attr;
3282 const bgp_size_t length = args->length;
3283 uint8_t *s = stream_pnt(peer->curr);
3284 uint64_t aigp = 0;
3285
3286 /* If an AIGP attribute is received on a BGP session for which
3287 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3288 * as if it were an unrecognized non-transitive attribute.
3289 * That is, it "MUST be quietly ignored and not passed along to
3290 * other BGP peers".
3291 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3292 * sessions between members of the same BGP Confederation,
3293 * the default value of AIGP_SESSION SHOULD be "enabled".
3294 */
3295 if (peer->sort == BGP_PEER_EBGP &&
3296 !CHECK_FLAG(peer->flags, PEER_FLAG_AIGP)) {
3297 zlog_warn(
3298 "%pBP received AIGP attribute, but eBGP peer do not support it",
3299 peer);
3300 goto aigp_ignore;
3301 }
3302
a5c6a9b1
DA
3303 if (peer->discard_attrs[args->type])
3304 goto aigp_ignore;
3305
97a52c82
DA
3306 if (!bgp_attr_aigp_valid(s, length))
3307 goto aigp_ignore;
3308
3309 /* Extract AIGP Metric TLV */
3310 if (bgp_attr_aigp_get_tlv_metric(s, length, &aigp))
3311 bgp_attr_set_aigp_metric(attr, aigp);
3312
3313aigp_ignore:
3314 stream_forward_getp(peer->curr, length);
3315
a5c6a9b1
DA
3316 if (bgp_debug_update(peer, NULL, NULL, 1))
3317 zlog_debug("%pBP: Ignoring attribute %s", peer,
3318 lookup_msg(attr_str, args->type, NULL));
3319
97a52c82
DA
3320 return BGP_ATTR_PARSE_PROCEED;
3321}
3322
d864dd9e
EB
3323/* OTC attribute. */
3324static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
3325{
3326 struct peer *const peer = args->peer;
3327 struct attr *const attr = args->attr;
3328 const bgp_size_t length = args->length;
3329
3330 /* Length check. */
3331 if (length != 4) {
3332 flog_err(EC_BGP_ATTR_LEN, "OTC attribute length isn't 4 [%u]",
3333 length);
3334 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3335 args->total);
3336 }
3337
a5c6a9b1
DA
3338 if (peer->discard_attrs[args->type])
3339 goto otc_ignore;
3340
d864dd9e 3341 attr->otc = stream_getl(peer->curr);
adc1c459
DA
3342 if (!attr->otc) {
3343 flog_err(EC_BGP_ATTR_MAL_AS_PATH, "OTC attribute value is 0");
3344 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
3345 args->total);
3346 }
d864dd9e
EB
3347
3348 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
3349
3350 return BGP_ATTR_PARSE_PROCEED;
a5c6a9b1
DA
3351
3352otc_ignore:
3353 stream_forward_getp(peer->curr, length);
3354
3355 if (bgp_debug_update(peer, NULL, NULL, 1))
3356 zlog_debug("%pBP: Ignoring attribute %s", peer,
3357 lookup_msg(attr_str, args->type, NULL));
3358
3359 return BGP_ATTR_PARSE_PROCEED;
d864dd9e
EB
3360}
3361
718e3744 3362/* BGP unknown attribute treatment. */
79288e4c
DA
3363static enum bgp_attr_parse_ret
3364bgp_attr_unknown(struct bgp_attr_parser_args *args)
d62a17ae 3365{
3366 bgp_size_t total = args->total;
3367 struct transit *transit;
3368 struct peer *const peer = args->peer;
3369 struct attr *const attr = args->attr;
d7c0a89a
QY
3370 uint8_t *const startp = args->startp;
3371 const uint8_t type = args->type;
3372 const uint8_t flag = args->flags;
d62a17ae 3373 const bgp_size_t length = args->length;
3374
3375 if (bgp_debug_update(peer, NULL, NULL, 1))
3376 zlog_debug(
3377 "%s Unknown attribute is received (type %d, length %d)",
3378 peer->host, type, length);
3379
3380 /* Forward read pointer of input stream. */
424ab01d 3381 stream_forward_getp(peer->curr, length);
d62a17ae 3382
a5c6a9b1
DA
3383 if (peer->discard_attrs[type]) {
3384 if (bgp_debug_update(peer, NULL, NULL, 1))
3385 zlog_debug("%pBP: Ignoring attribute %s", peer,
3386 lookup_msg(attr_str, args->type, NULL));
3387
3388 return BGP_ATTR_PARSE_PROCEED;
3389 }
3390
d62a17ae 3391 /* If any of the mandatory well-known attributes are not recognized,
3392 then the Error Subcode is set to Unrecognized Well-known
3393 Attribute. The Data field contains the unrecognized attribute
3394 (type, length and value). */
3395 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
3396 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_UNREC_ATTR,
3397 args->total);
3398 }
3399
3400 /* Unrecognized non-transitive optional attributes must be quietly
3401 ignored and not passed along to other BGP peers. */
3402 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
3403 return BGP_ATTR_PARSE_PROCEED;
3404
3405 /* If a path with recognized transitive optional attribute is
3406 accepted and passed along to other BGP peers and the Partial bit
3407 in the Attribute Flags octet is set to 1 by some previous AS, it
3408 is not set back to 0 by the current AS. */
3409 SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL);
3410
3411 /* Store transitive attribute to the end of attr->transit. */
04fb21e2
DS
3412 transit = bgp_attr_get_transit(attr);
3413 if (!transit)
3414 transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
d62a17ae 3415
0b04fa0e
DS
3416 transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val,
3417 transit->length + total);
d62a17ae 3418
3419 memcpy(transit->val + transit->length, startp, total);
3420 transit->length += total;
04fb21e2 3421 bgp_attr_set_transit(attr, transit);
d62a17ae 3422
3423 return BGP_ATTR_PARSE_PROCEED;
718e3744 3424}
3425
bb7bef14 3426/* Well-known attribute check. */
d62a17ae 3427static int bgp_attr_check(struct peer *peer, struct attr *attr)
3428{
d7c0a89a 3429 uint8_t type = 0;
d62a17ae 3430
3431 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3432 * empty UPDATE. */
3433 if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
3434 return BGP_ATTR_PARSE_PROCEED;
3435
3436 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3437 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3438 are present, it should. Check for any other attribute being present
3439 instead.
3440 */
404c82d5
PG
3441 if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
3442 CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
d62a17ae 3443 return BGP_ATTR_PARSE_PROCEED;
3444
3445 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
3446 type = BGP_ATTR_ORIGIN;
3447
3448 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
3449 type = BGP_ATTR_AS_PATH;
3450
3451 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3452 * and
3453 * NLRI is empty. We can't easily check NLRI empty here though.
3454 */
3455 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3456 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)))
3457 type = BGP_ATTR_NEXT_HOP;
3458
3459 if (peer->sort == BGP_PEER_IBGP
3460 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
3461 type = BGP_ATTR_LOCAL_PREF;
3462
4ba5a9c5
DA
3463 /* If any of the well-known mandatory attributes are not present
3464 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3465 */
d62a17ae 3466 if (type) {
e50f7cfd 3467 flog_warn(EC_BGP_MISSING_ATTRIBUTE,
559aaa30 3468 "%s Missing well-known attribute %s.", peer->host,
d62a17ae 3469 lookup_msg(attr_str, type, NULL));
4ba5a9c5 3470 return BGP_ATTR_PARSE_WITHDRAW;
d62a17ae 3471 }
3472 return BGP_ATTR_PARSE_PROCEED;
bb7bef14
PJ
3473}
3474
718e3744 3475/* Read attribute of update packet. This function is called from
8b366b9c 3476 bgp_update_receive() in bgp_packet.c. */
79288e4c
DA
3477enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
3478 bgp_size_t size,
3479 struct bgp_nlri *mp_update,
3480 struct bgp_nlri *mp_withdraw)
d62a17ae 3481{
79288e4c 3482 enum bgp_attr_parse_ret ret;
d7c0a89a
QY
3483 uint8_t flag = 0;
3484 uint8_t type = 0;
d62a17ae 3485 bgp_size_t length;
d7c0a89a
QY
3486 uint8_t *startp, *endp;
3487 uint8_t *attr_endp;
3488 uint8_t seen[BGP_ATTR_BITMAP_SIZE];
d62a17ae 3489 /* we need the as4_path only until we have synthesized the as_path with
3490 * it */
3491 /* same goes for as4_aggregator */
3492 struct aspath *as4_path = NULL;
3493 as_t as4_aggregator = 0;
3494 struct in_addr as4_aggregator_addr = {.s_addr = 0};
04fb21e2 3495 struct transit *transit;
d62a17ae 3496
3497 /* Initialize bitmap. */
3498 memset(seen, 0, BGP_ATTR_BITMAP_SIZE);
3499
3500 /* End pointer of BGP attribute. */
3501 endp = BGP_INPUT_PNT(peer) + size;
3502
3503 /* Get attributes to the end of attribute length. */
3504 while (BGP_INPUT_PNT(peer) < endp) {
3505 /* Check remaining length check.*/
3506 if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) {
3507 /* XXX warning: long int format, int arg (arg 5) */
ade6974d 3508 flog_warn(
e50f7cfd 3509 EC_BGP_ATTRIBUTE_TOO_SMALL,
ade6974d
QY
3510 "%s: error BGP attribute length %lu is smaller than min len",
3511 peer->host,
3512 (unsigned long)(endp
3513 - stream_pnt(BGP_INPUT(peer))));
d62a17ae 3514
3515 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3516 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b6a171c7
QY
3517 ret = BGP_ATTR_PARSE_ERROR;
3518 goto done;
d62a17ae 3519 }
718e3744 3520
d62a17ae 3521 /* Fetch attribute flag and type. */
3522 startp = BGP_INPUT_PNT(peer);
3523 /* "The lower-order four bits of the Attribute Flags octet are
3524 unused. They MUST be zero when sent and MUST be ignored when
3525 received." */
3526 flag = 0xF0 & stream_getc(BGP_INPUT(peer));
3527 type = stream_getc(BGP_INPUT(peer));
3528
3529 /* Check whether Extended-Length applies and is in bounds */
3530 if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
3531 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
ade6974d 3532 flog_warn(
e50f7cfd 3533 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
ade6974d
QY
3534 "%s: Extended length set, but just %lu bytes of attr header",
3535 peer->host,
3536 (unsigned long)(endp
3537 - stream_pnt(BGP_INPUT(peer))));
d62a17ae 3538
3539 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3540 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b6a171c7
QY
3541 ret = BGP_ATTR_PARSE_ERROR;
3542 goto done;
d62a17ae 3543 }
718e3744 3544
d62a17ae 3545 /* Check extended attribue length bit. */
3546 if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN))
3547 length = stream_getw(BGP_INPUT(peer));
3548 else
3549 length = stream_getc(BGP_INPUT(peer));
718e3744 3550
d62a17ae 3551 /* If any attribute appears more than once in the UPDATE
3552 message, then the Error Subcode is set to Malformed Attribute
3553 List. */
718e3744 3554
d62a17ae 3555 if (CHECK_BITMAP(seen, type)) {
ade6974d 3556 flog_warn(
e50f7cfd 3557 EC_BGP_ATTRIBUTE_REPEATED,
ade6974d
QY
3558 "%s: error BGP attribute type %d appears twice in a message",
3559 peer->host, type);
718e3744 3560
d62a17ae 3561 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3562 BGP_NOTIFY_UPDATE_MAL_ATTR);
b6a171c7
QY
3563 ret = BGP_ATTR_PARSE_ERROR;
3564 goto done;
d62a17ae 3565 }
3566
3567 /* Set type to bitmap to check duplicate attribute. `type' is
3568 unsigned char so it never overflow bitmap range. */
3569
3570 SET_BITMAP(seen, type);
3571
3572 /* Overflow check. */
3573 attr_endp = BGP_INPUT_PNT(peer) + length;
3574
3575 if (attr_endp > endp) {
ade6974d 3576 flog_warn(
e50f7cfd 3577 EC_BGP_ATTRIBUTE_TOO_LARGE,
ade6974d
QY
3578 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3579 peer->host, type, length, size, attr_endp,
3580 endp);
dacffad4
QY
3581 /*
3582 * RFC 4271 6.3
3583 * If any recognized attribute has an Attribute
3584 * Length that conflicts with the expected length
3585 * (based on the attribute type code), then the
3586 * Error Subcode MUST be set to Attribute Length
3587 * Error. The Data field MUST contain the erroneous
3588 * attribute (type, length, and value).
3589 * ----------
3590 * We do not currently have a good way to determine the
3591 * length of the attribute independent of the length
3592 * received in the message. Instead we send the
3593 * minimum between the amount of data we have and the
3594 * amount specified by the attribute length field.
3595 *
3596 * Instead of directly passing in the packet buffer and
3597 * offset we use the stream_get* functions to read into
3598 * a stack buffer, since they perform bounds checking
3599 * and we are working with untrusted data.
3600 */
ef56aee4 3601 unsigned char ndata[peer->max_packet_size];
dacffad4
QY
3602 memset(ndata, 0x00, sizeof(ndata));
3603 size_t lfl =
3604 CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 2 : 1;
3605 /* Rewind to end of flag field */
763a5d3c 3606 stream_rewind_getp(BGP_INPUT(peer), (1 + lfl));
dacffad4
QY
3607 /* Type */
3608 stream_get(&ndata[0], BGP_INPUT(peer), 1);
3609 /* Length */
3610 stream_get(&ndata[1], BGP_INPUT(peer), lfl);
3611 /* Value */
3612 size_t atl = attr_endp - startp;
3613 size_t ndl = MIN(atl, STREAM_READABLE(BGP_INPUT(peer)));
3614 stream_get(&ndata[lfl + 1], BGP_INPUT(peer), ndl);
3615
d62a17ae 3616 bgp_notify_send_with_data(
3617 peer, BGP_NOTIFY_UPDATE_ERR,
dacffad4
QY
3618 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
3619 ndl + lfl + 1);
3620
b6a171c7
QY
3621 ret = BGP_ATTR_PARSE_ERROR;
3622 goto done;
d62a17ae 3623 }
3624
3625 struct bgp_attr_parser_args attr_args = {
3626 .peer = peer,
3627 .length = length,
3628 .attr = attr,
3629 .type = type,
3630 .flags = flag,
3631 .startp = startp,
3632 .total = attr_endp - startp,
3633 };
3634
3635
3636 /* If any recognized attribute has Attribute Flags that conflict
3637 with the Attribute Type Code, then the Error Subcode is set
3638 to
3639 Attribute Flags Error. The Data field contains the erroneous
3640 attribute (type, length and value). */
3641 if (bgp_attr_flag_invalid(&attr_args)) {
d62a17ae 3642 ret = bgp_attr_malformed(
3643 &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
3644 attr_args.total);
3645 if (ret == BGP_ATTR_PARSE_PROCEED)
3646 continue;
b6a171c7 3647 goto done;
d62a17ae 3648 }
3649
3650 /* OK check attribute and store it's value. */
3651 switch (type) {
3652 case BGP_ATTR_ORIGIN:
3653 ret = bgp_attr_origin(&attr_args);
3654 break;
3655 case BGP_ATTR_AS_PATH:
3656 ret = bgp_attr_aspath(&attr_args);
3657 break;
3658 case BGP_ATTR_AS4_PATH:
3659 ret = bgp_attr_as4_path(&attr_args, &as4_path);
3660 break;
3661 case BGP_ATTR_NEXT_HOP:
3662 ret = bgp_attr_nexthop(&attr_args);
3663 break;
3664 case BGP_ATTR_MULTI_EXIT_DISC:
3665 ret = bgp_attr_med(&attr_args);
3666 break;
3667 case BGP_ATTR_LOCAL_PREF:
3668 ret = bgp_attr_local_pref(&attr_args);
3669 break;
3670 case BGP_ATTR_ATOMIC_AGGREGATE:
3671 ret = bgp_attr_atomic(&attr_args);
3672 break;
3673 case BGP_ATTR_AGGREGATOR:
3674 ret = bgp_attr_aggregator(&attr_args);
3675 break;
3676 case BGP_ATTR_AS4_AGGREGATOR:
3677 ret = bgp_attr_as4_aggregator(&attr_args,
3678 &as4_aggregator,
3679 &as4_aggregator_addr);
3680 break;
3681 case BGP_ATTR_COMMUNITIES:
3682 ret = bgp_attr_community(&attr_args);
3683 break;
3684 case BGP_ATTR_LARGE_COMMUNITIES:
3685 ret = bgp_attr_large_community(&attr_args);
3686 break;
3687 case BGP_ATTR_ORIGINATOR_ID:
3688 ret = bgp_attr_originator_id(&attr_args);
3689 break;
3690 case BGP_ATTR_CLUSTER_LIST:
3691 ret = bgp_attr_cluster_list(&attr_args);
3692 break;
3693 case BGP_ATTR_MP_REACH_NLRI:
3694 ret = bgp_mp_reach_parse(&attr_args, mp_update);
3695 break;
3696 case BGP_ATTR_MP_UNREACH_NLRI:
3697 ret = bgp_mp_unreach_parse(&attr_args, mp_withdraw);
3698 break;
3699 case BGP_ATTR_EXT_COMMUNITIES:
3700 ret = bgp_attr_ext_communities(&attr_args);
3701 break;
1e20238a 3702#ifdef ENABLE_BGP_VNC_ATTR
d62a17ae 3703 case BGP_ATTR_VNC:
65efcfce 3704#endif
d62a17ae 3705 case BGP_ATTR_ENCAP:
3706 ret = bgp_attr_encap(type, peer, length, attr, flag,
3707 startp);
3708 break;
3709 case BGP_ATTR_PREFIX_SID:
45a06b11 3710 ret = bgp_attr_prefix_sid(&attr_args);
d62a17ae 3711 break;
7fd077aa 3712 case BGP_ATTR_PMSI_TUNNEL:
3713 ret = bgp_attr_pmsi_tunnel(&attr_args);
3714 break;
9a659715
PG
3715 case BGP_ATTR_IPV6_EXT_COMMUNITIES:
3716 ret = bgp_attr_ipv6_ext_communities(&attr_args);
3717 break;
d864dd9e
EB
3718 case BGP_ATTR_OTC:
3719 ret = bgp_attr_otc(&attr_args);
3720 break;
97a52c82
DA
3721 case BGP_ATTR_AIGP:
3722 ret = bgp_attr_aigp(&attr_args);
3723 break;
d62a17ae 3724 default:
3725 ret = bgp_attr_unknown(&attr_args);
3726 break;
3727 }
3728
3729 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) {
3730 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3731 BGP_NOTIFY_UPDATE_MAL_ATTR);
3732 ret = BGP_ATTR_PARSE_ERROR;
b6a171c7 3733 goto done;
d62a17ae 3734 }
3735
9b9df989 3736 if (ret == BGP_ATTR_PARSE_EOR) {
b6a171c7 3737 goto done;
9b9df989
DS
3738 }
3739
d62a17ae 3740 if (ret == BGP_ATTR_PARSE_ERROR) {
e50f7cfd 3741 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
559aaa30 3742 "%s: Attribute %s, parse error", peer->host,
d62a17ae 3743 lookup_msg(attr_str, type, NULL));
b6a171c7 3744 goto done;
d62a17ae 3745 }
3746 if (ret == BGP_ATTR_PARSE_WITHDRAW) {
ade6974d 3747 flog_warn(
e50f7cfd 3748 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
d62a17ae 3749 "%s: Attribute %s, parse error - treating as withdrawal",
3750 peer->host, lookup_msg(attr_str, type, NULL));
b6a171c7 3751 goto done;
d62a17ae 3752 }
3753
3754 /* Check the fetched length. */
3755 if (BGP_INPUT_PNT(peer) != attr_endp) {
e50f7cfd 3756 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR,
559aaa30 3757 "%s: BGP attribute %s, fetch error",
d62a17ae 3758 peer->host, lookup_msg(attr_str, type, NULL));
3759 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3760 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b6a171c7
QY
3761 ret = BGP_ATTR_PARSE_ERROR;
3762 goto done;
d62a17ae 3763 }
718e3744 3764 }
d62a17ae 3765
e5d4cda0
HS
3766 /*
3767 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3768 * About Prefix-SID path attribute,
3769 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3770 * may only appear in a BGP Prefix-SID attribute attached to
3771 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3772 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3773 */
3774 if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST)
3775 attr->label_index = BGP_INVALID_LABEL_INDEX;
3776
d62a17ae 3777 /* Check final read pointer is same as end pointer. */
3778 if (BGP_INPUT_PNT(peer) != endp) {
e50f7cfd 3779 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH,
559aaa30 3780 "%s: BGP attribute %s, length mismatch", peer->host,
d62a17ae 3781 lookup_msg(attr_str, type, NULL));
3782 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3783 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b6a171c7
QY
3784
3785 ret = BGP_ATTR_PARSE_ERROR;
3786 goto done;
d62a17ae 3787 }
3788
88f33d66 3789 /*
3790 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3791 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3792 * This is implemented below and will result in a NOTIFICATION. If the
3793 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3794 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3795 * message SHOULD NOT be sent. This is implemented elsewhere.
3796 *
3797 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3798 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3799 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3800 * speaker that receives the message SHOULD ignore this attribute.
3801 */
3802 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3803 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
9738e9aa 3804 if (bgp_attr_nexthop_valid(peer, attr) < 0) {
b6a171c7
QY
3805 ret = BGP_ATTR_PARSE_ERROR;
3806 goto done;
88f33d66 3807 }
3808 }
3809
d62a17ae 3810 /* Check all mandatory well-known attributes are present */
11dbcdd3
DA
3811 ret = bgp_attr_check(peer, attr);
3812 if (ret < 0)
b6a171c7 3813 goto done;
d62a17ae 3814
3815 /*
3816 * At this place we can see whether we got AS4_PATH and/or
3817 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3818 * We can not do this before we've read all attributes because
3819 * the as4 handling does not say whether AS4_PATH has to be sent
3820 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3821 * in relationship to AGGREGATOR.
3822 * So, to be defensive, we are not relying on any order and read
3823 * all attributes first, including these 32bit ones, and now,
3824 * afterwards, we look what and if something is to be done for as4.
3825 *
3826 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3827 * MP_UNREACH_NLRI.
3828 */
3829 /* actually... this doesn't ever return failure currently, but
3830 * better safe than sorry */
3831 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))
3832 && bgp_attr_munge_as4_attrs(peer, attr, as4_path, as4_aggregator,
3833 &as4_aggregator_addr)) {
3834 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3835 BGP_NOTIFY_UPDATE_MAL_ATTR);
b6a171c7
QY
3836 ret = BGP_ATTR_PARSE_ERROR;
3837 goto done;
d62a17ae 3838 }
3839
d62a17ae 3840 /*
3841 * Finally do the checks on the aspath we did not do yet
3842 * because we waited for a potentially synthesized aspath.
3843 */
3844 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
3845 ret = bgp_attr_aspath_check(peer, attr);
3846 if (ret != BGP_ATTR_PARSE_PROCEED)
b6a171c7 3847 goto done;
d62a17ae 3848 }
718e3744 3849
b6a171c7 3850 ret = BGP_ATTR_PARSE_PROCEED;
b6a171c7 3851done:
5e0e9c09 3852
b6a171c7
QY
3853 /*
3854 * At this stage, we have done all fiddling with as4, and the
3855 * resulting info is in attr->aggregator resp. attr->aspath so
3856 * we can chuck as4_aggregator and as4_path alltogether in order
3857 * to save memory
3858 */
b7b3e63c
DA
3859 /*
3860 * unintern - it is in the hash
3861 * The flag that we got this is still there, but that
3862 * does not do any trouble
3863 */
3864 aspath_unintern(&as4_path);
b6a171c7 3865
04fb21e2 3866 transit = bgp_attr_get_transit(attr);
b6a171c7
QY
3867 if (ret != BGP_ATTR_PARSE_ERROR) {
3868 /* Finally intern unknown attribute. */
04fb21e2
DS
3869 if (transit)
3870 bgp_attr_set_transit(attr, transit_intern(transit));
b6a171c7
QY
3871 if (attr->encap_subtlvs)
3872 attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
3873 ENCAP_SUBTLV_TYPE);
1e20238a 3874#ifdef ENABLE_BGP_VNC
91ebf12c
DS
3875 struct bgp_attr_encap_subtlv *vnc_subtlvs =
3876 bgp_attr_get_vnc_subtlvs(attr);
3877
3878 if (vnc_subtlvs)
3879 bgp_attr_set_vnc_subtlvs(
3880 attr,
3881 encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
5e0e9c09
QY
3882#endif
3883 } else {
04fb21e2
DS
3884 if (transit) {
3885 transit_free(transit);
3886 bgp_attr_set_transit(attr, NULL);
5e0e9c09
QY
3887 }
3888
3889 bgp_attr_flush_encap(attr);
3890 };
3891
3892 /* Sanity checks */
04fb21e2
DS
3893 transit = bgp_attr_get_transit(attr);
3894 if (transit)
3895 assert(transit->refcnt > 0);
d62a17ae 3896 if (attr->encap_subtlvs)
5e0e9c09 3897 assert(attr->encap_subtlvs->refcnt > 0);
1e20238a 3898#ifdef ENABLE_BGP_VNC
91ebf12c
DS
3899 struct bgp_attr_encap_subtlv *vnc_subtlvs =
3900 bgp_attr_get_vnc_subtlvs(attr);
3901
3902 if (vnc_subtlvs)
3903 assert(vnc_subtlvs->refcnt > 0);
bede7744 3904#endif
718e3744 3905
b6a171c7 3906 return ret;
d62a17ae 3907}
3908
f4bd90c5
LK
3909/*
3910 * Extract the tunnel type from extended community
3911 */
3912void bgp_attr_extcom_tunnel_type(struct attr *attr,
fa346686 3913 bgp_encap_types *tunnel_type)
f4bd90c5
LK
3914{
3915 struct ecommunity *ecom;
f6e07e1b
DS
3916 uint32_t i;
3917
f4bd90c5 3918 if (!attr)
fa346686 3919 return;
f4bd90c5 3920
b53e67a3 3921 ecom = bgp_attr_get_ecommunity(attr);
f4bd90c5 3922 if (!ecom || !ecom->size)
fa346686 3923 return;
f4bd90c5
LK
3924
3925 for (i = 0; i < ecom->size; i++) {
3926 uint8_t *pnt;
3927 uint8_t type, sub_type;
3928
3929 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
3930 type = pnt[0];
3931 sub_type = pnt[1];
3932 if (!(type == ECOMMUNITY_ENCODE_OPAQUE &&
3933 sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP))
3934 continue;
3935 *tunnel_type = ((pnt[6] << 8) | pnt[7]);
fa346686 3936 return;
f4bd90c5
LK
3937 }
3938
fa346686 3939 return;
f4bd90c5
LK
3940}
3941
d62a17ae 3942size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
3943 safi_t safi, struct bpacket_attr_vec_arr *vecarr,
3944 struct attr *attr)
3945{
3946 size_t sizep;
617975d1
DS
3947 iana_afi_t pkt_afi = IANA_AFI_IPV4;
3948 iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
d62a17ae 3949 afi_t nh_afi;
3950
3951 /* Set extended bit always to encode the attribute length as 2 bytes */
3952 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
3953 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
3954 sizep = stream_get_endp(s);
3955 stream_putw(s, 0); /* Marker: Attribute length. */
3956
3957
3958 /* Convert AFI, SAFI to values for packet. */
3959 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
3960
3961 stream_putw(s, pkt_afi); /* AFI */
3962 stream_putc(s, pkt_safi); /* SAFI */
3963
3964 /* Nexthop AFI */
ce78a6fb 3965 if (afi == AFI_IP
e496b420
HS
3966 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST
3967 || safi == SAFI_MPLS_VPN || safi == SAFI_MULTICAST))
d62a17ae 3968 nh_afi = peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : AFI_IP;
211ee7aa
PG
3969 else if (safi == SAFI_FLOWSPEC)
3970 nh_afi = afi;
d62a17ae 3971 else
3972 nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
3973
3974 /* Nexthop */
3975 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, attr);
3976 switch (nh_afi) {
3977 case AFI_IP:
3978 switch (safi) {
3979 case SAFI_UNICAST:
3980 case SAFI_MULTICAST:
3981 case SAFI_LABELED_UNICAST:
3982 stream_putc(s, 4);
3983 stream_put_ipv4(s, attr->nexthop.s_addr);
3984 break;
3985 case SAFI_MPLS_VPN:
3986 stream_putc(s, 12);
3987 stream_putl(s, 0); /* RD = 0, per RFC */
3988 stream_putl(s, 0);
3989 stream_put(s, &attr->mp_nexthop_global_in, 4);
3990 break;
3991 case SAFI_ENCAP:
3992 case SAFI_EVPN:
3993 stream_putc(s, 4);
3994 stream_put(s, &attr->mp_nexthop_global_in, 4);
3995 break;
7c40bf39 3996 case SAFI_FLOWSPEC:
211ee7aa
PG
3997 if (attr->mp_nexthop_len == 0)
3998 stream_putc(s, 0); /* no nexthop for flowspec */
3999 else {
4000 stream_putc(s, attr->mp_nexthop_len);
4001 stream_put_ipv4(s, attr->nexthop.s_addr);
4002 }
722e8011
DS
4003 break;
4004 case SAFI_UNSPEC:
4005 case SAFI_MAX:
4006 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
d62a17ae 4007 break;
4008 }
4009 break;
4010 case AFI_IP6:
4011 switch (safi) {
4012 case SAFI_UNICAST:
4013 case SAFI_MULTICAST:
4014 case SAFI_LABELED_UNICAST:
4015 case SAFI_EVPN: {
4016 if (attr->mp_nexthop_len
4017 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
4018 stream_putc(s,
4019 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
4020 stream_put(s, &attr->mp_nexthop_global,
4021 IPV6_MAX_BYTELEN);
4022 stream_put(s, &attr->mp_nexthop_local,
4023 IPV6_MAX_BYTELEN);
4024 } else {
4025 stream_putc(s, IPV6_MAX_BYTELEN);
4026 stream_put(s, &attr->mp_nexthop_global,
4027 IPV6_MAX_BYTELEN);
4028 }
4029 } break;
4030 case SAFI_MPLS_VPN: {
4031 if (attr->mp_nexthop_len
d62a17ae 4032 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
4033 stream_putc(s, 48);
4034 stream_putl(s, 0); /* RD = 0, per RFC */
4035 stream_putl(s, 0);
4036 stream_put(s, &attr->mp_nexthop_global,
4037 IPV6_MAX_BYTELEN);
4038 stream_putl(s, 0); /* RD = 0, per RFC */
4039 stream_putl(s, 0);
4040 stream_put(s, &attr->mp_nexthop_local,
4041 IPV6_MAX_BYTELEN);
63e7ddb5
RS
4042 } else {
4043 stream_putc(s, 24);
4044 stream_putl(s, 0); /* RD = 0, per RFC */
4045 stream_putl(s, 0);
4046 stream_put(s, &attr->mp_nexthop_global,
4047 IPV6_MAX_BYTELEN);
d62a17ae 4048 }
4049 } break;
4050 case SAFI_ENCAP:
4051 stream_putc(s, IPV6_MAX_BYTELEN);
4052 stream_put(s, &attr->mp_nexthop_global,
4053 IPV6_MAX_BYTELEN);
4054 break;
7c40bf39 4055 case SAFI_FLOWSPEC:
4056 stream_putc(s, 0); /* no nexthop for flowspec */
722e8011
DS
4057 break;
4058 case SAFI_UNSPEC:
4059 case SAFI_MAX:
4060 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
d62a17ae 4061 break;
4062 }
4063 break;
722e8011 4064 case AFI_L2VPN:
a83da8e1 4065 if (safi != SAFI_FLOWSPEC)
af4c2728 4066 flog_err(
e50f7cfd 4067 EC_BGP_ATTR_NH_SEND_LEN,
14454c9f
DS
4068 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
4069 peer->host, afi, safi, attr->mp_nexthop_len);
d62a17ae 4070 break;
722e8011
DS
4071 case AFI_UNSPEC:
4072 case AFI_MAX:
4073 assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
4074 break;
d62a17ae 4075 }
4076
4077 /* SNPA */
4078 stream_putc(s, 0);
4079 return sizep;
4080}
4081
4082void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
5f040085
DS
4083 const struct prefix *p,
4084 const struct prefix_rd *prd, mpls_label_t *label,
be92fc9f 4085 uint32_t num_labels, bool addpath_capable,
5f040085 4086 uint32_t addpath_tx_id, struct attr *attr)
d62a17ae 4087{
233b1a38
DS
4088 switch (safi) {
4089 case SAFI_UNSPEC:
4090 case SAFI_MAX:
4091 assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
4092 break;
4093 case SAFI_MPLS_VPN:
be92fc9f 4094 if (addpath_capable)
d62a17ae 4095 stream_putl(s, addpath_tx_id);
4096 /* Label, RD, Prefix write. */
4097 stream_putc(s, p->prefixlen + 88);
4098 stream_put(s, label, BGP_LABEL_BYTES);
4099 stream_put(s, prd->val, 8);
4100 stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
233b1a38
DS
4101 break;
4102 case SAFI_EVPN:
4103 if (afi == AFI_L2VPN)
4104 /* EVPN prefix - contents depend on type */
4105 bgp_evpn_encode_prefix(s, p, prd, label, num_labels,
4106 attr, addpath_capable,
4107 addpath_tx_id);
4108 else
4109 assert(!"Add encoding bits here for other AFI's");
4110 break;
4111 case SAFI_LABELED_UNICAST:
d62a17ae 4112 /* Prefix write with label. */
be92fc9f 4113 stream_put_labeled_prefix(s, p, label, addpath_capable,
ec15e1b5 4114 addpath_tx_id);
233b1a38
DS
4115 break;
4116 case SAFI_FLOWSPEC:
f1af8f04
PG
4117 stream_putc(s, p->u.prefix_flowspec.prefixlen);
4118 stream_put(s, (const void *)p->u.prefix_flowspec.ptr,
4119 p->u.prefix_flowspec.prefixlen);
233b1a38
DS
4120 break;
4121
4122 case SAFI_UNICAST:
4123 case SAFI_MULTICAST:
be92fc9f 4124 stream_put_prefix_addpath(s, p, addpath_capable, addpath_tx_id);
233b1a38
DS
4125 break;
4126 case SAFI_ENCAP:
4127 assert(!"Please add proper encoding of SAFI_ENCAP");
4128 break;
4129 }
d62a17ae 4130}
4131
5f040085
DS
4132size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
4133 const struct prefix *p)
d62a17ae 4134{
4135 int size = PSIZE(p->prefixlen);
4487f0bd
DS
4136
4137 switch (safi) {
4138 case SAFI_UNSPEC:
4139 case SAFI_MAX:
4140 assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4141 break;
4142 case SAFI_UNICAST:
4143 case SAFI_MULTICAST:
4144 break;
4145 case SAFI_MPLS_VPN:
d62a17ae 4146 size += 88;
4487f0bd
DS
4147 break;
4148 case SAFI_ENCAP:
4149 /* This has to be wrong, but I don't know what to put here */
4150 assert(!"Do we try to use this?");
4151 break;
4152 case SAFI_LABELED_UNICAST:
4195afbf 4153 size += BGP_LABEL_BYTES;
4487f0bd
DS
4154 break;
4155 case SAFI_EVPN:
4156 /*
4157 * TODO: Maximum possible for type-2, type-3 and type-5
4158 */
4159 if (afi == AFI_L2VPN)
4160 size += 232;
4161 else
4162 assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4163 break;
4164 case SAFI_FLOWSPEC:
0a9705a1 4165 size = ((struct prefix_fs *)p)->prefix.prefixlen;
4487f0bd
DS
4166 break;
4167 }
4168
d62a17ae 4169 return size;
8c71e481
PM
4170}
4171
f4c89855 4172/*
65efcfce 4173 * Encodes the tunnel encapsulation attribute,
d62a17ae 4174 * and with ENABLE_BGP_VNC the VNC attribute which uses
65efcfce 4175 * almost the same TLV format
f4c89855 4176 */
d62a17ae 4177static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
4178 struct stream *s, struct attr *attr,
4179 uint8_t attrtype)
4180{
4181 unsigned int attrlenfield = 0;
4182 unsigned int attrhdrlen = 0;
4183 struct bgp_attr_encap_subtlv *subtlvs;
4184 struct bgp_attr_encap_subtlv *st;
4185 const char *attrname;
4186
9d303b37
DL
4187 if (!attr || (attrtype == BGP_ATTR_ENCAP
4188 && (!attr->encap_tunneltype
4189 || attr->encap_tunneltype == BGP_ENCAP_TYPE_MPLS)))
d62a17ae 4190 return;
4191
4192 switch (attrtype) {
f4c89855 4193 case BGP_ATTR_ENCAP:
d62a17ae 4194 attrname = "Tunnel Encap";
4195 subtlvs = attr->encap_subtlvs;
4196 if (subtlvs == NULL) /* nothing to do */
4197 return;
4198 /*
4199 * The tunnel encap attr has an "outer" tlv.
4200 * T = tunneltype,
4201 * L = total length of subtlvs,
4202 * V = concatenated subtlvs.
4203 */
4204 attrlenfield = 2 + 2; /* T + L */
4205 attrhdrlen = 1 + 1; /* subTLV T + L */
4206 break;
f4c89855 4207
1e20238a 4208#ifdef ENABLE_BGP_VNC_ATTR
65efcfce 4209 case BGP_ATTR_VNC:
d62a17ae 4210 attrname = "VNC";
91ebf12c 4211 subtlvs = bgp_attr_get_vnc_subtlvs(attr);
d62a17ae 4212 if (subtlvs == NULL) /* nothing to do */
4213 return;
4214 attrlenfield = 0; /* no outer T + L */
4215 attrhdrlen = 2 + 2; /* subTLV T + L */
4216 break;
65efcfce
LB
4217#endif
4218
f4c89855 4219 default:
d62a17ae 4220 assert(0);
4221 }
4222
4223 /* compute attr length */
4224 for (st = subtlvs; st; st = st->next) {
4225 attrlenfield += (attrhdrlen + st->length);
4226 }
4227
4228 if (attrlenfield > 0xffff) {
4229 zlog_info("%s attribute is too long (length=%d), can't send it",
4230 attrname, attrlenfield);
4231 return;
4232 }
4233
4234 if (attrlenfield > 0xff) {
4235 /* 2-octet length field */
996c9314
LB
4236 stream_putc(s,
4237 BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4238 | BGP_ATTR_FLAG_EXTLEN);
d62a17ae 4239 stream_putc(s, attrtype);
4240 stream_putw(s, attrlenfield & 0xffff);
4241 } else {
4242 /* 1-octet length field */
4243 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL);
4244 stream_putc(s, attrtype);
4245 stream_putc(s, attrlenfield & 0xff);
4246 }
4247
4248 if (attrtype == BGP_ATTR_ENCAP) {
4249 /* write outer T+L */
4250 stream_putw(s, attr->encap_tunneltype);
4251 stream_putw(s, attrlenfield - 4);
4252 }
4253
4254 /* write each sub-tlv */
4255 for (st = subtlvs; st; st = st->next) {
4256 if (attrtype == BGP_ATTR_ENCAP) {
4257 stream_putc(s, st->type);
4258 stream_putc(s, st->length);
1e20238a 4259#ifdef ENABLE_BGP_VNC
d62a17ae 4260 } else {
4261 stream_putw(s, st->type);
4262 stream_putw(s, st->length);
65efcfce 4263#endif
d62a17ae 4264 }
4265 stream_put(s, st->value, st->length);
4266 }
f4c89855 4267}
f4c89855 4268
d62a17ae 4269void bgp_packet_mpattr_end(struct stream *s, size_t sizep)
8c71e481 4270{
d62a17ae 4271 /* Set MP attribute length. Don't count the (2) bytes used to encode
4272 the attr length */
4273 stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2);
8c71e481
PM
4274}
4275
3dc339cd 4276static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
6b5a72a3
DA
4277{
4278 if (!BGP_AS_IS_PRIVATE(peer->local_as)
4279 || (BGP_AS_IS_PRIVATE(peer->local_as)
4280 && !CHECK_FLAG(peer->af_flags[afi][safi],
4281 PEER_FLAG_REMOVE_PRIVATE_AS)
4282 && !CHECK_FLAG(peer->af_flags[afi][safi],
4283 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
4284 && !CHECK_FLAG(peer->af_flags[afi][safi],
4285 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
4286 && !CHECK_FLAG(peer->af_flags[afi][safi],
4287 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)))
3dc339cd
DA
4288 return true;
4289 return false;
6b5a72a3
DA
4290}
4291
718e3744 4292/* Make attribute packet. */
d62a17ae 4293bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
4294 struct stream *s, struct attr *attr,
4295 struct bpacket_attr_vec_arr *vecarr,
4296 struct prefix *p, afi_t afi, safi_t safi,
4297 struct peer *from, struct prefix_rd *prd,
d7c0a89a 4298 mpls_label_t *label, uint32_t num_labels,
97a52c82
DA
4299 bool addpath_capable, uint32_t addpath_tx_id,
4300 struct bgp_path_info *bpi)
d62a17ae 4301{
4302 size_t cp;
4303 size_t aspath_sizep;
4304 struct aspath *aspath;
4305 int send_as4_path = 0;
4306 int send_as4_aggregator = 0;
8cff42ad
DA
4307 bool use32bit = CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
4308 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV);
d62a17ae 4309
4310 if (!bgp)
4311 bgp = peer->bgp;
4312
4313 /* Remember current pointer. */
4314 cp = stream_get_endp(s);
4315
4316 if (p
4317 && !((afi == AFI_IP && safi == SAFI_UNICAST)
4318 && !peer_cap_enhe(peer, afi, safi))) {
4319 size_t mpattrlen_pos = 0;
4320
4321 mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
4322 vecarr, attr);
996c9314 4323 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
be92fc9f 4324 num_labels, addpath_capable,
996c9314 4325 addpath_tx_id, attr);
d62a17ae 4326 bgp_packet_mpattr_end(s, mpattrlen_pos);
718e3744 4327 }
d62a17ae 4328
4329 /* Origin attribute. */
4330 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4331 stream_putc(s, BGP_ATTR_ORIGIN);
4332 stream_putc(s, 1);
4333 stream_putc(s, attr->origin);
4334
4335 /* AS path attribute. */
4336
4337 /* If remote-peer is EBGP */
4338 if (peer->sort == BGP_PEER_EBGP
4339 && (!CHECK_FLAG(peer->af_flags[afi][safi],
4340 PEER_FLAG_AS_PATH_UNCHANGED)
4341 || attr->aspath->segments == NULL)
4342 && (!CHECK_FLAG(peer->af_flags[afi][safi],
4343 PEER_FLAG_RSERVER_CLIENT))) {
4344 aspath = aspath_dup(attr->aspath);
4345
4346 /* Even though we may not be configured for confederations we
4347 * may have
4348 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4349 aspath = aspath_delete_confed_seq(aspath);
4350
4351 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
4352 /* Stuff our path CONFED_ID on the front */
4353 aspath = aspath_add_seq(aspath, bgp->confed_id);
4354 } else {
4355 if (peer->change_local_as) {
4356 /* If replace-as is specified, we only use the
4357 change_local_as when
4358 advertising routes. */
6b5a72a3
DA
4359 if (!CHECK_FLAG(peer->flags,
4360 PEER_FLAG_LOCAL_AS_REPLACE_AS))
4361 if (bgp_append_local_as(peer, afi,
4362 safi))
4363 aspath = aspath_add_seq(
4364 aspath, peer->local_as);
d62a17ae 4365 aspath = aspath_add_seq(aspath,
4366 peer->change_local_as);
4367 } else {
4368 aspath = aspath_add_seq(aspath, peer->local_as);
4369 }
4370 }
4371 } else if (peer->sort == BGP_PEER_CONFED) {
4372 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4373 * thing */
4374 aspath = aspath_dup(attr->aspath);
4375 aspath = aspath_add_confed_seq(aspath, peer->local_as);
4376 } else
4377 aspath = attr->aspath;
4378
4379 /* If peer is not AS4 capable, then:
4380 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4381 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4382 * segment
4383 * types are in it (i.e. exclude them if they are there)
4384 * AND do this only if there is at least one asnum > 65535 in the
4385 * path!
4386 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4387 * change
4388 * all ASnums > 65535 to BGP_AS_TRANS
4389 */
4390
4391 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4392 stream_putc(s, BGP_ATTR_AS_PATH);
4393 aspath_sizep = stream_get_endp(s);
4394 stream_putw(s, 0);
4395 stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, use32bit));
4396
4397 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4398 * in the path
4399 */
4400 if (!use32bit && aspath_has_as4(aspath))
4401 send_as4_path =
4402 1; /* we'll do this later, at the correct place */
4403
4404 /* Nexthop attribute. */
4405 if (afi == AFI_IP && safi == SAFI_UNICAST
4406 && !peer_cap_enhe(peer, afi, safi)) {
b96306f0
DS
4407 afi_t nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
4408
d62a17ae 4409 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
4410 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4411 stream_putc(s, BGP_ATTR_NEXT_HOP);
4412 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4413 attr);
4414 stream_putc(s, 4);
4415 stream_put_ipv4(s, attr->nexthop.s_addr);
b96306f0
DS
4416 } else if (peer_cap_enhe(from, afi, safi)
4417 || (nh_afi == AFI_IP6)) {
d62a17ae 4418 /*
4419 * Likely this is the case when an IPv4 prefix was
b96306f0
DS
4420 * received with Extended Next-hop capability in this
4421 * or another vrf and is now being advertised to
4422 * non-ENHE peers. Since peer_cap_enhe only checks
4423 * peers in this vrf, also check the nh_afi to catch
4424 * the case where the originator was in another vrf.
d62a17ae 4425 * Setting the mandatory (ipv4) next-hop attribute here
b96306f0
DS
4426 * to enable implicit next-hop self with correct A-F
4427 * (ipv4 address family).
d62a17ae 4428 */
4429 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4430 stream_putc(s, BGP_ATTR_NEXT_HOP);
4431 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4432 NULL);
4433 stream_putc(s, 4);
4434 stream_put_ipv4(s, 0);
4435 }
718e3744 4436 }
d62a17ae 4437
4438 /* MED attribute. */
4439 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)
4440 || bgp->maxmed_active) {
4441 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4442 stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4443 stream_putc(s, 4);
4444 stream_putl(s, (bgp->maxmed_active ? bgp->maxmed_value
4445 : attr->med));
4446 }
4447
4448 /* Local preference. */
4449 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
4450 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4451 stream_putc(s, BGP_ATTR_LOCAL_PREF);
4452 stream_putc(s, 4);
4453 stream_putl(s, attr->local_pref);
4454 }
4455
4456 /* Atomic aggregate. */
4457 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4458 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4459 stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4460 stream_putc(s, 0);
4461 }
4462
4463 /* Aggregator. */
4464 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4465 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4466 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4467 stream_putc(s, BGP_ATTR_AGGREGATOR);
4468
4469 if (use32bit) {
4470 /* AS4 capable peer */
4471 stream_putc(s, 8);
4472 stream_putl(s, attr->aggregator_as);
4473 } else {
4474 /* 2-byte AS peer */
4475 stream_putc(s, 6);
4476
4477 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4478 * used? */
48e1932b 4479 if (attr->aggregator_as > UINT16_MAX) {
d62a17ae 4480 stream_putw(s, BGP_AS_TRANS);
4481
4482 /* we have to send AS4_AGGREGATOR, too.
4483 * we'll do that later in order to send
4484 * attributes in ascending
4485 * order.
4486 */
4487 send_as4_aggregator = 1;
4488 } else
d7c0a89a 4489 stream_putw(s, (uint16_t)attr->aggregator_as);
d62a17ae 4490 }
4491 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4492 }
4493
4494 /* Community attribute. */
4495 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
4496 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
9a706b42
DA
4497 struct community *comm = NULL;
4498
4499 comm = bgp_attr_get_community(attr);
4500 if (comm->size * 4 > 255) {
996c9314
LB
4501 stream_putc(s,
4502 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4503 | BGP_ATTR_FLAG_EXTLEN);
d62a17ae 4504 stream_putc(s, BGP_ATTR_COMMUNITIES);
9a706b42 4505 stream_putw(s, comm->size * 4);
d62a17ae 4506 } else {
996c9314
LB
4507 stream_putc(s,
4508 BGP_ATTR_FLAG_OPTIONAL
4509 | BGP_ATTR_FLAG_TRANS);
d62a17ae 4510 stream_putc(s, BGP_ATTR_COMMUNITIES);
9a706b42 4511 stream_putc(s, comm->size * 4);
4372df71 4512 }
9a706b42 4513 stream_put(s, comm->val, comm->size * 4);
d62a17ae 4514 }
4515
4516 /*
4517 * Large Community attribute.
4518 */
4519 if (CHECK_FLAG(peer->af_flags[afi][safi],
4520 PEER_FLAG_SEND_LARGE_COMMUNITY)
4521 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
1bcf3a96 4522 if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
996c9314
LB
4523 stream_putc(s,
4524 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4525 | BGP_ATTR_FLAG_EXTLEN);
d62a17ae 4526 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
1bcf3a96
DA
4527 stream_putw(s,
4528 lcom_length(bgp_attr_get_lcommunity(attr)));
d62a17ae 4529 } else {
996c9314
LB
4530 stream_putc(s,
4531 BGP_ATTR_FLAG_OPTIONAL
4532 | BGP_ATTR_FLAG_TRANS);
d62a17ae 4533 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
1bcf3a96
DA
4534 stream_putc(s,
4535 lcom_length(bgp_attr_get_lcommunity(attr)));
4372df71 4536 }
1bcf3a96
DA
4537 stream_put(s, bgp_attr_get_lcommunity(attr)->val,
4538 lcom_length(bgp_attr_get_lcommunity(attr)));
d62a17ae 4539 }
4372df71 4540
d62a17ae 4541 /* Route Reflector. */
4542 if (peer->sort == BGP_PEER_IBGP && from
4543 && from->sort == BGP_PEER_IBGP) {
779fee93
DS
4544 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
4545
d62a17ae 4546 /* Originator ID. */
4547 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4548 stream_putc(s, BGP_ATTR_ORIGINATOR_ID);
4549 stream_putc(s, 4);
4550
4551 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
4552 stream_put_in_addr(s, &attr->originator_id);
4553 else
4554 stream_put_in_addr(s, &from->remote_id);
4555
4556 /* Cluster list. */
4557 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4558 stream_putc(s, BGP_ATTR_CLUSTER_LIST);
4559
779fee93
DS
4560 if (cluster) {
4561 stream_putc(s, cluster->length + 4);
d62a17ae 4562 /* If this peer configuration's parent BGP has
4563 * cluster_id. */
4564 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4565 stream_put_in_addr(s, &bgp->cluster_id);
4566 else
4567 stream_put_in_addr(s, &bgp->router_id);
779fee93 4568 stream_put(s, cluster->list, cluster->length);
d62a17ae 4569 } else {
4570 stream_putc(s, 4);
4571 /* If this peer configuration's parent BGP has
4572 * cluster_id. */
4573 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4574 stream_put_in_addr(s, &bgp->cluster_id);
4575 else
4576 stream_put_in_addr(s, &bgp->router_id);
4577 }
4578 }
4372df71 4579
d62a17ae 4580 /* Extended Communities attribute. */
4581 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
4582 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
b53e67a3 4583 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
b17d5444
DA
4584 bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
4585 PEER_FLAG_RSERVER_CLIENT) &&
4586 from &&
4587 CHECK_FLAG(from->af_flags[afi][safi],
4588 PEER_FLAG_RSERVER_CLIENT);
4589
4590 if (peer->sort == BGP_PEER_IBGP ||
4591 peer->sort == BGP_PEER_CONFED || transparent) {
b53e67a3 4592 if (ecomm->size * 8 > 255) {
996c9314
LB
4593 stream_putc(s,
4594 BGP_ATTR_FLAG_OPTIONAL
4595 | BGP_ATTR_FLAG_TRANS
4596 | BGP_ATTR_FLAG_EXTLEN);
d62a17ae 4597 stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
b53e67a3 4598 stream_putw(s, ecomm->size * 8);
d62a17ae 4599 } else {
996c9314
LB
4600 stream_putc(s,
4601 BGP_ATTR_FLAG_OPTIONAL
4602 | BGP_ATTR_FLAG_TRANS);
d62a17ae 4603 stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
b53e67a3 4604 stream_putc(s, ecomm->size * 8);
d62a17ae 4605 }
b53e67a3 4606 stream_put(s, ecomm->val, ecomm->size * 8);
d62a17ae 4607 } else {
d7c0a89a 4608 uint8_t *pnt;
d62a17ae 4609 int tbit;
4610 int ecom_tr_size = 0;
f6e07e1b 4611 uint32_t i;
d62a17ae 4612
b53e67a3
DA
4613 for (i = 0; i < ecomm->size; i++) {
4614 pnt = ecomm->val + (i * 8);
d62a17ae 4615 tbit = *pnt;
4616
4617 if (CHECK_FLAG(tbit,
4618 ECOMMUNITY_FLAG_NON_TRANSITIVE))
4619 continue;
4620
4621 ecom_tr_size++;
4622 }
4623
4624 if (ecom_tr_size) {
4625 if (ecom_tr_size * 8 > 255) {
4626 stream_putc(
4627 s,
4628 BGP_ATTR_FLAG_OPTIONAL
4629 | BGP_ATTR_FLAG_TRANS
4630 | BGP_ATTR_FLAG_EXTLEN);
4631 stream_putc(s,
4632 BGP_ATTR_EXT_COMMUNITIES);
4633 stream_putw(s, ecom_tr_size * 8);
4634 } else {
4635 stream_putc(
4636 s,
4637 BGP_ATTR_FLAG_OPTIONAL
4638 | BGP_ATTR_FLAG_TRANS);
4639 stream_putc(s,
4640 BGP_ATTR_EXT_COMMUNITIES);
4641 stream_putc(s, ecom_tr_size * 8);
4642 }
4643
b53e67a3
DA
4644 for (i = 0; i < ecomm->size; i++) {
4645 pnt = ecomm->val + (i * 8);
d62a17ae 4646 tbit = *pnt;
4647
4648 if (CHECK_FLAG(
4649 tbit,
4650 ECOMMUNITY_FLAG_NON_TRANSITIVE))
4651 continue;
4652
4653 stream_put(s, pnt, 8);
4654 }
4655 }
4656 }
4657 }
4372df71 4658
d62a17ae 4659 /* Label index attribute. */
4660 if (safi == SAFI_LABELED_UNICAST) {
4661 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
d7c0a89a 4662 uint32_t label_index;
d62a17ae 4663
4664 label_index = attr->label_index;
4665
4666 if (label_index != BGP_INVALID_LABEL_INDEX) {
996c9314
LB
4667 stream_putc(s,
4668 BGP_ATTR_FLAG_OPTIONAL
4669 | BGP_ATTR_FLAG_TRANS);
d62a17ae 4670 stream_putc(s, BGP_ATTR_PREFIX_SID);
4671 stream_putc(s, 10);
4672 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
4673 stream_putw(s,
4674 BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
4675 stream_putc(s, 0); // reserved
4676 stream_putw(s, 0); // flags
4677 stream_putl(s, label_index);
4678 }
4372df71 4679 }
d62a17ae 4680 }
4681
e496b420 4682 /* SRv6 Service Information Attribute. */
dbcf19b8 4683 if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN) {
e496b420 4684 if (attr->srv6_l3vpn) {
a3e3b5b0 4685 uint8_t subtlv_len =
a1a51008
RS
4686 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4687 + BGP_ATTR_MIN_LEN
4688 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH;
4689 uint8_t tlv_len = subtlv_len + BGP_ATTR_MIN_LEN + 1;
4690 uint8_t attr_len = tlv_len + BGP_ATTR_MIN_LEN;
e496b420
HS
4691 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4692 | BGP_ATTR_FLAG_TRANS);
4693 stream_putc(s, BGP_ATTR_PREFIX_SID);
a1a51008 4694 stream_putc(s, attr_len);
e496b420 4695 stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE);
a1a51008 4696 stream_putw(s, tlv_len);
a3e3b5b0
RS
4697 stream_putc(s, 0); /* reserved */
4698 stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO);
a1a51008 4699 stream_putw(s, subtlv_len);
e496b420
HS
4700 stream_putc(s, 0); /* reserved */
4701 stream_put(s, &attr->srv6_l3vpn->sid,
4702 sizeof(attr->srv6_l3vpn->sid)); /* sid */
4703 stream_putc(s, 0); /* sid_flags */
05d99980
CS
4704 stream_putw(s,
4705 attr->srv6_l3vpn
4706 ->endpoint_behavior); /* endpoint */
e496b420 4707 stream_putc(s, 0); /* reserved */
a1a51008
RS
4708 stream_putc(
4709 s,
4710 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE);
4711 stream_putw(
4712 s,
4713 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH);
4714 stream_putc(s, attr->srv6_l3vpn->loc_block_len);
4715 stream_putc(s, attr->srv6_l3vpn->loc_node_len);
4716 stream_putc(s, attr->srv6_l3vpn->func_len);
4717 stream_putc(s, attr->srv6_l3vpn->arg_len);
4718 stream_putc(s, attr->srv6_l3vpn->transposition_len);
4719 stream_putc(s, attr->srv6_l3vpn->transposition_offset);
e496b420
HS
4720 } else if (attr->srv6_vpn) {
4721 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4722 | BGP_ATTR_FLAG_TRANS);
4723 stream_putc(s, BGP_ATTR_PREFIX_SID);
4724 stream_putc(s, 22); /* tlv len */
4725 stream_putc(s, BGP_PREFIX_SID_VPN_SID);
4726 stream_putw(s, 0x13); /* tlv len */
4727 stream_putc(s, 0x00); /* reserved */
4728 stream_putc(s, 0x01); /* sid_type */
4729 stream_putc(s, 0x00); /* sif_flags */
4730 stream_put(s, &attr->srv6_vpn->sid,
4731 sizeof(attr->srv6_vpn->sid)); /* sid */
4732 }
4733 }
4734
d62a17ae 4735 if (send_as4_path) {
4736 /* If the peer is NOT As4 capable, AND */
4737 /* there are ASnums > 65535 in path THEN
4738 * give out AS4_PATH */
4739
4740 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4741 * path segments!
4742 * Hm, I wonder... confederation things *should* only be at
4743 * the beginning of an aspath, right? Then we should use
4744 * aspath_delete_confed_seq for this, because it is already
4745 * there! (JK)
4746 * Folks, talk to me: what is reasonable here!?
4747 */
4748 aspath = aspath_delete_confed_seq(aspath);
4749
996c9314
LB
4750 stream_putc(s,
4751 BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4752 | BGP_ATTR_FLAG_EXTLEN);
d62a17ae 4753 stream_putc(s, BGP_ATTR_AS4_PATH);
4754 aspath_sizep = stream_get_endp(s);
4755 stream_putw(s, 0);
4756 stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, 1));
4757 }
4758
4759 if (aspath != attr->aspath)
4760 aspath_free(aspath);
4761
4762 if (send_as4_aggregator) {
4763 /* send AS4_AGGREGATOR, at this place */
4764 /* this section of code moved here in order to ensure the
4765 * correct
4766 * *ascending* order of attributes
4767 */
4768 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4769 stream_putc(s, BGP_ATTR_AS4_AGGREGATOR);
4770 stream_putc(s, 8);
4771 stream_putl(s, attr->aggregator_as);
4772 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4773 }
4774
4775 if (((afi == AFI_IP || afi == AFI_IP6)
4776 && (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
4777 || (afi == AFI_L2VPN && safi == SAFI_EVPN)) {
4778 /* Tunnel Encap attribute */
4779 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
65efcfce 4780
1e20238a 4781#ifdef ENABLE_BGP_VNC_ATTR
d62a17ae 4782 /* VNC attribute */
4783 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC);
65efcfce 4784#endif
d62a17ae 4785 }
587ff0fd 4786
a21bd7a3
DW
4787 /* PMSI Tunnel */
4788 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
4789 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4790 stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
4791 stream_putc(s, 9); // Length
4792 stream_putc(s, 0); // Flags
2a3f51cf 4793 stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr));
996c9314
LB
4794 stream_put(s, &(attr->label),
4795 BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
30d85a30
LB
4796 stream_put_ipv4(s, attr->nexthop.s_addr);
4797 // Unicast tunnel endpoint IP address
a21bd7a3
DW
4798 }
4799
d864dd9e
EB
4800 /* OTC */
4801 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
4802 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4803 stream_putc(s, BGP_ATTR_OTC);
4804 stream_putc(s, 4);
4805 stream_putl(s, attr->otc);
4806 }
4807
97a52c82 4808 /* AIGP */
af9aee79 4809 if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
97a52c82
DA
4810 (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
4811 peer->sort != BGP_PEER_EBGP)) {
4812 /* At the moment only AIGP Metric TLV exists for AIGP
4813 * attribute. If more comes in, do not forget to update
4814 * attr_len variable to include new ones.
4815 */
4816 uint8_t attr_len = BGP_AIGP_TLV_METRIC_LEN;
4817
4818 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4819 stream_putc(s, BGP_ATTR_AIGP);
4820 stream_putc(s, attr_len);
4821 stream_put_bgp_aigp_tlv_metric(s, bpi);
4822 }
4823
d62a17ae 4824 /* Unknown transit attribute. */
04fb21e2
DS
4825 struct transit *transit = bgp_attr_get_transit(attr);
4826
4827 if (transit)
4828 stream_put(s, transit->val, transit->length);
718e3744 4829
d62a17ae 4830 /* Return total size of attribute. */
4831 return stream_get_endp(s) - cp;
718e3744 4832}
4833
d62a17ae 4834size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
718e3744 4835{
d62a17ae 4836 unsigned long attrlen_pnt;
617975d1
DS
4837 iana_afi_t pkt_afi = IANA_AFI_IPV4;
4838 iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
718e3744 4839
d62a17ae 4840 /* Set extended bit always to encode the attribute length as 2 bytes */
4841 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
4842 stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI);
718e3744 4843
d62a17ae 4844 attrlen_pnt = stream_get_endp(s);
4845 stream_putw(s, 0); /* Length of this attribute. */
718e3744 4846
d62a17ae 4847 /* Convert AFI, SAFI to values for packet. */
4848 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
9cabb64b 4849
d62a17ae 4850 stream_putw(s, pkt_afi);
4851 stream_putc(s, pkt_safi);
9cabb64b 4852
d62a17ae 4853 return attrlen_pnt;
8c71e481 4854}
718e3744 4855
5f040085
DS
4856void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
4857 afi_t afi, safi_t safi,
4858 const struct prefix_rd *prd,
d7c0a89a 4859 mpls_label_t *label, uint32_t num_labels,
be92fc9f 4860 bool addpath_capable, uint32_t addpath_tx_id,
b57ba6d2 4861 struct attr *attr)
8c71e481 4862{
d87c526b 4863 uint8_t wlabel[4] = {0x80, 0x00, 0x00};
cd1964ff 4864
b57ba6d2 4865 if (safi == SAFI_LABELED_UNICAST) {
d62a17ae 4866 label = (mpls_label_t *)wlabel;
b57ba6d2
MK
4867 num_labels = 1;
4868 }
cd1964ff 4869
d90b788e 4870 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
be92fc9f 4871 addpath_capable, addpath_tx_id, attr);
8c71e481 4872}
718e3744 4873
d62a17ae 4874void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt)
8c71e481 4875{
d62a17ae 4876 bgp_packet_mpattr_end(s, attrlen_pnt);
718e3744 4877}
4878
4879/* Initialization of attribute. */
d62a17ae 4880void bgp_attr_init(void)
718e3744 4881{
d62a17ae 4882 aspath_init();
4883 attrhash_init();
4884 community_init();
4885 ecommunity_init();
4886 lcommunity_init();
4887 cluster_init();
4888 transit_init();
4889 encap_init();
e496b420 4890 srv6_init();
718e3744 4891}
4892
d62a17ae 4893void bgp_attr_finish(void)
228da428 4894{
d62a17ae 4895 aspath_finish();
4896 attrhash_finish();
4897 community_finish();
4898 ecommunity_finish();
4899 lcommunity_finish();
4900 cluster_finish();
4901 transit_finish();
4902 encap_finish();
e496b420 4903 srv6_finish();
228da428
CC
4904}
4905
718e3744 4906/* Make attribute packet. */
97a52c82 4907void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
bd494ec5 4908 const struct prefix *prefix)
d62a17ae 4909{
4910 unsigned long cp;
4911 unsigned long len;
4912 size_t aspath_lenp;
4913 struct aspath *aspath;
be92fc9f 4914 bool addpath_capable = false;
d7c0a89a 4915 uint32_t addpath_tx_id = 0;
97a52c82 4916 struct attr *attr = bpi->attr;
d62a17ae 4917
4918 /* Remember current pointer. */
4919 cp = stream_get_endp(s);
4920
4921 /* Place holder of length. */
4922 stream_putw(s, 0);
4923
4924 /* Origin attribute. */
4925 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4926 stream_putc(s, BGP_ATTR_ORIGIN);
4927 stream_putc(s, 1);
4928 stream_putc(s, attr->origin);
4929
4930 aspath = attr->aspath;
4931
4932 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4933 stream_putc(s, BGP_ATTR_AS_PATH);
4934 aspath_lenp = stream_get_endp(s);
4935 stream_putw(s, 0);
4936
4937 stream_putw_at(s, aspath_lenp, aspath_put(s, aspath, 1));
4938
4939 /* Nexthop attribute. */
4940 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4941 if (prefix != NULL && prefix->family != AF_INET6) {
4942 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4943 stream_putc(s, BGP_ATTR_NEXT_HOP);
4944 stream_putc(s, 4);
4945 stream_put_ipv4(s, attr->nexthop.s_addr);
718e3744 4946 }
d62a17ae 4947
4948 /* MED attribute. */
4949 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
4950 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4951 stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4952 stream_putc(s, 4);
4953 stream_putl(s, attr->med);
4954 }
4955
4956 /* Local preference. */
4957 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
4958 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4959 stream_putc(s, BGP_ATTR_LOCAL_PREF);
4960 stream_putc(s, 4);
4961 stream_putl(s, attr->local_pref);
4962 }
4963
4964 /* Atomic aggregate. */
4965 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4966 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4967 stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4968 stream_putc(s, 0);
4969 }
4970
4971 /* Aggregator. */
4972 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4973 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4974 stream_putc(s, BGP_ATTR_AGGREGATOR);
4975 stream_putc(s, 8);
4976 stream_putl(s, attr->aggregator_as);
4977 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4978 }
4979
4980 /* Community attribute. */
4981 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
9a706b42
DA
4982 struct community *comm = NULL;
4983
4984 comm = bgp_attr_get_community(attr);
4985 if (comm->size * 4 > 255) {
996c9314
LB
4986 stream_putc(s,
4987 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4988 | BGP_ATTR_FLAG_EXTLEN);
d62a17ae 4989 stream_putc(s, BGP_ATTR_COMMUNITIES);
9a706b42 4990 stream_putw(s, comm->size * 4);
d62a17ae 4991 } else {
996c9314
LB
4992 stream_putc(s,
4993 BGP_ATTR_FLAG_OPTIONAL
4994 | BGP_ATTR_FLAG_TRANS);
d62a17ae 4995 stream_putc(s, BGP_ATTR_COMMUNITIES);
9a706b42 4996 stream_putc(s, comm->size * 4);
d62a17ae 4997 }
9a706b42 4998 stream_put(s, comm->val, comm->size * 4);
d62a17ae 4999 }
5000
5001 /* Large Community attribute. */
5002 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
1bcf3a96 5003 if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
996c9314
LB
5004 stream_putc(s,
5005 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
5006 | BGP_ATTR_FLAG_EXTLEN);
d62a17ae 5007 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
1bcf3a96
DA
5008 stream_putw(s,
5009 lcom_length(bgp_attr_get_lcommunity(attr)));
d62a17ae 5010 } else {
996c9314
LB
5011 stream_putc(s,
5012 BGP_ATTR_FLAG_OPTIONAL
5013 | BGP_ATTR_FLAG_TRANS);
d62a17ae 5014 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
1bcf3a96
DA
5015 stream_putc(s,
5016 lcom_length(bgp_attr_get_lcommunity(attr)));
d62a17ae 5017 }
5018
1bcf3a96
DA
5019 stream_put(s, bgp_attr_get_lcommunity(attr)->val,
5020 lcom_length(bgp_attr_get_lcommunity(attr)));
d62a17ae 5021 }
5022
5023 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
5024 if (prefix != NULL && prefix->family == AF_INET6
5025 && (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
5026 || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)) {
5027 int sizep;
5028
5029 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
5030 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
5031 sizep = stream_get_endp(s);
5032
5033 /* MP header */
5034 stream_putc(s, 0); /* Marker: Attribute length. */
5035 stream_putw(s, AFI_IP6); /* AFI */
5036 stream_putc(s, SAFI_UNICAST); /* SAFI */
5037
5038 /* Next hop */
5039 stream_putc(s, attr->mp_nexthop_len);
5040 stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN);
5041 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
5042 stream_put(s, &attr->mp_nexthop_local,
5043 IPV6_MAX_BYTELEN);
5044
5045 /* SNPA */
5046 stream_putc(s, 0);
5047
5048 /* Prefix */
be92fc9f 5049 stream_put_prefix_addpath(s, prefix, addpath_capable,
d62a17ae 5050 addpath_tx_id);
5051
5052 /* Set MP attribute length. */
5053 stream_putc_at(s, sizep, (stream_get_endp(s) - sizep) - 1);
5054 }
5055
5056 /* Prefix SID */
5057 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
5058 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
996c9314
LB
5059 stream_putc(s,
5060 BGP_ATTR_FLAG_OPTIONAL
5061 | BGP_ATTR_FLAG_TRANS);
d62a17ae 5062 stream_putc(s, BGP_ATTR_PREFIX_SID);
5063 stream_putc(s, 10);
5064 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
5065 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
5066 stream_putc(s, 0); // reserved
5067 stream_putw(s, 0); // flags
5068 stream_putl(s, attr->label_index);
5069 }
5070 }
5071
d864dd9e
EB
5072 /* OTC */
5073 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
5074 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
5075 stream_putc(s, BGP_ATTR_OTC);
5076 stream_putc(s, 4);
5077 stream_putl(s, attr->otc);
5078 }
5079
97a52c82
DA
5080 /* AIGP */
5081 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
5082 /* At the moment only AIGP Metric TLV exists for AIGP
5083 * attribute. If more comes in, do not forget to update
5084 * attr_len variable to include new ones.
5085 */
5086 uint8_t attr_len = BGP_AIGP_TLV_METRIC_LEN;
5087
5088 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
5089 stream_putc(s, BGP_ATTR_AIGP);
5090 stream_putc(s, attr_len);
5091 stream_put_bgp_aigp_tlv_metric(s, bpi);
5092 }
5093
d62a17ae 5094 /* Return total size of attribute. */
5095 len = stream_get_endp(s) - cp - 2;
5096 stream_putw_at(s, cp, len);
718e3744 5097}
a5c6a9b1
DA
5098
5099void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
5100 const char *discard_attrs)
5101{
5102 int i, num_attributes;
5103 char **attributes;
5104 afi_t afi;
5105 safi_t safi;
5106
5107 if (discard_attrs) {
5108 frrstr_split(discard_attrs, " ", &attributes, &num_attributes);
5109
5110 for (i = 0; i < BGP_ATTR_MAX; i++)
5111 peer->discard_attrs[i] = false;
5112
5113 for (i = 0; i < num_attributes; i++) {
5114 uint8_t attr_num = strtoul(attributes[i], NULL, 10);
5115
5116 XFREE(MTYPE_TMP, attributes[i]);
5117
5118 /* Some of the attributes, just can't be ignored. */
5119 if (attr_num == BGP_ATTR_ORIGIN ||
5120 attr_num == BGP_ATTR_AS_PATH ||
5121 attr_num == BGP_ATTR_NEXT_HOP ||
5122 attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
5123 attr_num == BGP_ATTR_MP_REACH_NLRI ||
5124 attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
5125 attr_num == BGP_ATTR_EXT_COMMUNITIES) {
5126 vty_out(vty,
5127 "%% Can't discard path-attribute %s, ignoring.\n",
5128 lookup_msg(attr_str, attr_num, NULL));
5129 continue;
5130 }
5131
5132 /* Ignore local-pref, originator-id, cluster-list only
5133 * for eBGP.
5134 */
5135 if (peer->sort != BGP_PEER_EBGP &&
5136 (attr_num == BGP_ATTR_LOCAL_PREF ||
5137 attr_num == BGP_ATTR_ORIGINATOR_ID ||
5138 attr_num == BGP_ATTR_CLUSTER_LIST)) {
5139 vty_out(vty,
5140 "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
5141 lookup_msg(attr_str, attr_num, NULL));
5142 continue;
5143 }
5144
5145 peer->discard_attrs[attr_num] = true;
5146 }
5147 XFREE(MTYPE_TMP, attributes);
5148
5149 /* Configuring path attributes to be discarded will trigger
5150 * an inbound Route Refresh to ensure that the routing table
5151 * is up to date.
5152 */
5153 FOREACH_AFI_SAFI (afi, safi)
5154 peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
5155 }
5156}