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