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