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