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