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