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