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