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