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