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