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