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