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