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