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