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