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