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