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