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