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