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