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