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