]> git.proxmox.com Git - mirror_frr.git/blame_incremental - bgpd/bgp_attr.c
Merge pull request #10481 from mobash-rasool/pim-doc
[mirror_frr.git] / bgpd / bgp_attr.c
... / ...
CommitLineData
1/* BGP attributes management routines.
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 */
20
21#include <zebra.h>
22
23#include "linklist.h"
24#include "prefix.h"
25#include "memory.h"
26#include "vector.h"
27#include "stream.h"
28#include "log.h"
29#include "hash.h"
30#include "jhash.h"
31#include "queue.h"
32#include "table.h"
33#include "filter.h"
34#include "command.h"
35#include "srv6.h"
36
37#include "bgpd/bgpd.h"
38#include "bgpd/bgp_attr.h"
39#include "bgpd/bgp_route.h"
40#include "bgpd/bgp_aspath.h"
41#include "bgpd/bgp_community.h"
42#include "bgpd/bgp_debug.h"
43#include "bgpd/bgp_errors.h"
44#include "bgpd/bgp_label.h"
45#include "bgpd/bgp_packet.h"
46#include "bgpd/bgp_ecommunity.h"
47#include "bgpd/bgp_lcommunity.h"
48#include "bgpd/bgp_updgrp.h"
49#include "bgpd/bgp_encap_types.h"
50#ifdef ENABLE_BGP_VNC
51#include "bgpd/rfapi/bgp_rfapi_cfg.h"
52#include "bgp_encap_types.h"
53#include "bgp_vnc_types.h"
54#endif
55#include "bgp_evpn.h"
56#include "bgp_flowspec_private.h"
57#include "bgp_mac.h"
58
59/* Attribute strings for logging. */
60static const struct message attr_str[] = {
61 {BGP_ATTR_ORIGIN, "ORIGIN"},
62 {BGP_ATTR_AS_PATH, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST"},
71 {BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI"},
72 {BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI"},
73 {BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES"},
74 {BGP_ATTR_AS4_PATH, "AS4_PATH"},
75 {BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR"},
76 {BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT"},
77 {BGP_ATTR_PMSI_TUNNEL, "PMSI_TUNNEL_ATTRIBUTE"},
78 {BGP_ATTR_ENCAP, "ENCAP"},
79#ifdef ENABLE_BGP_VNC_ATTR
80 {BGP_ATTR_VNC, "VNC"},
81#endif
82 {BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY"},
83 {BGP_ATTR_PREFIX_SID, "PREFIX_SID"},
84 {BGP_ATTR_IPV6_EXT_COMMUNITIES, "IPV6_EXT_COMMUNITIES"},
85 {0}};
86
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}};
95
96static struct hash *cluster_hash;
97
98struct attr_extra *bgp_attr_extra_alloc(void)
99{
100 return XCALLOC(MTYPE_ATTR_EXTRA, sizeof(struct attr_extra));
101}
102
103void bgp_attr_extra_free(struct attr *attr)
104{
105 XFREE(MTYPE_ATTR_EXTRA, attr->extra);
106}
107
108static void *cluster_hash_alloc(void *p)
109{
110 const struct cluster_list *val = (const struct cluster_list *)p;
111 struct cluster_list *cluster;
112
113 cluster = XMALLOC(MTYPE_CLUSTER, sizeof(struct cluster_list));
114 cluster->length = val->length;
115
116 if (cluster->length) {
117 cluster->list = XMALLOC(MTYPE_CLUSTER_VAL, val->length);
118 memcpy(cluster->list, val->list, val->length);
119 } else
120 cluster->list = NULL;
121
122 cluster->refcnt = 0;
123
124 return cluster;
125}
126
127/* Cluster list related functions. */
128static struct cluster_list *cluster_parse(struct in_addr *pnt, int length)
129{
130 struct cluster_list tmp = {};
131 struct cluster_list *cluster;
132
133 tmp.length = length;
134 tmp.list = length == 0 ? NULL : pnt;
135
136 cluster = hash_get(cluster_hash, &tmp, cluster_hash_alloc);
137 cluster->refcnt++;
138 return cluster;
139}
140
141bool cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
142{
143 int i;
144
145 for (i = 0; i < cluster->length / 4; i++)
146 if (cluster->list[i].s_addr == originator.s_addr)
147 return true;
148 return false;
149}
150
151static unsigned int cluster_hash_key_make(const void *p)
152{
153 const struct cluster_list *cluster = p;
154
155 return jhash(cluster->list, cluster->length, 0);
156}
157
158static bool cluster_hash_cmp(const void *p1, const void *p2)
159{
160 const struct cluster_list *cluster1 = p1;
161 const struct cluster_list *cluster2 = p2;
162
163 if (cluster1->list == cluster2->list)
164 return true;
165
166 if (!cluster1->list || !cluster2->list)
167 return false;
168
169 if (cluster1->length != cluster2->length)
170 return false;
171
172 return (memcmp(cluster1->list, cluster2->list, cluster1->length) == 0);
173}
174
175static void cluster_free(struct cluster_list *cluster)
176{
177 XFREE(MTYPE_CLUSTER_VAL, cluster->list);
178 XFREE(MTYPE_CLUSTER, cluster);
179}
180
181static struct cluster_list *cluster_intern(struct cluster_list *cluster)
182{
183 struct cluster_list *find;
184
185 find = hash_get(cluster_hash, cluster, cluster_hash_alloc);
186 find->refcnt++;
187
188 return find;
189}
190
191static void cluster_unintern(struct cluster_list **cluster)
192{
193 if ((*cluster)->refcnt)
194 (*cluster)->refcnt--;
195
196 if ((*cluster)->refcnt == 0) {
197 void *p = hash_release(cluster_hash, *cluster);
198 assert(p == *cluster);
199 cluster_free(*cluster);
200 *cluster = NULL;
201 }
202}
203
204static void cluster_init(void)
205{
206 cluster_hash = hash_create(cluster_hash_key_make, cluster_hash_cmp,
207 "BGP Cluster");
208}
209
210static void cluster_finish(void)
211{
212 hash_clean(cluster_hash, (void (*)(void *))cluster_free);
213 hash_free(cluster_hash);
214 cluster_hash = NULL;
215}
216
217static struct hash *encap_hash = NULL;
218#ifdef ENABLE_BGP_VNC
219static struct hash *vnc_hash = NULL;
220#endif
221static struct hash *srv6_l3vpn_hash;
222static struct hash *srv6_vpn_hash;
223
224struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
225{
226 struct bgp_attr_encap_subtlv *new;
227 struct bgp_attr_encap_subtlv *tail;
228 struct bgp_attr_encap_subtlv *p;
229
230 for (p = orig, tail = new = NULL; p; p = p->next) {
231 int size = sizeof(struct bgp_attr_encap_subtlv) + p->length;
232 if (tail) {
233 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
234 tail = tail->next;
235 } else {
236 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
237 }
238 assert(tail);
239 memcpy(tail, p, size);
240 tail->next = NULL;
241 }
242
243 return new;
244}
245
246static void encap_free(struct bgp_attr_encap_subtlv *p)
247{
248 struct bgp_attr_encap_subtlv *next;
249 while (p) {
250 next = p->next;
251 p->next = NULL;
252 XFREE(MTYPE_ENCAP_TLV, p);
253 p = next;
254 }
255}
256
257void bgp_attr_flush_encap(struct attr *attr)
258{
259 if (!attr)
260 return;
261
262 if (attr->encap_subtlvs) {
263 encap_free(attr->encap_subtlvs);
264 attr->encap_subtlvs = NULL;
265 }
266#ifdef ENABLE_BGP_VNC
267 struct bgp_attr_encap_subtlv *vnc_subtlvs =
268 bgp_attr_get_vnc_subtlvs(attr);
269
270 if (vnc_subtlvs) {
271 encap_free(vnc_subtlvs);
272 bgp_attr_set_vnc_subtlvs(attr, NULL);
273 }
274#endif
275}
276
277/*
278 * Compare encap sub-tlv chains
279 *
280 * 1 = equivalent
281 * 0 = not equivalent
282 *
283 * This algorithm could be made faster if needed
284 */
285static bool encap_same(const struct bgp_attr_encap_subtlv *h1,
286 const struct bgp_attr_encap_subtlv *h2)
287{
288 const struct bgp_attr_encap_subtlv *p;
289 const struct bgp_attr_encap_subtlv *q;
290
291 if (h1 == h2)
292 return true;
293 if (h1 == NULL || h2 == NULL)
294 return false;
295
296 for (p = h1; p; p = p->next) {
297 for (q = h2; q; q = q->next) {
298 if ((p->type == q->type) && (p->length == q->length)
299 && !memcmp(p->value, q->value, p->length)) {
300
301 break;
302 }
303 }
304 if (!q)
305 return false;
306 }
307
308 for (p = h2; p; p = p->next) {
309 for (q = h1; q; q = q->next) {
310 if ((p->type == q->type) && (p->length == q->length)
311 && !memcmp(p->value, q->value, p->length)) {
312
313 break;
314 }
315 }
316 if (!q)
317 return false;
318 }
319
320 return true;
321}
322
323static void *encap_hash_alloc(void *p)
324{
325 /* Encap structure is already allocated. */
326 return p;
327}
328
329typedef enum {
330 ENCAP_SUBTLV_TYPE,
331#ifdef ENABLE_BGP_VNC
332 VNC_SUBTLV_TYPE
333#endif
334} encap_subtlv_type;
335
336static struct bgp_attr_encap_subtlv *
337encap_intern(struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type)
338{
339 struct bgp_attr_encap_subtlv *find;
340 struct hash *hash = encap_hash;
341#ifdef ENABLE_BGP_VNC
342 if (type == VNC_SUBTLV_TYPE)
343 hash = vnc_hash;
344#endif
345
346 find = hash_get(hash, encap, encap_hash_alloc);
347 if (find != encap)
348 encap_free(encap);
349 find->refcnt++;
350
351 return find;
352}
353
354static void encap_unintern(struct bgp_attr_encap_subtlv **encapp,
355 encap_subtlv_type type)
356{
357 struct bgp_attr_encap_subtlv *encap = *encapp;
358 if (encap->refcnt)
359 encap->refcnt--;
360
361 if (encap->refcnt == 0) {
362 struct hash *hash = encap_hash;
363#ifdef ENABLE_BGP_VNC
364 if (type == VNC_SUBTLV_TYPE)
365 hash = vnc_hash;
366#endif
367 hash_release(hash, encap);
368 encap_free(encap);
369 *encapp = NULL;
370 }
371}
372
373static unsigned int encap_hash_key_make(const void *p)
374{
375 const struct bgp_attr_encap_subtlv *encap = p;
376
377 return jhash(encap->value, encap->length, 0);
378}
379
380static bool encap_hash_cmp(const void *p1, const void *p2)
381{
382 return encap_same((const struct bgp_attr_encap_subtlv *)p1,
383 (const struct bgp_attr_encap_subtlv *)p2);
384}
385
386static void encap_init(void)
387{
388 encap_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
389 "BGP Encap Hash");
390#ifdef ENABLE_BGP_VNC
391 vnc_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
392 "BGP VNC Hash");
393#endif
394}
395
396static void encap_finish(void)
397{
398 hash_clean(encap_hash, (void (*)(void *))encap_free);
399 hash_free(encap_hash);
400 encap_hash = NULL;
401#ifdef ENABLE_BGP_VNC
402 hash_clean(vnc_hash, (void (*)(void *))encap_free);
403 hash_free(vnc_hash);
404 vnc_hash = NULL;
405#endif
406}
407
408static bool overlay_index_same(const struct attr *a1, const struct attr *a2)
409{
410 if (!a1 && a2)
411 return false;
412 if (!a2 && a1)
413 return false;
414 if (!a1 && !a2)
415 return true;
416
417 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1),
418 bgp_attr_get_evpn_overlay(a2));
419}
420
421/* Unknown transit attribute. */
422static struct hash *transit_hash;
423
424static void transit_free(struct transit *transit)
425{
426 XFREE(MTYPE_TRANSIT_VAL, transit->val);
427 XFREE(MTYPE_TRANSIT, transit);
428}
429
430static void *transit_hash_alloc(void *p)
431{
432 /* Transit structure is already allocated. */
433 return p;
434}
435
436static struct transit *transit_intern(struct transit *transit)
437{
438 struct transit *find;
439
440 find = hash_get(transit_hash, transit, transit_hash_alloc);
441 if (find != transit)
442 transit_free(transit);
443 find->refcnt++;
444
445 return find;
446}
447
448static void transit_unintern(struct transit **transit)
449{
450 if ((*transit)->refcnt)
451 (*transit)->refcnt--;
452
453 if ((*transit)->refcnt == 0) {
454 hash_release(transit_hash, *transit);
455 transit_free(*transit);
456 *transit = NULL;
457 }
458}
459
460static void *srv6_l3vpn_hash_alloc(void *p)
461{
462 return p;
463}
464
465static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn *l3vpn)
466{
467 XFREE(MTYPE_BGP_SRV6_L3VPN, l3vpn);
468}
469
470static struct bgp_attr_srv6_l3vpn *
471srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn *l3vpn)
472{
473 struct bgp_attr_srv6_l3vpn *find;
474
475 find = hash_get(srv6_l3vpn_hash, l3vpn, srv6_l3vpn_hash_alloc);
476 if (find != l3vpn)
477 srv6_l3vpn_free(l3vpn);
478 find->refcnt++;
479 return find;
480}
481
482static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn **l3vpnp)
483{
484 struct bgp_attr_srv6_l3vpn *l3vpn = *l3vpnp;
485
486 if (l3vpn->refcnt)
487 l3vpn->refcnt--;
488
489 if (l3vpn->refcnt == 0) {
490 hash_release(srv6_l3vpn_hash, l3vpn);
491 srv6_l3vpn_free(l3vpn);
492 *l3vpnp = NULL;
493 }
494}
495
496static void *srv6_vpn_hash_alloc(void *p)
497{
498 return p;
499}
500
501static void srv6_vpn_free(struct bgp_attr_srv6_vpn *vpn)
502{
503 XFREE(MTYPE_BGP_SRV6_VPN, vpn);
504}
505
506static struct bgp_attr_srv6_vpn *srv6_vpn_intern(struct bgp_attr_srv6_vpn *vpn)
507{
508 struct bgp_attr_srv6_vpn *find;
509
510 find = hash_get(srv6_vpn_hash, vpn, srv6_vpn_hash_alloc);
511 if (find != vpn)
512 srv6_vpn_free(vpn);
513 find->refcnt++;
514 return find;
515}
516
517static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn **vpnp)
518{
519 struct bgp_attr_srv6_vpn *vpn = *vpnp;
520
521 if (vpn->refcnt)
522 vpn->refcnt--;
523
524 if (vpn->refcnt == 0) {
525 hash_release(srv6_vpn_hash, vpn);
526 srv6_vpn_free(vpn);
527 *vpnp = NULL;
528 }
529}
530
531static uint32_t srv6_l3vpn_hash_key_make(const void *p)
532{
533 const struct bgp_attr_srv6_l3vpn *l3vpn = p;
534 uint32_t key = 0;
535
536 key = jhash(&l3vpn->sid, 16, key);
537 key = jhash_1word(l3vpn->sid_flags, key);
538 key = jhash_1word(l3vpn->endpoint_behavior, key);
539 key = jhash_1word(l3vpn->loc_block_len, key);
540 key = jhash_1word(l3vpn->loc_node_len, key);
541 key = jhash_1word(l3vpn->func_len, key);
542 key = jhash_1word(l3vpn->arg_len, key);
543 key = jhash_1word(l3vpn->transposition_len, key);
544 key = jhash_1word(l3vpn->transposition_offset, key);
545 return key;
546}
547
548static bool srv6_l3vpn_hash_cmp(const void *p1, const void *p2)
549{
550 const struct bgp_attr_srv6_l3vpn *l3vpn1 = p1;
551 const struct bgp_attr_srv6_l3vpn *l3vpn2 = p2;
552
553 return sid_same(&l3vpn1->sid, &l3vpn2->sid)
554 && l3vpn1->sid_flags == l3vpn2->sid_flags
555 && l3vpn1->endpoint_behavior == l3vpn2->endpoint_behavior
556 && l3vpn1->loc_block_len == l3vpn2->loc_block_len
557 && l3vpn1->loc_node_len == l3vpn2->loc_node_len
558 && l3vpn1->func_len == l3vpn2->func_len
559 && l3vpn1->arg_len == l3vpn2->arg_len
560 && l3vpn1->transposition_len == l3vpn2->transposition_len
561 && l3vpn1->transposition_offset == l3vpn2->transposition_offset;
562}
563
564static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn *h1,
565 const struct bgp_attr_srv6_l3vpn *h2)
566{
567 if (h1 == h2)
568 return true;
569 else if (h1 == NULL || h2 == NULL)
570 return false;
571 else
572 return srv6_l3vpn_hash_cmp((const void *)h1, (const void *)h2);
573}
574
575static unsigned int srv6_vpn_hash_key_make(const void *p)
576{
577 const struct bgp_attr_srv6_vpn *vpn = p;
578 uint32_t key = 0;
579
580 key = jhash(&vpn->sid, 16, key);
581 key = jhash_1word(vpn->sid_flags, key);
582 return key;
583}
584
585static bool srv6_vpn_hash_cmp(const void *p1, const void *p2)
586{
587 const struct bgp_attr_srv6_vpn *vpn1 = p1;
588 const struct bgp_attr_srv6_vpn *vpn2 = p2;
589
590 return sid_same(&vpn1->sid, &vpn2->sid)
591 && vpn1->sid_flags == vpn2->sid_flags;
592}
593
594static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn *h1,
595 const struct bgp_attr_srv6_vpn *h2)
596{
597 if (h1 == h2)
598 return true;
599 else if (h1 == NULL || h2 == NULL)
600 return false;
601 else
602 return srv6_vpn_hash_cmp((const void *)h1, (const void *)h2);
603}
604
605static void srv6_init(void)
606{
607 srv6_l3vpn_hash =
608 hash_create(srv6_l3vpn_hash_key_make, srv6_l3vpn_hash_cmp,
609 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
610 srv6_vpn_hash = hash_create(srv6_vpn_hash_key_make, srv6_vpn_hash_cmp,
611 "BGP Prefix-SID SRv6-VPN-Service-TLV");
612}
613
614static void srv6_finish(void)
615{
616 hash_clean(srv6_l3vpn_hash, (void (*)(void *))srv6_l3vpn_free);
617 hash_free(srv6_l3vpn_hash);
618 srv6_l3vpn_hash = NULL;
619 hash_clean(srv6_vpn_hash, (void (*)(void *))srv6_vpn_free);
620 hash_free(srv6_vpn_hash);
621 srv6_vpn_hash = NULL;
622}
623
624static unsigned int transit_hash_key_make(const void *p)
625{
626 const struct transit *transit = p;
627
628 return jhash(transit->val, transit->length, 0);
629}
630
631static bool transit_hash_cmp(const void *p1, const void *p2)
632{
633 const struct transit *transit1 = p1;
634 const struct transit *transit2 = p2;
635
636 return (transit1->length == transit2->length
637 && memcmp(transit1->val, transit2->val, transit1->length) == 0);
638}
639
640static void transit_init(void)
641{
642 transit_hash = hash_create(transit_hash_key_make, transit_hash_cmp,
643 "BGP Transit Hash");
644}
645
646static void transit_finish(void)
647{
648 hash_clean(transit_hash, (void (*)(void *))transit_free);
649 hash_free(transit_hash);
650 transit_hash = NULL;
651}
652
653/* Attribute hash routines. */
654static struct hash *attrhash;
655
656unsigned long int attr_count(void)
657{
658 return attrhash->count;
659}
660
661unsigned long int attr_unknown_count(void)
662{
663 return transit_hash->count;
664}
665
666unsigned int attrhash_key_make(const void *p)
667{
668 const struct attr *attr = (struct attr *)p;
669 uint32_t key = 0;
670#define MIX(val) key = jhash_1word(val, key)
671#define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
672
673 MIX3(attr->origin, attr->nexthop.s_addr, attr->med);
674 MIX3(attr->local_pref, attr->aggregator_as,
675 attr->aggregator_addr.s_addr);
676 MIX3(attr->weight, attr->mp_nexthop_global_in.s_addr,
677 attr->originator_id.s_addr);
678 MIX3(attr->tag, attr->label, attr->label_index);
679
680 if (attr->aspath)
681 MIX(aspath_key_make(attr->aspath));
682 if (attr->community)
683 MIX(community_hash_make(attr->community));
684
685 if (attr->lcommunity)
686 MIX(lcommunity_hash_make(attr->lcommunity));
687 if (attr->ecommunity)
688 MIX(ecommunity_hash_make(attr->ecommunity));
689 if (bgp_attr_get_ipv6_ecommunity(attr))
690 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr)));
691 if (bgp_attr_get_cluster(attr))
692 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr)));
693 if (bgp_attr_get_transit(attr))
694 MIX(transit_hash_key_make(bgp_attr_get_transit(attr)));
695 if (attr->encap_subtlvs)
696 MIX(encap_hash_key_make(attr->encap_subtlvs));
697 if (attr->srv6_l3vpn)
698 MIX(srv6_l3vpn_hash_key_make(attr->srv6_l3vpn));
699 if (attr->srv6_vpn)
700 MIX(srv6_vpn_hash_key_make(attr->srv6_vpn));
701#ifdef ENABLE_BGP_VNC
702 struct bgp_attr_encap_subtlv *vnc_subtlvs =
703 bgp_attr_get_vnc_subtlvs(attr);
704 if (vnc_subtlvs)
705 MIX(encap_hash_key_make(vnc_subtlvs));
706#endif
707 MIX(attr->mp_nexthop_len);
708 key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key);
709 key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key);
710 MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance);
711 MIX(attr->rmap_table_id);
712 MIX(attr->nh_type);
713 MIX(attr->bh_type);
714
715 return key;
716}
717
718bool attrhash_cmp(const void *p1, const void *p2)
719{
720 const struct attr *attr1 = p1;
721 const struct attr *attr2 = p2;
722
723 if (attr1->flag == attr2->flag && attr1->origin == attr2->origin
724 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
725 && attr1->aspath == attr2->aspath
726 && attr1->community == attr2->community && attr1->med == attr2->med
727 && attr1->local_pref == attr2->local_pref
728 && attr1->rmap_change_flags == attr2->rmap_change_flags) {
729 if (attr1->aggregator_as == attr2->aggregator_as
730 && attr1->aggregator_addr.s_addr
731 == attr2->aggregator_addr.s_addr
732 && attr1->weight == attr2->weight
733 && attr1->tag == attr2->tag
734 && attr1->label_index == attr2->label_index
735 && attr1->mp_nexthop_len == attr2->mp_nexthop_len
736 && attr1->ecommunity == attr2->ecommunity
737 && bgp_attr_get_ipv6_ecommunity(attr1)
738 == bgp_attr_get_ipv6_ecommunity(attr2)
739 && attr1->lcommunity == attr2->lcommunity
740 && bgp_attr_get_cluster(attr1)
741 == bgp_attr_get_cluster(attr2)
742 && bgp_attr_get_transit(attr1)
743 == bgp_attr_get_transit(attr2)
744 && attr1->rmap_table_id == attr2->rmap_table_id
745 && (attr1->encap_tunneltype == attr2->encap_tunneltype)
746 && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
747#ifdef ENABLE_BGP_VNC
748 && encap_same(bgp_attr_get_vnc_subtlvs(attr1),
749 bgp_attr_get_vnc_subtlvs(attr2))
750#endif
751 && IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
752 &attr2->mp_nexthop_global)
753 && IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
754 &attr2->mp_nexthop_local)
755 && IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
756 &attr2->mp_nexthop_global_in)
757 && IPV4_ADDR_SAME(&attr1->originator_id,
758 &attr2->originator_id)
759 && overlay_index_same(attr1, attr2)
760 && !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t))
761 && attr1->es_flags == attr2->es_flags
762 && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum
763 && attr1->df_pref == attr2->df_pref
764 && attr1->df_alg == attr2->df_alg
765 && attr1->nh_ifindex == attr2->nh_ifindex
766 && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex
767 && attr1->distance == attr2->distance
768 && srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn)
769 && srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn)
770 && attr1->srte_color == attr2->srte_color
771 && attr1->nh_type == attr2->nh_type
772 && attr1->bh_type == attr2->bh_type)
773 return true;
774 }
775
776 return false;
777}
778
779static void attrhash_init(void)
780{
781 attrhash =
782 hash_create(attrhash_key_make, attrhash_cmp, "BGP Attributes");
783}
784
785/*
786 * special for hash_clean below
787 */
788static void attr_vfree(void *attr)
789{
790 bgp_attr_extra_free(attr);
791 XFREE(MTYPE_ATTR, attr);
792}
793
794static void attrhash_finish(void)
795{
796 hash_clean(attrhash, attr_vfree);
797 hash_free(attrhash);
798 attrhash = NULL;
799}
800
801static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty)
802{
803 struct attr *attr = bucket->data;
804 char sid_str[BUFSIZ];
805
806 vty_out(vty, "attr[%ld] nexthop %pI4\n", attr->refcnt, &attr->nexthop);
807
808 sid_str[0] = '\0';
809 if (attr->srv6_l3vpn)
810 inet_ntop(AF_INET6, &attr->srv6_l3vpn->sid, sid_str, BUFSIZ);
811 else if (attr->srv6_vpn)
812 inet_ntop(AF_INET6, &attr->srv6_vpn->sid, sid_str, BUFSIZ);
813
814 vty_out(vty,
815 "\tflags: %" PRIu64" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
816 attr->flag, attr->distance, attr->med, attr->local_pref,
817 attr->origin, attr->weight, attr->label, sid_str);
818}
819
820void attr_show_all(struct vty *vty)
821{
822 hash_iterate(attrhash, (void (*)(struct hash_bucket *,
823 void *))attr_show_all_iterator,
824 vty);
825}
826
827static void *bgp_attr_hash_alloc(void *p)
828{
829 struct attr *val = (struct attr *)p;
830 struct attr *attr;
831
832 attr = XMALLOC(MTYPE_ATTR, sizeof(struct attr));
833 *attr = *val;
834 if (val->encap_subtlvs) {
835 val->encap_subtlvs = NULL;
836 }
837#ifdef ENABLE_BGP_VNC
838 struct bgp_attr_encap_subtlv *vnc_subtlvs =
839 bgp_attr_get_vnc_subtlvs(val);
840
841 if (vnc_subtlvs)
842 bgp_attr_set_vnc_subtlvs(val, NULL);
843#endif
844
845 attr->refcnt = 0;
846 return attr;
847}
848
849/* Internet argument attribute. */
850struct attr *bgp_attr_intern(struct attr *attr)
851{
852 struct attr *find;
853 struct ecommunity *ecomm;
854
855 /* Intern referenced strucutre. */
856 if (attr->aspath) {
857 if (!attr->aspath->refcnt)
858 attr->aspath = aspath_intern(attr->aspath);
859 else
860 attr->aspath->refcnt++;
861 }
862 if (attr->community) {
863 if (!attr->community->refcnt)
864 attr->community = community_intern(attr->community);
865 else
866 attr->community->refcnt++;
867 }
868
869 if (attr->ecommunity) {
870 if (!attr->ecommunity->refcnt)
871 attr->ecommunity = ecommunity_intern(attr->ecommunity);
872 else
873 attr->ecommunity->refcnt++;
874 }
875
876 ecomm = bgp_attr_get_ipv6_ecommunity(attr);
877 if (ecomm) {
878 if (!ecomm->refcnt)
879 bgp_attr_set_ipv6_ecommunity(attr,
880 ecommunity_intern(ecomm));
881 else
882 ecomm->refcnt++;
883 }
884
885 if (attr->lcommunity) {
886 if (!attr->lcommunity->refcnt)
887 attr->lcommunity = lcommunity_intern(attr->lcommunity);
888 else
889 attr->lcommunity->refcnt++;
890 }
891
892 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
893
894 if (cluster) {
895 if (!cluster->refcnt)
896 bgp_attr_set_cluster(attr, cluster_intern(cluster));
897 else
898 cluster->refcnt++;
899 }
900
901 struct transit *transit = bgp_attr_get_transit(attr);
902
903 if (transit) {
904 if (!transit->refcnt)
905 bgp_attr_set_transit(attr, transit_intern(transit));
906 else
907 transit->refcnt++;
908 }
909 if (attr->encap_subtlvs) {
910 if (!attr->encap_subtlvs->refcnt)
911 attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
912 ENCAP_SUBTLV_TYPE);
913 else
914 attr->encap_subtlvs->refcnt++;
915 }
916 if (attr->srv6_l3vpn) {
917 if (!attr->srv6_l3vpn->refcnt)
918 attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
919 else
920 attr->srv6_l3vpn->refcnt++;
921 }
922 if (attr->srv6_vpn) {
923 if (!attr->srv6_vpn->refcnt)
924 attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
925 else
926 attr->srv6_vpn->refcnt++;
927 }
928#ifdef ENABLE_BGP_VNC
929 struct bgp_attr_encap_subtlv *vnc_subtlvs =
930 bgp_attr_get_vnc_subtlvs(attr);
931
932 if (vnc_subtlvs) {
933 if (!vnc_subtlvs->refcnt)
934 bgp_attr_set_vnc_subtlvs(
935 attr,
936 encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
937 else
938 vnc_subtlvs->refcnt++;
939 }
940#endif
941
942 /* At this point, attr only contains intern'd pointers. that means
943 * if we find it in attrhash, it has all the same pointers and we
944 * correctly updated the refcounts on these.
945 * If we don't find it, we need to allocate a one because in all
946 * cases this returns a new reference to a hashed attr, but the input
947 * wasn't on hash. */
948 find = (struct attr *)hash_get(attrhash, attr, bgp_attr_hash_alloc);
949 find->refcnt++;
950
951 return find;
952}
953
954/* Make network statement's attribute. */
955struct attr *bgp_attr_default_set(struct attr *attr, uint8_t origin)
956{
957 memset(attr, 0, sizeof(struct attr));
958
959 attr->origin = origin;
960 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
961 attr->aspath = aspath_empty();
962 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
963 attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
964 attr->tag = 0;
965 attr->label_index = BGP_INVALID_LABEL_INDEX;
966 attr->label = MPLS_INVALID_LABEL;
967 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
968 attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
969
970 return attr;
971}
972
973/* Create the attributes for an aggregate */
974struct attr *bgp_attr_aggregate_intern(
975 struct bgp *bgp, uint8_t origin, struct aspath *aspath,
976 struct community *community, struct ecommunity *ecommunity,
977 struct lcommunity *lcommunity, struct bgp_aggregate *aggregate,
978 uint8_t atomic_aggregate, const struct prefix *p)
979{
980 struct attr attr;
981 struct attr *new;
982 int ret;
983
984 memset(&attr, 0, sizeof(struct attr));
985
986 /* Origin attribute. */
987 attr.origin = origin;
988 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
989
990 /* AS path attribute. */
991 if (aspath)
992 attr.aspath = aspath_intern(aspath);
993 else
994 attr.aspath = aspath_empty();
995 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
996
997 /* Next hop attribute. */
998 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
999
1000 if (community) {
1001 uint32_t gshut = COMMUNITY_GSHUT;
1002
1003 /* If we are not shutting down ourselves and we are
1004 * aggregating a route that contains the GSHUT community we
1005 * need to remove that community when creating the aggregate */
1006 if (!bgp_in_graceful_shutdown(bgp)
1007 && community_include(community, gshut)) {
1008 community_del_val(community, &gshut);
1009 }
1010
1011 attr.community = community;
1012 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1013 }
1014
1015 if (ecommunity) {
1016 attr.ecommunity = ecommunity;
1017 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
1018 }
1019
1020 if (lcommunity) {
1021 attr.lcommunity = lcommunity;
1022 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
1023 }
1024
1025 if (bgp_in_graceful_shutdown(bgp))
1026 bgp_attr_add_gshut_community(&attr);
1027
1028 attr.label_index = BGP_INVALID_LABEL_INDEX;
1029 attr.label = MPLS_INVALID_LABEL;
1030 attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
1031 attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
1032 if (!aggregate->as_set || atomic_aggregate)
1033 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1034 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
1035 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
1036 attr.aggregator_as = bgp->confed_id;
1037 else
1038 attr.aggregator_as = bgp->as;
1039 attr.aggregator_addr = bgp->router_id;
1040 attr.label_index = BGP_INVALID_LABEL_INDEX;
1041 attr.label = MPLS_INVALID_LABEL;
1042
1043 /* Apply route-map */
1044 if (aggregate->rmap.name) {
1045 struct attr attr_tmp = attr;
1046 struct bgp_path_info rmap_path;
1047
1048 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1049 rmap_path.peer = bgp->peer_self;
1050 rmap_path.attr = &attr_tmp;
1051
1052 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1053
1054 ret = route_map_apply(aggregate->rmap.map, p, &rmap_path);
1055
1056 bgp->peer_self->rmap_type = 0;
1057
1058 if (ret == RMAP_DENYMATCH) {
1059 /* Free uninterned attribute. */
1060 bgp_attr_flush(&attr_tmp);
1061
1062 /* Unintern original. */
1063 aspath_unintern(&attr.aspath);
1064 return NULL;
1065 }
1066
1067 if (bgp_in_graceful_shutdown(bgp))
1068 bgp_attr_add_gshut_community(&attr_tmp);
1069
1070 new = bgp_attr_intern(&attr_tmp);
1071 } else {
1072
1073 if (bgp_in_graceful_shutdown(bgp))
1074 bgp_attr_add_gshut_community(&attr);
1075
1076 new = bgp_attr_intern(&attr);
1077 }
1078
1079 /* Always release the 'intern()'ed AS Path. */
1080 aspath_unintern(&attr.aspath);
1081
1082 return new;
1083}
1084
1085/* Unintern just the sub-components of the attr, but not the attr */
1086void bgp_attr_unintern_sub(struct attr *attr)
1087{
1088 struct ecommunity *ecomm;
1089 struct cluster_list *cluster;
1090
1091 /* aspath refcount shoud be decrement. */
1092 if (attr->aspath)
1093 aspath_unintern(&attr->aspath);
1094 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
1095
1096 if (attr->community)
1097 community_unintern(&attr->community);
1098 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
1099
1100 ecommunity_unintern(&attr->ecommunity);
1101 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
1102
1103 ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1104 ecommunity_unintern(&ecomm);
1105 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES));
1106 bgp_attr_set_ipv6_ecommunity(attr, NULL);
1107
1108 if (attr->lcommunity)
1109 lcommunity_unintern(&attr->lcommunity);
1110 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
1111
1112 cluster = bgp_attr_get_cluster(attr);
1113 if (cluster) {
1114 cluster_unintern(&cluster);
1115 bgp_attr_set_cluster(attr, cluster);
1116 }
1117 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
1118
1119 struct transit *transit = bgp_attr_get_transit(attr);
1120
1121 if (transit) {
1122 transit_unintern(&transit);
1123 bgp_attr_set_transit(attr, transit);
1124 }
1125
1126 if (attr->encap_subtlvs)
1127 encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
1128
1129#ifdef ENABLE_BGP_VNC
1130 struct bgp_attr_encap_subtlv *vnc_subtlvs =
1131 bgp_attr_get_vnc_subtlvs(attr);
1132
1133 if (vnc_subtlvs) {
1134 encap_unintern(&vnc_subtlvs, VNC_SUBTLV_TYPE);
1135 bgp_attr_set_vnc_subtlvs(attr, vnc_subtlvs);
1136 }
1137#endif
1138
1139 if (attr->srv6_l3vpn)
1140 srv6_l3vpn_unintern(&attr->srv6_l3vpn);
1141
1142 if (attr->srv6_vpn)
1143 srv6_vpn_unintern(&attr->srv6_vpn);
1144}
1145
1146/*
1147 * We have some show commands that let you experimentally
1148 * apply a route-map. When we apply the route-map
1149 * we are reseting values but not saving them for
1150 * posterity via intern'ing( because route-maps don't
1151 * do that) but at this point in time we need
1152 * to compare the new attr to the old and if the
1153 * routemap has changed it we need to, as Snoop Dog says,
1154 * Drop it like it's hot
1155 */
1156void bgp_attr_undup(struct attr *new, struct attr *old)
1157{
1158 if (new->aspath != old->aspath)
1159 aspath_free(new->aspath);
1160
1161 if (new->community != old->community)
1162 community_free(&new->community);
1163
1164 if (new->ecommunity != old->ecommunity)
1165 ecommunity_free(&new->ecommunity);
1166
1167 if (new->lcommunity != old->lcommunity)
1168 lcommunity_free(&new->lcommunity);
1169
1170 if (new->srv6_l3vpn != old->srv6_l3vpn) {
1171 srv6_l3vpn_free(new->srv6_l3vpn);
1172 new->srv6_l3vpn = NULL;
1173 }
1174
1175 if (new->srv6_vpn != old->srv6_vpn) {
1176 srv6_vpn_free(new->srv6_vpn);
1177 new->srv6_vpn = NULL;
1178 }
1179}
1180
1181/* Free bgp attribute and aspath. */
1182void bgp_attr_unintern(struct attr **pattr)
1183{
1184 struct attr *attr = *pattr;
1185 struct attr *ret;
1186 struct attr tmp;
1187
1188 /* Decrement attribute reference. */
1189 attr->refcnt--;
1190
1191 tmp = *attr;
1192
1193 /* If reference becomes zero then free attribute object. */
1194 if (attr->refcnt == 0) {
1195 ret = hash_release(attrhash, attr);
1196 assert(ret != NULL);
1197 bgp_attr_extra_free(attr);
1198 XFREE(MTYPE_ATTR, attr);
1199 *pattr = NULL;
1200 }
1201
1202 bgp_attr_unintern_sub(&tmp);
1203}
1204
1205void bgp_attr_flush(struct attr *attr)
1206{
1207 struct ecommunity *ecomm;
1208 struct cluster_list *cluster;
1209
1210 if (attr->aspath && !attr->aspath->refcnt) {
1211 aspath_free(attr->aspath);
1212 attr->aspath = NULL;
1213 }
1214 if (attr->community && !attr->community->refcnt)
1215 community_free(&attr->community);
1216 if (attr->ecommunity && !attr->ecommunity->refcnt)
1217 ecommunity_free(&attr->ecommunity);
1218 ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1219 if (ecomm && !ecomm->refcnt)
1220 ecommunity_free(&ecomm);
1221 bgp_attr_set_ipv6_ecommunity(attr, NULL);
1222 if (attr->lcommunity && !attr->lcommunity->refcnt)
1223 lcommunity_free(&attr->lcommunity);
1224
1225 cluster = bgp_attr_get_cluster(attr);
1226 if (cluster && !cluster->refcnt) {
1227 cluster_free(cluster);
1228 bgp_attr_set_cluster(attr, NULL);
1229 }
1230
1231 struct transit *transit = bgp_attr_get_transit(attr);
1232
1233 if (transit && !transit->refcnt) {
1234 transit_free(transit);
1235 bgp_attr_set_transit(attr, NULL);
1236 }
1237 if (attr->encap_subtlvs && !attr->encap_subtlvs->refcnt) {
1238 encap_free(attr->encap_subtlvs);
1239 attr->encap_subtlvs = NULL;
1240 }
1241 if (attr->srv6_l3vpn && !attr->srv6_l3vpn->refcnt) {
1242 srv6_l3vpn_free(attr->srv6_l3vpn);
1243 attr->srv6_l3vpn = NULL;
1244 }
1245 if (attr->srv6_vpn && !attr->srv6_vpn->refcnt) {
1246 srv6_vpn_free(attr->srv6_vpn);
1247 attr->srv6_vpn = NULL;
1248 }
1249#ifdef ENABLE_BGP_VNC
1250 struct bgp_attr_encap_subtlv *vnc_subtlvs =
1251 bgp_attr_get_vnc_subtlvs(attr);
1252
1253 if (vnc_subtlvs && !vnc_subtlvs->refcnt) {
1254 encap_free(vnc_subtlvs);
1255 bgp_attr_set_vnc_subtlvs(attr, NULL);
1256 }
1257#endif
1258}
1259
1260/* Implement draft-scudder-idr-optional-transitive behaviour and
1261 * avoid resetting sessions for malformed attributes which are
1262 * are partial/optional and hence where the error likely was not
1263 * introduced by the sending neighbour.
1264 */
1265static bgp_attr_parse_ret_t
1266bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
1267 bgp_size_t length)
1268{
1269 struct peer *const peer = args->peer;
1270 struct attr *const attr = args->attr;
1271 const uint8_t flags = args->flags;
1272 /* startp and length must be special-cased, as whether or not to
1273 * send the attribute data with the NOTIFY depends on the error,
1274 * the caller therefore signals this with the seperate length argument
1275 */
1276 uint8_t *notify_datap = (length > 0 ? args->startp : NULL);
1277
1278 if (bgp_debug_update(peer, NULL, NULL, 1)) {
1279 char attr_str[BUFSIZ] = {0};
1280
1281 bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1282
1283 zlog_debug("%s: attributes: %s", __func__, attr_str);
1284 }
1285
1286 /* Only relax error handling for eBGP peers */
1287 if (peer->sort != BGP_PEER_EBGP) {
1288 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
1289 notify_datap, length);
1290 return BGP_ATTR_PARSE_ERROR;
1291 }
1292
1293 /* Adjust the stream getp to the end of the attribute, in case we can
1294 * still proceed but the caller hasn't read all the attribute.
1295 */
1296 stream_set_getp(BGP_INPUT(peer),
1297 (args->startp - STREAM_DATA(BGP_INPUT(peer)))
1298 + args->total);
1299
1300 switch (args->type) {
1301 /* where an attribute is relatively inconsequential, e.g. it does not
1302 * affect route selection, and can be safely ignored, then any such
1303 * attributes which are malformed should just be ignored and the route
1304 * processed as normal.
1305 */
1306 case BGP_ATTR_AS4_AGGREGATOR:
1307 case BGP_ATTR_AGGREGATOR:
1308 case BGP_ATTR_ATOMIC_AGGREGATE:
1309 return BGP_ATTR_PARSE_PROCEED;
1310
1311 /* Core attributes, particularly ones which may influence route
1312 * selection, should be treat-as-withdraw.
1313 */
1314 case BGP_ATTR_ORIGIN:
1315 case BGP_ATTR_AS_PATH:
1316 case BGP_ATTR_NEXT_HOP:
1317 case BGP_ATTR_MULTI_EXIT_DISC:
1318 case BGP_ATTR_LOCAL_PREF:
1319 case BGP_ATTR_COMMUNITIES:
1320 case BGP_ATTR_EXT_COMMUNITIES:
1321 case BGP_ATTR_IPV6_EXT_COMMUNITIES:
1322 case BGP_ATTR_LARGE_COMMUNITIES:
1323 case BGP_ATTR_ORIGINATOR_ID:
1324 case BGP_ATTR_CLUSTER_LIST:
1325 return BGP_ATTR_PARSE_WITHDRAW;
1326 case BGP_ATTR_MP_REACH_NLRI:
1327 case BGP_ATTR_MP_UNREACH_NLRI:
1328 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
1329 notify_datap, length);
1330 return BGP_ATTR_PARSE_ERROR;
1331 }
1332
1333 /* Partial optional attributes that are malformed should not cause
1334 * the whole session to be reset. Instead treat it as a withdrawal
1335 * of the routes, if possible.
1336 */
1337 if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)
1338 && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1339 && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
1340 return BGP_ATTR_PARSE_WITHDRAW;
1341
1342 /* default to reset */
1343 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1344}
1345
1346/* Find out what is wrong with the path attribute flag bits and log the error.
1347 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1348 Extended Length. Checking O/T/P bits at once implies, that the attribute
1349 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1350 non-transitive" attribute. */
1351static void
1352bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args,
1353 uint8_t desired_flags /* how RFC says it must be */
1354)
1355{
1356 uint8_t seen = 0, i;
1357 uint8_t real_flags = args->flags;
1358 const uint8_t attr_code = args->type;
1359
1360 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1361 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1362 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
1363 if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1364 != CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
1365 flog_err(EC_BGP_ATTR_FLAG,
1366 "%s attribute must%s be flagged as \"%s\"",
1367 lookup_msg(attr_str, attr_code, NULL),
1368 CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1369 ? ""
1370 : " not",
1371 attr_flag_str[i].str);
1372 seen = 1;
1373 }
1374 if (!seen) {
1375 zlog_debug(
1376 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1377 __func__, lookup_msg(attr_str, attr_code, NULL),
1378 real_flags, desired_flags);
1379 }
1380}
1381
1382/* Required flags for attributes. EXTLEN will be masked off when testing,
1383 * as will PARTIAL for optional+transitive attributes.
1384 */
1385const uint8_t attr_flags_values[] = {
1386 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
1387 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
1388 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
1389 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
1390 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
1391 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
1392 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1393 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1394 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
1395 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1396 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1397 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1398 [BGP_ATTR_EXT_COMMUNITIES] =
1399 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1400 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1401 [BGP_ATTR_AS4_AGGREGATOR] =
1402 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1403 [BGP_ATTR_PMSI_TUNNEL] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1404 [BGP_ATTR_LARGE_COMMUNITIES] =
1405 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1406 [BGP_ATTR_PREFIX_SID] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1407 [BGP_ATTR_IPV6_EXT_COMMUNITIES] =
1408 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1409};
1410static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
1411
1412static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
1413{
1414 uint8_t mask = BGP_ATTR_FLAG_EXTLEN;
1415 const uint8_t flags = args->flags;
1416 const uint8_t attr_code = args->type;
1417
1418 /* there may be attributes we don't know about */
1419 if (attr_code > attr_flags_values_max)
1420 return false;
1421 if (attr_flags_values[attr_code] == 0)
1422 return false;
1423
1424 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1425 * to
1426 * 1."
1427 */
1428 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL, flags)
1429 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS, flags)) {
1430 flog_err(
1431 EC_BGP_ATTR_FLAG,
1432 "%s well-known attributes must have transitive flag set (%x)",
1433 lookup_msg(attr_str, attr_code, NULL), flags);
1434 return true;
1435 }
1436
1437 /* "For well-known attributes and for optional non-transitive
1438 * attributes,
1439 * the Partial bit MUST be set to 0."
1440 */
1441 if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) {
1442 if (!CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)) {
1443 flog_err(EC_BGP_ATTR_FLAG,
1444 "%s well-known attribute must NOT have the partial flag set (%x)",
1445 lookup_msg(attr_str, attr_code, NULL), flags);
1446 return true;
1447 }
1448 if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1449 && !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) {
1450 flog_err(EC_BGP_ATTR_FLAG,
1451 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1452 lookup_msg(attr_str, attr_code, NULL), flags);
1453 return true;
1454 }
1455 }
1456
1457 /* Optional transitive attributes may go through speakers that don't
1458 * reocgnise them and set the Partial bit.
1459 */
1460 if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1461 && CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS))
1462 SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
1463
1464 if ((flags & ~mask) == attr_flags_values[attr_code])
1465 return false;
1466
1467 bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
1468 return true;
1469}
1470
1471/* Get origin attribute of the update message. */
1472static bgp_attr_parse_ret_t bgp_attr_origin(struct bgp_attr_parser_args *args)
1473{
1474 struct peer *const peer = args->peer;
1475 struct attr *const attr = args->attr;
1476 const bgp_size_t length = args->length;
1477
1478 /* If any recognized attribute has Attribute Length that conflicts
1479 with the expected length (based on the attribute type code), then
1480 the Error Subcode is set to Attribute Length Error. The Data
1481 field contains the erroneous attribute (type, length and
1482 value). */
1483 if (length != 1) {
1484 flog_err(EC_BGP_ATTR_LEN,
1485 "Origin attribute length is not one %d", length);
1486 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1487 args->total);
1488 }
1489
1490 /* Fetch origin attribute. */
1491 attr->origin = stream_getc(BGP_INPUT(peer));
1492
1493 /* If the ORIGIN attribute has an undefined value, then the Error
1494 Subcode is set to Invalid Origin Attribute. The Data field
1495 contains the unrecognized attribute (type, length and value). */
1496 if ((attr->origin != BGP_ORIGIN_IGP) && (attr->origin != BGP_ORIGIN_EGP)
1497 && (attr->origin != BGP_ORIGIN_INCOMPLETE)) {
1498 flog_err(EC_BGP_ATTR_ORIGIN,
1499 "Origin attribute value is invalid %d", attr->origin);
1500 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1501 args->total);
1502 }
1503
1504 /* Set oring attribute flag. */
1505 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1506
1507 return 0;
1508}
1509
1510/* Parse AS path information. This function is wrapper of
1511 aspath_parse. */
1512static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
1513{
1514 struct attr *const attr = args->attr;
1515 struct peer *const peer = args->peer;
1516 const bgp_size_t length = args->length;
1517
1518 /*
1519 * peer with AS4 => will get 4Byte ASnums
1520 * otherwise, will get 16 Bit
1521 */
1522 attr->aspath = aspath_parse(
1523 peer->curr, length,
1524 CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1525 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV));
1526
1527 /* In case of IBGP, length will be zero. */
1528 if (!attr->aspath) {
1529 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1530 "Malformed AS path from %s, length is %d", peer->host,
1531 length);
1532 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1533 0);
1534 }
1535
1536 /* Set aspath attribute flag. */
1537 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1538
1539 return BGP_ATTR_PARSE_PROCEED;
1540}
1541
1542static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
1543 struct attr *const attr)
1544{
1545 /* These checks were part of bgp_attr_aspath, but with
1546 * as4 we should to check aspath things when
1547 * aspath synthesizing with as4_path has already taken place.
1548 * Otherwise we check ASPATH and use the synthesized thing, and that is
1549 * not right.
1550 * So do the checks later, i.e. here
1551 */
1552 struct aspath *aspath;
1553
1554 /* Confederation sanity check. */
1555 if ((peer->sort == BGP_PEER_CONFED
1556 && !aspath_left_confed_check(attr->aspath))
1557 || (peer->sort == BGP_PEER_EBGP
1558 && aspath_confed_check(attr->aspath))) {
1559 flog_err(EC_BGP_ATTR_MAL_AS_PATH, "Malformed AS path from %s",
1560 peer->host);
1561 return BGP_ATTR_PARSE_WITHDRAW;
1562 }
1563
1564 /* First AS check for EBGP. */
1565 if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
1566 if (peer->sort == BGP_PEER_EBGP
1567 && !aspath_firstas_check(attr->aspath, peer->as)) {
1568 flog_err(EC_BGP_ATTR_FIRST_AS,
1569 "%s incorrect first AS (must be %u)",
1570 peer->host, peer->as);
1571 return BGP_ATTR_PARSE_WITHDRAW;
1572 }
1573 }
1574
1575 /* Codification of AS 0 Processing */
1576 if (peer->sort == BGP_PEER_EBGP && aspath_check_as_zero(attr->aspath)) {
1577 flog_err(
1578 EC_BGP_ATTR_MAL_AS_PATH,
1579 "Malformed AS path, AS number is 0 in the path from %s",
1580 peer->host);
1581 return BGP_ATTR_PARSE_WITHDRAW;
1582 }
1583
1584 /* local-as prepend */
1585 if (peer->change_local_as
1586 && !CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) {
1587 aspath = aspath_dup(attr->aspath);
1588 aspath = aspath_add_seq(aspath, peer->change_local_as);
1589 aspath_unintern(&attr->aspath);
1590 attr->aspath = aspath_intern(aspath);
1591 }
1592
1593 return BGP_ATTR_PARSE_PROCEED;
1594}
1595
1596/* Parse AS4 path information. This function is another wrapper of
1597 aspath_parse. */
1598static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
1599 struct aspath **as4_path)
1600{
1601 struct peer *const peer = args->peer;
1602 struct attr *const attr = args->attr;
1603 const bgp_size_t length = args->length;
1604
1605 *as4_path = aspath_parse(peer->curr, length, 1);
1606
1607 /* In case of IBGP, length will be zero. */
1608 if (!*as4_path) {
1609 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1610 "Malformed AS4 path from %s, length is %d", peer->host,
1611 length);
1612 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1613 0);
1614 }
1615
1616 /* Set aspath attribute flag. */
1617 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
1618
1619 return BGP_ATTR_PARSE_PROCEED;
1620}
1621
1622/*
1623 * Check that the nexthop attribute is valid.
1624 */
1625bgp_attr_parse_ret_t
1626bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
1627{
1628 in_addr_t nexthop_h;
1629
1630 nexthop_h = ntohl(attr->nexthop.s_addr);
1631 if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h)
1632 || IPV4_CLASS_DE(nexthop_h))
1633 && !BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) {
1634 uint8_t data[7]; /* type(2) + length(1) + nhop(4) */
1635 char buf[INET_ADDRSTRLEN];
1636
1637 inet_ntop(AF_INET, &attr->nexthop.s_addr, buf,
1638 INET_ADDRSTRLEN);
1639 flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s",
1640 buf);
1641 data[0] = BGP_ATTR_FLAG_TRANS;
1642 data[1] = BGP_ATTR_NEXT_HOP;
1643 data[2] = BGP_ATTR_NHLEN_IPV4;
1644 memcpy(&data[3], &attr->nexthop.s_addr, BGP_ATTR_NHLEN_IPV4);
1645 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
1646 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
1647 data, 7);
1648 return BGP_ATTR_PARSE_ERROR;
1649 }
1650
1651 return BGP_ATTR_PARSE_PROCEED;
1652}
1653
1654/* Nexthop attribute. */
1655static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
1656{
1657 struct peer *const peer = args->peer;
1658 struct attr *const attr = args->attr;
1659 const bgp_size_t length = args->length;
1660
1661 /* Check nexthop attribute length. */
1662 if (length != 4) {
1663 flog_err(EC_BGP_ATTR_LEN,
1664 "Nexthop attribute length isn't four [%d]", length);
1665
1666 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1667 args->total);
1668 }
1669
1670 attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
1671 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1672
1673 return BGP_ATTR_PARSE_PROCEED;
1674}
1675
1676/* MED atrribute. */
1677static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args)
1678{
1679 struct peer *const peer = args->peer;
1680 struct attr *const attr = args->attr;
1681 const bgp_size_t length = args->length;
1682
1683 /* Length check. */
1684 if (length != 4) {
1685 flog_err(EC_BGP_ATTR_LEN,
1686 "MED attribute length isn't four [%d]", length);
1687
1688 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1689 args->total);
1690 }
1691
1692 attr->med = stream_getl(peer->curr);
1693
1694 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1695
1696 return BGP_ATTR_PARSE_PROCEED;
1697}
1698
1699/* Local preference attribute. */
1700static bgp_attr_parse_ret_t
1701bgp_attr_local_pref(struct bgp_attr_parser_args *args)
1702{
1703 struct peer *const peer = args->peer;
1704 struct attr *const attr = args->attr;
1705 const bgp_size_t length = args->length;
1706
1707 /* if received from an internal neighbor, it SHALL be considered
1708 * malformed if its length is not equal to 4. If malformed, the
1709 * UPDATE message SHALL be handled using the approach of "treat-as-
1710 * withdraw".
1711 */
1712 if (peer->sort == BGP_PEER_IBGP && length != 4) {
1713 flog_err(EC_BGP_ATTR_LEN,
1714 "LOCAL_PREF attribute length isn't 4 [%u]", length);
1715 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1716 args->total);
1717 }
1718
1719 /* If it is contained in an UPDATE message that is received from an
1720 external peer, then this attribute MUST be ignored by the
1721 receiving speaker. */
1722 if (peer->sort == BGP_PEER_EBGP) {
1723 STREAM_FORWARD_GETP(peer->curr, length);
1724 return BGP_ATTR_PARSE_PROCEED;
1725 }
1726
1727 STREAM_GETL(peer->curr, attr->local_pref);
1728
1729 /* Set the local-pref flag. */
1730 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1731
1732 return BGP_ATTR_PARSE_PROCEED;
1733
1734stream_failure:
1735 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1736 args->total);
1737}
1738
1739/* Atomic aggregate. */
1740static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
1741{
1742 struct attr *const attr = args->attr;
1743 const bgp_size_t length = args->length;
1744
1745 /* Length check. */
1746 if (length != 0) {
1747 flog_err(EC_BGP_ATTR_LEN,
1748 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1749 length);
1750 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1751 args->total);
1752 }
1753
1754 /* Set atomic aggregate flag. */
1755 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1756
1757 return BGP_ATTR_PARSE_PROCEED;
1758}
1759
1760/* Aggregator attribute */
1761static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
1762{
1763 struct peer *const peer = args->peer;
1764 struct attr *const attr = args->attr;
1765 const bgp_size_t length = args->length;
1766 as_t aggregator_as;
1767
1768 int wantedlen = 6;
1769
1770 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1771 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1772 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV))
1773 wantedlen = 8;
1774
1775 if (length != wantedlen) {
1776 flog_err(EC_BGP_ATTR_LEN,
1777 "AGGREGATOR attribute length isn't %u [%u]", wantedlen,
1778 length);
1779 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1780 args->total);
1781 }
1782
1783 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV))
1784 aggregator_as = stream_getl(peer->curr);
1785 else
1786 aggregator_as = stream_getw(peer->curr);
1787
1788 attr->aggregator_as = aggregator_as;
1789 attr->aggregator_addr.s_addr = stream_get_ipv4(peer->curr);
1790
1791 /* Codification of AS 0 Processing */
1792 if (aggregator_as == BGP_AS_ZERO) {
1793 flog_err(EC_BGP_ATTR_LEN,
1794 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1795 peer->host, aspath_print(attr->aspath));
1796
1797 if (bgp_debug_update(peer, NULL, NULL, 1)) {
1798 char attr_str[BUFSIZ] = {0};
1799
1800 bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1801
1802 zlog_debug("%s: attributes: %s", __func__, attr_str);
1803 }
1804 } else {
1805 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
1806 }
1807
1808 return BGP_ATTR_PARSE_PROCEED;
1809}
1810
1811/* New Aggregator attribute */
1812static bgp_attr_parse_ret_t
1813bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
1814 as_t *as4_aggregator_as,
1815 struct in_addr *as4_aggregator_addr)
1816{
1817 struct peer *const peer = args->peer;
1818 struct attr *const attr = args->attr;
1819 const bgp_size_t length = args->length;
1820 as_t aggregator_as;
1821
1822 if (length != 8) {
1823 flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
1824 length);
1825 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1826 0);
1827 }
1828
1829 aggregator_as = stream_getl(peer->curr);
1830
1831 *as4_aggregator_as = aggregator_as;
1832 as4_aggregator_addr->s_addr = stream_get_ipv4(peer->curr);
1833
1834 /* Codification of AS 0 Processing */
1835 if (aggregator_as == BGP_AS_ZERO) {
1836 flog_err(EC_BGP_ATTR_LEN,
1837 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1838 peer->host, aspath_print(attr->aspath));
1839
1840 if (bgp_debug_update(peer, NULL, NULL, 1)) {
1841 char attr_str[BUFSIZ] = {0};
1842
1843 bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1844
1845 zlog_debug("%s: attributes: %s", __func__, attr_str);
1846 }
1847 } else {
1848 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
1849 }
1850
1851 return BGP_ATTR_PARSE_PROCEED;
1852}
1853
1854/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1855 */
1856static bgp_attr_parse_ret_t
1857bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
1858 struct aspath *as4_path, as_t as4_aggregator,
1859 struct in_addr *as4_aggregator_addr)
1860{
1861 int ignore_as4_path = 0;
1862 struct aspath *newpath;
1863
1864 if (!attr->aspath) {
1865 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1866 * have
1867 * checked that all well-known, mandatory attributes were
1868 * present.
1869 *
1870 * Can only be a problem with peer itself - hard error
1871 */
1872 return BGP_ATTR_PARSE_ERROR;
1873 }
1874
1875 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) {
1876 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1877 * if given.
1878 * It is worth a warning though, because the peer really
1879 * should not send them
1880 */
1881 if (BGP_DEBUG(as4, AS4)) {
1882 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1883 zlog_debug("[AS4] %s %s AS4_PATH", peer->host,
1884 "AS4 capable peer, yet it sent");
1885
1886 if (attr->flag
1887 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1888 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1889 peer->host,
1890 "AS4 capable peer, yet it sent");
1891 }
1892
1893 return BGP_ATTR_PARSE_PROCEED;
1894 }
1895
1896 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1897 * because that may override AS4_PATH
1898 */
1899 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) {
1900 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
1901 /* received both.
1902 * if the as_number in aggregator is not AS_TRANS,
1903 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1904 * and the Aggregator shall be taken as
1905 * info on the aggregating node, and the AS_PATH
1906 * shall be taken as the AS_PATH
1907 * otherwise
1908 * the Aggregator shall be ignored and the
1909 * AS4_AGGREGATOR shall be taken as the
1910 * Aggregating node and the AS_PATH is to be
1911 * constructed "as in all other cases"
1912 */
1913 if (attr->aggregator_as != BGP_AS_TRANS) {
1914 /* ignore */
1915 if (BGP_DEBUG(as4, AS4))
1916 zlog_debug(
1917 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1918 peer->host);
1919 ignore_as4_path = 1;
1920 } else {
1921 /* "New_aggregator shall be taken as aggregator"
1922 */
1923 attr->aggregator_as = as4_aggregator;
1924 attr->aggregator_addr.s_addr =
1925 as4_aggregator_addr->s_addr;
1926 }
1927 } else {
1928 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1929 * That is bogus - but reading the conditions
1930 * we have to handle AS4_AGGREGATOR as if it were
1931 * AGGREGATOR in that case
1932 */
1933 if (BGP_DEBUG(as4, AS4))
1934 zlog_debug(
1935 "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there",
1936 peer->host);
1937 attr->aggregator_as = as4_aggregator;
1938 /* sweep it under the carpet and simulate a "good"
1939 * AGGREGATOR */
1940 attr->flag |= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
1941 }
1942 }
1943
1944 /* need to reconcile NEW_AS_PATH and AS_PATH */
1945 if (!ignore_as4_path
1946 && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) {
1947 newpath = aspath_reconcile_as4(attr->aspath, as4_path);
1948 if (!newpath)
1949 return BGP_ATTR_PARSE_ERROR;
1950
1951 aspath_unintern(&attr->aspath);
1952 attr->aspath = aspath_intern(newpath);
1953 }
1954 return BGP_ATTR_PARSE_PROCEED;
1955}
1956
1957/* Community attribute. */
1958static bgp_attr_parse_ret_t
1959bgp_attr_community(struct bgp_attr_parser_args *args)
1960{
1961 struct peer *const peer = args->peer;
1962 struct attr *const attr = args->attr;
1963 const bgp_size_t length = args->length;
1964
1965 if (length == 0) {
1966 attr->community = NULL;
1967 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1968 args->total);
1969 }
1970
1971 attr->community =
1972 community_parse((uint32_t *)stream_pnt(peer->curr), length);
1973
1974 /* XXX: fix community_parse to use stream API and remove this */
1975 stream_forward_getp(peer->curr, length);
1976
1977 /* The Community attribute SHALL be considered malformed if its
1978 * length is not a non-zero multiple of 4.
1979 */
1980 if (!attr->community)
1981 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1982 args->total);
1983
1984 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1985
1986 return BGP_ATTR_PARSE_PROCEED;
1987}
1988
1989/* Originator ID attribute. */
1990static bgp_attr_parse_ret_t
1991bgp_attr_originator_id(struct bgp_attr_parser_args *args)
1992{
1993 struct peer *const peer = args->peer;
1994 struct attr *const attr = args->attr;
1995 const bgp_size_t length = args->length;
1996
1997 /* if received from an internal neighbor, it SHALL be considered
1998 * malformed if its length is not equal to 4. If malformed, the
1999 * UPDATE message SHALL be handled using the approach of "treat-as-
2000 * withdraw".
2001 */
2002 if (length != 4) {
2003 flog_err(EC_BGP_ATTR_LEN, "Bad originator ID length %d",
2004 length);
2005
2006 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2007 args->total);
2008 }
2009
2010 attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
2011
2012 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
2013
2014 return BGP_ATTR_PARSE_PROCEED;
2015}
2016
2017/* Cluster list attribute. */
2018static bgp_attr_parse_ret_t
2019bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
2020{
2021 struct peer *const peer = args->peer;
2022 struct attr *const attr = args->attr;
2023 const bgp_size_t length = args->length;
2024
2025 /* if received from an internal neighbor, it SHALL be considered
2026 * malformed if its length is not a non-zero multiple of 4. If
2027 * malformed, the UPDATE message SHALL be handled using the approach
2028 * of "treat-as-withdraw".
2029 */
2030 if (length == 0 || length % 4) {
2031 flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
2032
2033 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2034 args->total);
2035 }
2036
2037 bgp_attr_set_cluster(
2038 attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
2039 length));
2040
2041 /* XXX: Fix cluster_parse to use stream API and then remove this */
2042 stream_forward_getp(peer->curr, length);
2043
2044 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
2045
2046 return BGP_ATTR_PARSE_PROCEED;
2047}
2048
2049/* Multiprotocol reachability information parse. */
2050int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
2051 struct bgp_nlri *mp_update)
2052{
2053 iana_afi_t pkt_afi;
2054 afi_t afi;
2055 iana_safi_t pkt_safi;
2056 safi_t safi;
2057 bgp_size_t nlri_len;
2058 size_t start;
2059 struct stream *s;
2060 struct peer *const peer = args->peer;
2061 struct attr *const attr = args->attr;
2062 const bgp_size_t length = args->length;
2063
2064 /* Set end of packet. */
2065 s = BGP_INPUT(peer);
2066 start = stream_get_getp(s);
2067
2068/* safe to read statically sized header? */
2069#define BGP_MP_REACH_MIN_SIZE 5
2070#define LEN_LEFT (length - (stream_get_getp(s) - start))
2071 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) {
2072 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2073 __func__, peer->host, (unsigned long)length);
2074 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2075 }
2076
2077 /* Load AFI, SAFI. */
2078 pkt_afi = stream_getw(s);
2079 pkt_safi = stream_getc(s);
2080
2081 /* Convert AFI, SAFI to internal values, check. */
2082 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2083 /* Log if AFI or SAFI is unrecognized. This is not an error
2084 * unless
2085 * the attribute is otherwise malformed.
2086 */
2087 if (bgp_debug_update(peer, NULL, NULL, 0))
2088 zlog_debug(
2089 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2090 peer->host, iana_afi2str(pkt_afi),
2091 iana_safi2str(pkt_safi));
2092 return BGP_ATTR_PARSE_ERROR;
2093 }
2094
2095 /* Get nexthop length. */
2096 attr->mp_nexthop_len = stream_getc(s);
2097
2098 if (LEN_LEFT < attr->mp_nexthop_len) {
2099 zlog_info(
2100 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2101 __func__, peer->host, attr->mp_nexthop_len);
2102 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2103 }
2104
2105 /* Nexthop length check. */
2106 switch (attr->mp_nexthop_len) {
2107 case 0:
2108 if (safi != SAFI_FLOWSPEC) {
2109 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2110 __func__, peer->host, attr->mp_nexthop_len);
2111 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2112 }
2113 break;
2114 case BGP_ATTR_NHLEN_VPNV4:
2115 stream_getl(s); /* RD high */
2116 stream_getl(s); /* RD low */
2117 /*
2118 * NOTE: intentional fall through
2119 * - for consistency in rx processing
2120 *
2121 * The following comment is to signal GCC this intention
2122 * and suppress the warning
2123 */
2124 /* FALLTHRU */
2125 case BGP_ATTR_NHLEN_IPV4:
2126 stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
2127 /* Probably needed for RFC 2283 */
2128 if (attr->nexthop.s_addr == INADDR_ANY)
2129 memcpy(&attr->nexthop.s_addr,
2130 &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
2131 break;
2132 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2133 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2134 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) {
2135 stream_getl(s); /* RD high */
2136 stream_getl(s); /* RD low */
2137 }
2138 stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2139 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2140 if (!peer->nexthop.ifp) {
2141 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2142 peer->host);
2143 return BGP_ATTR_PARSE_WITHDRAW;
2144 }
2145 attr->nh_ifindex = peer->nexthop.ifp->ifindex;
2146 }
2147 break;
2148 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2149 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
2150 if (attr->mp_nexthop_len
2151 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2152 stream_getl(s); /* RD high */
2153 stream_getl(s); /* RD low */
2154 }
2155 stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2156 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2157 if (!peer->nexthop.ifp) {
2158 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2159 peer->host);
2160 return BGP_ATTR_PARSE_WITHDRAW;
2161 }
2162 attr->nh_ifindex = peer->nexthop.ifp->ifindex;
2163 }
2164 if (attr->mp_nexthop_len
2165 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2166 stream_getl(s); /* RD high */
2167 stream_getl(s); /* RD low */
2168 }
2169 stream_get(&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
2170 if (!IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) {
2171 if (bgp_debug_update(peer, NULL, NULL, 1))
2172 zlog_debug(
2173 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2174 peer->host, &attr->mp_nexthop_global,
2175 &attr->mp_nexthop_local);
2176
2177 attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
2178 }
2179 if (!peer->nexthop.ifp) {
2180 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2181 peer->host);
2182 return BGP_ATTR_PARSE_WITHDRAW;
2183 }
2184 attr->nh_lla_ifindex = peer->nexthop.ifp->ifindex;
2185 break;
2186 default:
2187 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2188 __func__, peer->host, attr->mp_nexthop_len);
2189 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2190 }
2191
2192 if (!LEN_LEFT) {
2193 zlog_info("%s: %s sent SNPA which couldn't be read",
2194 __func__, peer->host);
2195 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2196 }
2197
2198 {
2199 uint8_t val;
2200 if ((val = stream_getc(s)))
2201 flog_warn(
2202 EC_BGP_DEFUNCT_SNPA_LEN,
2203 "%s sent non-zero value, %u, for defunct SNPA-length field",
2204 peer->host, val);
2205 }
2206
2207 /* must have nrli_len, what is left of the attribute */
2208 nlri_len = LEN_LEFT;
2209 if (nlri_len > STREAM_READABLE(s)) {
2210 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2211 __func__, peer->host);
2212 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2213 }
2214
2215 if (!nlri_len) {
2216 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2217 __func__, peer->host);
2218
2219 mp_update->afi = afi;
2220 mp_update->safi = safi;
2221 return BGP_ATTR_PARSE_EOR;
2222 }
2223
2224 mp_update->afi = afi;
2225 mp_update->safi = safi;
2226 mp_update->nlri = stream_pnt(s);
2227 mp_update->length = nlri_len;
2228
2229 stream_forward_getp(s, nlri_len);
2230
2231 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
2232
2233 return BGP_ATTR_PARSE_PROCEED;
2234#undef LEN_LEFT
2235}
2236
2237/* Multiprotocol unreachable parse */
2238int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
2239 struct bgp_nlri *mp_withdraw)
2240{
2241 struct stream *s;
2242 iana_afi_t pkt_afi;
2243 afi_t afi;
2244 iana_safi_t pkt_safi;
2245 safi_t safi;
2246 uint16_t withdraw_len;
2247 struct peer *const peer = args->peer;
2248 struct attr *const attr = args->attr;
2249 const bgp_size_t length = args->length;
2250
2251 s = peer->curr;
2252
2253#define BGP_MP_UNREACH_MIN_SIZE 3
2254 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
2255 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2256
2257 pkt_afi = stream_getw(s);
2258 pkt_safi = stream_getc(s);
2259
2260 /* Convert AFI, SAFI to internal values, check. */
2261 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2262 /* Log if AFI or SAFI is unrecognized. This is not an error
2263 * unless
2264 * the attribute is otherwise malformed.
2265 */
2266 if (bgp_debug_update(peer, NULL, NULL, 0))
2267 zlog_debug(
2268 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2269 peer->host, iana_afi2str(pkt_afi),
2270 iana_safi2str(pkt_safi));
2271 return BGP_ATTR_PARSE_ERROR;
2272 }
2273
2274 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
2275
2276 mp_withdraw->afi = afi;
2277 mp_withdraw->safi = safi;
2278 mp_withdraw->nlri = stream_pnt(s);
2279 mp_withdraw->length = withdraw_len;
2280
2281 stream_forward_getp(s, withdraw_len);
2282
2283 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI);
2284
2285 return BGP_ATTR_PARSE_PROCEED;
2286}
2287
2288/* Large Community attribute. */
2289static bgp_attr_parse_ret_t
2290bgp_attr_large_community(struct bgp_attr_parser_args *args)
2291{
2292 struct peer *const peer = args->peer;
2293 struct attr *const attr = args->attr;
2294 const bgp_size_t length = args->length;
2295
2296 /*
2297 * Large community follows new attribute format.
2298 */
2299 if (length == 0) {
2300 attr->lcommunity = NULL;
2301 /* Empty extcomm doesn't seem to be invalid per se */
2302 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2303 args->total);
2304 }
2305
2306 attr->lcommunity = lcommunity_parse(stream_pnt(peer->curr), length);
2307 /* XXX: fix ecommunity_parse to use stream API */
2308 stream_forward_getp(peer->curr, length);
2309
2310 if (!attr->lcommunity)
2311 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2312 args->total);
2313
2314 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
2315
2316 return BGP_ATTR_PARSE_PROCEED;
2317}
2318
2319/* Extended Community attribute. */
2320static bgp_attr_parse_ret_t
2321bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
2322{
2323 struct peer *const peer = args->peer;
2324 struct attr *const attr = args->attr;
2325 const bgp_size_t length = args->length;
2326 uint8_t sticky = 0;
2327 bool proxy = false;
2328
2329 if (length == 0) {
2330 attr->ecommunity = NULL;
2331 /* Empty extcomm doesn't seem to be invalid per se */
2332 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2333 args->total);
2334 }
2335
2336 attr->ecommunity = ecommunity_parse(
2337 stream_pnt(peer->curr), length,
2338 CHECK_FLAG(peer->flags,
2339 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2340 /* XXX: fix ecommunity_parse to use stream API */
2341 stream_forward_getp(peer->curr, length);
2342
2343 /* The Extended Community attribute SHALL be considered malformed if
2344 * its length is not a non-zero multiple of 8.
2345 */
2346 if (!attr->ecommunity)
2347 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2348 args->total);
2349
2350 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
2351
2352 /* Extract DF election preference and mobility sequence number */
2353 attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
2354
2355 /* Extract MAC mobility sequence number, if any. */
2356 attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
2357 attr->sticky = sticky;
2358
2359 /* Check if this is a Gateway MAC-IP advertisement */
2360 attr->default_gw = bgp_attr_default_gw(attr);
2361
2362 /* Handle scenario where router flag ecommunity is not
2363 * set but default gw ext community is present.
2364 * Use default gateway, set and propogate R-bit.
2365 */
2366 if (attr->default_gw)
2367 attr->router_flag = 1;
2368
2369 /* Check EVPN Neighbor advertisement flags, R-bit */
2370 bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy);
2371 if (proxy)
2372 attr->es_flags |= ATTR_ES_PROXY_ADVERT;
2373
2374 /* Extract the Rmac, if any */
2375 if (bgp_attr_rmac(attr, &attr->rmac)) {
2376 if (bgp_debug_update(peer, NULL, NULL, 1)
2377 && bgp_mac_exist(&attr->rmac))
2378 zlog_debug("%s: router mac %pEA is self mac", __func__,
2379 &attr->rmac);
2380 }
2381
2382 /* Get the tunnel type from encap extended community */
2383 bgp_attr_extcom_tunnel_type(attr,
2384 (bgp_encap_types *)&attr->encap_tunneltype);
2385
2386 /* Extract link bandwidth, if any. */
2387 (void)ecommunity_linkbw_present(attr->ecommunity, &attr->link_bw);
2388
2389 return BGP_ATTR_PARSE_PROCEED;
2390}
2391
2392/* IPv6 Extended Community attribute. */
2393static bgp_attr_parse_ret_t
2394bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
2395{
2396 struct peer *const peer = args->peer;
2397 struct attr *const attr = args->attr;
2398 const bgp_size_t length = args->length;
2399 struct ecommunity *ipv6_ecomm = NULL;
2400
2401 if (length == 0) {
2402 bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2403 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2404 args->total);
2405 }
2406
2407 ipv6_ecomm = ecommunity_parse_ipv6(
2408 stream_pnt(peer->curr), length,
2409 CHECK_FLAG(peer->flags,
2410 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2411 bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2412
2413 /* XXX: fix ecommunity_parse to use stream API */
2414 stream_forward_getp(peer->curr, length);
2415
2416 if (!ipv6_ecomm)
2417 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2418 args->total);
2419
2420 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES);
2421
2422 return BGP_ATTR_PARSE_PROCEED;
2423}
2424
2425/* Parse Tunnel Encap attribute in an UPDATE */
2426static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
2427 bgp_size_t length, /* IN: attr's length field */
2428 struct attr *attr, /* IN: caller already allocated */
2429 uint8_t flag, /* IN: attr's flags field */
2430 uint8_t *startp)
2431{
2432 bgp_size_t total;
2433 uint16_t tunneltype = 0;
2434
2435 total = length + (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
2436
2437 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
2438 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
2439 zlog_info(
2440 "Tunnel Encap attribute flag isn't optional and transitive %d",
2441 flag);
2442 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
2443 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2444 startp, total);
2445 return -1;
2446 }
2447
2448 if (BGP_ATTR_ENCAP == type) {
2449 /* read outer TLV type and length */
2450 uint16_t tlv_length;
2451
2452 if (length < 4) {
2453 zlog_info(
2454 "Tunnel Encap attribute not long enough to contain outer T,L");
2455 bgp_notify_send_with_data(
2456 peer, BGP_NOTIFY_UPDATE_ERR,
2457 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
2458 return -1;
2459 }
2460 tunneltype = stream_getw(BGP_INPUT(peer));
2461 tlv_length = stream_getw(BGP_INPUT(peer));
2462 length -= 4;
2463
2464 if (tlv_length != length) {
2465 zlog_info("%s: tlv_length(%d) != length(%d)",
2466 __func__, tlv_length, length);
2467 }
2468 }
2469
2470 while (length >= 4) {
2471 uint16_t subtype = 0;
2472 uint16_t sublength = 0;
2473 struct bgp_attr_encap_subtlv *tlv;
2474
2475 if (BGP_ATTR_ENCAP == type) {
2476 subtype = stream_getc(BGP_INPUT(peer));
2477 sublength = stream_getc(BGP_INPUT(peer));
2478 length -= 2;
2479#ifdef ENABLE_BGP_VNC
2480 } else {
2481 subtype = stream_getw(BGP_INPUT(peer));
2482 sublength = stream_getw(BGP_INPUT(peer));
2483 length -= 4;
2484#endif
2485 }
2486
2487 if (sublength > length) {
2488 zlog_info(
2489 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2490 sublength, length);
2491 bgp_notify_send_with_data(
2492 peer, BGP_NOTIFY_UPDATE_ERR,
2493 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
2494 return -1;
2495 }
2496
2497 /* alloc and copy sub-tlv */
2498 /* TBD make sure these are freed when attributes are released */
2499 tlv = XCALLOC(MTYPE_ENCAP_TLV,
2500 sizeof(struct bgp_attr_encap_subtlv) + sublength);
2501 tlv->type = subtype;
2502 tlv->length = sublength;
2503 stream_get(tlv->value, peer->curr, sublength);
2504 length -= sublength;
2505
2506 /* attach tlv to encap chain */
2507 if (BGP_ATTR_ENCAP == type) {
2508 struct bgp_attr_encap_subtlv *stlv_last;
2509 for (stlv_last = attr->encap_subtlvs;
2510 stlv_last && stlv_last->next;
2511 stlv_last = stlv_last->next)
2512 ;
2513 if (stlv_last) {
2514 stlv_last->next = tlv;
2515 } else {
2516 attr->encap_subtlvs = tlv;
2517 }
2518#ifdef ENABLE_BGP_VNC
2519 } else {
2520 struct bgp_attr_encap_subtlv *stlv_last;
2521 struct bgp_attr_encap_subtlv *vnc_subtlvs =
2522 bgp_attr_get_vnc_subtlvs(attr);
2523
2524 for (stlv_last = vnc_subtlvs;
2525 stlv_last && stlv_last->next;
2526 stlv_last = stlv_last->next)
2527 ;
2528 if (stlv_last)
2529 stlv_last->next = tlv;
2530 else
2531 bgp_attr_set_vnc_subtlvs(attr, tlv);
2532#endif
2533 }
2534 }
2535
2536 if (BGP_ATTR_ENCAP == type) {
2537 attr->encap_tunneltype = tunneltype;
2538 }
2539
2540 if (length) {
2541 /* spurious leftover data */
2542 zlog_info(
2543 "Tunnel Encap attribute length is bad: %d leftover octets",
2544 length);
2545 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
2546 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2547 startp, total);
2548 return -1;
2549 }
2550
2551 return 0;
2552}
2553
2554
2555/* SRv6 Service Data Sub-Sub-TLV attribute
2556 * draft-ietf-bess-srv6-services-07
2557 */
2558static bgp_attr_parse_ret_t
2559bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
2560{
2561 struct peer *const peer = args->peer;
2562 struct attr *const attr = args->attr;
2563 uint8_t type, loc_block_len, loc_node_len, func_len, arg_len,
2564 transposition_len, transposition_offset;
2565 uint16_t length;
2566 size_t headersz = sizeof(type) + sizeof(length);
2567
2568 if (STREAM_READABLE(peer->curr) < headersz) {
2569 flog_err(
2570 EC_BGP_ATTR_LEN,
2571 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2572 headersz, STREAM_READABLE(peer->curr));
2573 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2574 args->total);
2575 }
2576
2577 type = stream_getc(peer->curr);
2578 length = stream_getw(peer->curr);
2579
2580 if (STREAM_READABLE(peer->curr) < length) {
2581 flog_err(
2582 EC_BGP_ATTR_LEN,
2583 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2584 length, STREAM_READABLE(peer->curr));
2585 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2586 args->total);
2587 }
2588
2589 if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
2590 loc_block_len = stream_getc(peer->curr);
2591 loc_node_len = stream_getc(peer->curr);
2592 func_len = stream_getc(peer->curr);
2593 arg_len = stream_getc(peer->curr);
2594 transposition_len = stream_getc(peer->curr);
2595 transposition_offset = stream_getc(peer->curr);
2596
2597 /* Log SRv6 Service Data Sub-Sub-TLV */
2598 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
2599 zlog_debug(
2600 "%s: srv6-l3-srv-data loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u, transposition-len=%u, transposition-offset=%u",
2601 __func__, loc_block_len, loc_node_len, func_len,
2602 arg_len, transposition_len,
2603 transposition_offset);
2604 }
2605
2606 attr->srv6_l3vpn->loc_block_len = loc_block_len;
2607 attr->srv6_l3vpn->loc_node_len = loc_node_len;
2608 attr->srv6_l3vpn->func_len = func_len;
2609 attr->srv6_l3vpn->arg_len = arg_len;
2610 attr->srv6_l3vpn->transposition_len = transposition_len;
2611 attr->srv6_l3vpn->transposition_offset = transposition_offset;
2612 }
2613
2614 else {
2615 if (bgp_debug_update(peer, NULL, NULL, 1))
2616 zlog_debug(
2617 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2618 peer->host, type);
2619
2620 stream_forward_getp(peer->curr, length);
2621 }
2622
2623 return BGP_ATTR_PARSE_PROCEED;
2624}
2625
2626/* SRv6 Service Sub-TLV attribute
2627 * draft-ietf-bess-srv6-services-07
2628 */
2629static bgp_attr_parse_ret_t
2630bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
2631{
2632 struct peer *const peer = args->peer;
2633 struct attr *const attr = args->attr;
2634 struct in6_addr ipv6_sid;
2635 uint8_t type, sid_flags;
2636 uint16_t length, endpoint_behavior;
2637 size_t headersz = sizeof(type) + sizeof(length);
2638 bgp_attr_parse_ret_t err;
2639 char buf[BUFSIZ];
2640
2641 if (STREAM_READABLE(peer->curr) < headersz) {
2642 flog_err(
2643 EC_BGP_ATTR_LEN,
2644 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2645 headersz, STREAM_READABLE(peer->curr));
2646 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2647 args->total);
2648 }
2649
2650 type = stream_getc(peer->curr);
2651 length = stream_getw(peer->curr);
2652
2653 if (STREAM_READABLE(peer->curr) < length) {
2654 flog_err(
2655 EC_BGP_ATTR_LEN,
2656 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2657 length, STREAM_READABLE(peer->curr));
2658 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2659 args->total);
2660 }
2661
2662 if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
2663 stream_getc(peer->curr);
2664 stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
2665 sid_flags = stream_getc(peer->curr);
2666 endpoint_behavior = stream_getw(peer->curr);
2667 stream_getc(peer->curr);
2668
2669 /* Log SRv6 Service Sub-TLV */
2670 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
2671 inet_ntop(AF_INET6, &ipv6_sid, buf, sizeof(buf));
2672 zlog_debug(
2673 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2674 __func__, buf, sid_flags, endpoint_behavior);
2675 }
2676
2677 /* Configure from Info */
2678 if (attr->srv6_l3vpn) {
2679 flog_err(EC_BGP_ATTRIBUTE_REPEATED,
2680 "Prefix SID SRv6 L3VPN field repeated");
2681 return bgp_attr_malformed(
2682 args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
2683 }
2684 attr->srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
2685 sizeof(struct bgp_attr_srv6_l3vpn));
2686 sid_copy(&attr->srv6_l3vpn->sid, &ipv6_sid);
2687 attr->srv6_l3vpn->sid_flags = sid_flags;
2688 attr->srv6_l3vpn->endpoint_behavior = endpoint_behavior;
2689 attr->srv6_l3vpn->loc_block_len = 0;
2690 attr->srv6_l3vpn->loc_node_len = 0;
2691 attr->srv6_l3vpn->func_len = 0;
2692 attr->srv6_l3vpn->arg_len = 0;
2693 attr->srv6_l3vpn->transposition_len = 0;
2694 attr->srv6_l3vpn->transposition_offset = 0;
2695
2696 // Sub-Sub-TLV found
2697 if (length > BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2698 err = bgp_attr_srv6_service_data(args);
2699
2700 if (err != BGP_ATTR_PARSE_PROCEED)
2701 return err;
2702 }
2703
2704 attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
2705 }
2706
2707 /* Placeholder code for unsupported type */
2708 else {
2709 if (bgp_debug_update(peer, NULL, NULL, 1))
2710 zlog_debug(
2711 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2712 peer->host, type);
2713
2714 stream_forward_getp(peer->curr, length);
2715 }
2716
2717 return BGP_ATTR_PARSE_PROCEED;
2718}
2719
2720/*
2721 * Read an individual SID value returning how much data we have read
2722 * Returns 0 if there was an error that needs to be passed up the stack
2723 */
2724static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
2725 struct bgp_attr_parser_args *args)
2726{
2727 struct peer *const peer = args->peer;
2728 struct attr *const attr = args->attr;
2729 uint32_t label_index;
2730 struct in6_addr ipv6_sid;
2731 uint32_t srgb_base;
2732 uint32_t srgb_range;
2733 int srgb_count;
2734 uint8_t sid_type, sid_flags;
2735 char buf[BUFSIZ];
2736
2737 if (type == BGP_PREFIX_SID_LABEL_INDEX) {
2738 if (STREAM_READABLE(peer->curr) < length
2739 || length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
2740 flog_err(EC_BGP_ATTR_LEN,
2741 "Prefix SID label index length is %hu instead of %u",
2742 length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
2743 return bgp_attr_malformed(args,
2744 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2745 args->total);
2746 }
2747
2748 /* Ignore flags and reserved */
2749 stream_getc(peer->curr);
2750 stream_getw(peer->curr);
2751
2752 /* Fetch the label index and see if it is valid. */
2753 label_index = stream_getl(peer->curr);
2754 if (label_index == BGP_INVALID_LABEL_INDEX)
2755 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2756 args->total);
2757
2758 /* Store label index; subsequently, we'll check on
2759 * address-family */
2760 attr->label_index = label_index;
2761 }
2762
2763 /* Placeholder code for the IPv6 SID type */
2764 else if (type == BGP_PREFIX_SID_IPV6) {
2765 if (STREAM_READABLE(peer->curr) < length
2766 || length != BGP_PREFIX_SID_IPV6_LENGTH) {
2767 flog_err(EC_BGP_ATTR_LEN,
2768 "Prefix SID IPv6 length is %hu instead of %u",
2769 length, BGP_PREFIX_SID_IPV6_LENGTH);
2770 return bgp_attr_malformed(args,
2771 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2772 args->total);
2773 }
2774
2775 /* Ignore reserved */
2776 stream_getc(peer->curr);
2777 stream_getw(peer->curr);
2778
2779 stream_get(&ipv6_sid, peer->curr, 16);
2780 }
2781
2782 /* Placeholder code for the Originator SRGB type */
2783 else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
2784 /*
2785 * ietf-idr-bgp-prefix-sid-05:
2786 * Length is the total length of the value portion of the
2787 * TLV: 2 + multiple of 6.
2788 *
2789 * peer->curr stream readp should be at the beginning of the 16
2790 * bit flag field at this point in the code.
2791 */
2792
2793 /*
2794 * Check that the TLV length field is sane: at least 2 bytes of
2795 * flag, and at least 1 SRGB (these are 6 bytes each)
2796 */
2797 if (length < (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH)) {
2798 flog_err(
2799 EC_BGP_ATTR_LEN,
2800 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2801 length,
2802 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
2803 return bgp_attr_malformed(
2804 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2805 args->total);
2806 }
2807
2808 /*
2809 * Check that we actually have at least as much data as
2810 * specified by the length field
2811 */
2812 if (STREAM_READABLE(peer->curr) < length) {
2813 flog_err(EC_BGP_ATTR_LEN,
2814 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2815 length, STREAM_READABLE(peer->curr));
2816 return bgp_attr_malformed(
2817 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2818 args->total);
2819 }
2820
2821 /*
2822 * Check that the portion of the TLV containing the sequence of
2823 * SRGBs corresponds to a multiple of the SRGB size; to get
2824 * that length, we skip the 16 bit flags field
2825 */
2826 stream_getw(peer->curr);
2827 length -= 2;
2828 if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) {
2829 flog_err(
2830 EC_BGP_ATTR_LEN,
2831 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2832 length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
2833 return bgp_attr_malformed(
2834 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2835 args->total);
2836 }
2837
2838 srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH;
2839
2840 for (int i = 0; i < srgb_count; i++) {
2841 stream_get(&srgb_base, peer->curr, 3);
2842 stream_get(&srgb_range, peer->curr, 3);
2843 }
2844 }
2845
2846 /* Placeholder code for the VPN-SID Service type */
2847 else if (type == BGP_PREFIX_SID_VPN_SID) {
2848 if (STREAM_READABLE(peer->curr) < length
2849 || length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
2850 flog_err(EC_BGP_ATTR_LEN,
2851 "Prefix SID VPN SID length is %hu instead of %u",
2852 length, BGP_PREFIX_SID_VPN_SID_LENGTH);
2853 return bgp_attr_malformed(args,
2854 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2855 args->total);
2856 }
2857
2858 /* Parse VPN-SID Sub-TLV */
2859 stream_getc(peer->curr); /* reserved */
2860 sid_type = stream_getc(peer->curr); /* sid_type */
2861 sid_flags = stream_getc(peer->curr); /* sid_flags */
2862 stream_get(&ipv6_sid, peer->curr,
2863 sizeof(ipv6_sid)); /* sid_value */
2864
2865 /* Log VPN-SID Sub-TLV */
2866 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
2867 inet_ntop(AF_INET6, &ipv6_sid, buf, sizeof(buf));
2868 zlog_debug(
2869 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2870 __func__, buf, sid_type, sid_flags);
2871 }
2872
2873 /* Configure from Info */
2874 if (attr->srv6_vpn) {
2875 flog_err(EC_BGP_ATTRIBUTE_REPEATED,
2876 "Prefix SID SRv6 VPN field repeated");
2877 return bgp_attr_malformed(
2878 args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
2879 }
2880 attr->srv6_vpn = XCALLOC(MTYPE_BGP_SRV6_VPN,
2881 sizeof(struct bgp_attr_srv6_vpn));
2882 attr->srv6_vpn->sid_flags = sid_flags;
2883 sid_copy(&attr->srv6_vpn->sid, &ipv6_sid);
2884 attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
2885 }
2886
2887 /* Placeholder code for the SRv6 L3 Service type */
2888 else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
2889 if (STREAM_READABLE(peer->curr) < length) {
2890 flog_err(
2891 EC_BGP_ATTR_LEN,
2892 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2893 length, STREAM_READABLE(peer->curr));
2894 return bgp_attr_malformed(args,
2895 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2896 args->total);
2897 }
2898
2899 /* ignore reserved */
2900 stream_getc(peer->curr);
2901
2902 return bgp_attr_srv6_service(args);
2903 }
2904
2905 /* Placeholder code for Unsupported TLV */
2906 else {
2907
2908 if (STREAM_READABLE(peer->curr) < length) {
2909 flog_err(
2910 EC_BGP_ATTR_LEN,
2911 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2912 length, STREAM_READABLE(peer->curr));
2913 return bgp_attr_malformed(
2914 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2915 args->total);
2916 }
2917
2918 if (bgp_debug_update(peer, NULL, NULL, 1))
2919 zlog_debug(
2920 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2921 peer->host, type);
2922
2923 stream_forward_getp(peer->curr, length);
2924 }
2925
2926 return BGP_ATTR_PARSE_PROCEED;
2927}
2928
2929/* Prefix SID attribute
2930 * draft-ietf-idr-bgp-prefix-sid-05
2931 */
2932bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
2933{
2934 struct peer *const peer = args->peer;
2935 struct attr *const attr = args->attr;
2936 bgp_attr_parse_ret_t ret;
2937
2938 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
2939
2940 uint8_t type;
2941 uint16_t length;
2942 size_t headersz = sizeof(type) + sizeof(length);
2943 size_t psid_parsed_length = 0;
2944
2945 while (STREAM_READABLE(peer->curr) > 0
2946 && psid_parsed_length < args->length) {
2947
2948 if (STREAM_READABLE(peer->curr) < headersz) {
2949 flog_err(
2950 EC_BGP_ATTR_LEN,
2951 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2952 headersz, STREAM_READABLE(peer->curr));
2953 return bgp_attr_malformed(
2954 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2955 args->total);
2956 }
2957
2958 type = stream_getc(peer->curr);
2959 length = stream_getw(peer->curr);
2960
2961 if (STREAM_READABLE(peer->curr) < length) {
2962 flog_err(
2963 EC_BGP_ATTR_LEN,
2964 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2965 length, STREAM_READABLE(peer->curr));
2966 return bgp_attr_malformed(args,
2967 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2968 args->total);
2969 }
2970
2971 ret = bgp_attr_psid_sub(type, length, args);
2972
2973 if (ret != BGP_ATTR_PARSE_PROCEED)
2974 return ret;
2975
2976 psid_parsed_length += length + headersz;
2977
2978 if (psid_parsed_length > args->length) {
2979 flog_err(
2980 EC_BGP_ATTR_LEN,
2981 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2982 length + headersz, psid_parsed_length - (length + headersz));
2983 return bgp_attr_malformed(
2984 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2985 args->total);
2986 }
2987 }
2988
2989 return BGP_ATTR_PARSE_PROCEED;
2990}
2991
2992/* PMSI tunnel attribute (RFC 6514)
2993 * Basic validation checks done here.
2994 */
2995static bgp_attr_parse_ret_t
2996bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
2997{
2998 struct peer *const peer = args->peer;
2999 struct attr *const attr = args->attr;
3000 const bgp_size_t length = args->length;
3001 uint8_t tnl_type;
3002 int attr_parse_len = 2 + BGP_LABEL_BYTES;
3003
3004 /* Verify that the receiver is expecting "ingress replication" as we
3005 * can only support that.
3006 */
3007 if (length < attr_parse_len) {
3008 flog_err(EC_BGP_ATTR_LEN, "Bad PMSI tunnel attribute length %d",
3009 length);
3010 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3011 args->total);
3012 }
3013 stream_getc(peer->curr); /* Flags */
3014 tnl_type = stream_getc(peer->curr);
3015 if (tnl_type > PMSI_TNLTYPE_MAX) {
3016 flog_err(EC_BGP_ATTR_PMSI_TYPE,
3017 "Invalid PMSI tunnel attribute type %d", tnl_type);
3018 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
3019 args->total);
3020 }
3021 if (tnl_type == PMSI_TNLTYPE_INGR_REPL) {
3022 if (length != 9) {
3023 flog_err(EC_BGP_ATTR_PMSI_LEN,
3024 "Bad PMSI tunnel attribute length %d for IR",
3025 length);
3026 return bgp_attr_malformed(
3027 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3028 args->total);
3029 }
3030 }
3031
3032 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
3033 bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
3034 stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES);
3035
3036 /* Forward read pointer of input stream. */
3037 stream_forward_getp(peer->curr, length - attr_parse_len);
3038
3039 return BGP_ATTR_PARSE_PROCEED;
3040}
3041
3042/* BGP unknown attribute treatment. */
3043static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args)
3044{
3045 bgp_size_t total = args->total;
3046 struct transit *transit;
3047 struct peer *const peer = args->peer;
3048 struct attr *const attr = args->attr;
3049 uint8_t *const startp = args->startp;
3050 const uint8_t type = args->type;
3051 const uint8_t flag = args->flags;
3052 const bgp_size_t length = args->length;
3053
3054 if (bgp_debug_update(peer, NULL, NULL, 1))
3055 zlog_debug(
3056 "%s Unknown attribute is received (type %d, length %d)",
3057 peer->host, type, length);
3058
3059 /* Forward read pointer of input stream. */
3060 stream_forward_getp(peer->curr, length);
3061
3062 /* If any of the mandatory well-known attributes are not recognized,
3063 then the Error Subcode is set to Unrecognized Well-known
3064 Attribute. The Data field contains the unrecognized attribute
3065 (type, length and value). */
3066 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
3067 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_UNREC_ATTR,
3068 args->total);
3069 }
3070
3071 /* Unrecognized non-transitive optional attributes must be quietly
3072 ignored and not passed along to other BGP peers. */
3073 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
3074 return BGP_ATTR_PARSE_PROCEED;
3075
3076 /* If a path with recognized transitive optional attribute is
3077 accepted and passed along to other BGP peers and the Partial bit
3078 in the Attribute Flags octet is set to 1 by some previous AS, it
3079 is not set back to 0 by the current AS. */
3080 SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL);
3081
3082 /* Store transitive attribute to the end of attr->transit. */
3083 transit = bgp_attr_get_transit(attr);
3084 if (!transit)
3085 transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
3086
3087 transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val,
3088 transit->length + total);
3089
3090 memcpy(transit->val + transit->length, startp, total);
3091 transit->length += total;
3092 bgp_attr_set_transit(attr, transit);
3093
3094 return BGP_ATTR_PARSE_PROCEED;
3095}
3096
3097/* Well-known attribute check. */
3098static int bgp_attr_check(struct peer *peer, struct attr *attr)
3099{
3100 uint8_t type = 0;
3101
3102 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3103 * empty UPDATE. */
3104 if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
3105 return BGP_ATTR_PARSE_PROCEED;
3106
3107 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3108 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3109 are present, it should. Check for any other attribute being present
3110 instead.
3111 */
3112 if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
3113 CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
3114 return BGP_ATTR_PARSE_PROCEED;
3115
3116 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
3117 type = BGP_ATTR_ORIGIN;
3118
3119 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
3120 type = BGP_ATTR_AS_PATH;
3121
3122 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3123 * and
3124 * NLRI is empty. We can't easily check NLRI empty here though.
3125 */
3126 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3127 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)))
3128 type = BGP_ATTR_NEXT_HOP;
3129
3130 if (peer->sort == BGP_PEER_IBGP
3131 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
3132 type = BGP_ATTR_LOCAL_PREF;
3133
3134 /* If any of the well-known mandatory attributes are not present
3135 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3136 */
3137 if (type) {
3138 flog_warn(EC_BGP_MISSING_ATTRIBUTE,
3139 "%s Missing well-known attribute %s.", peer->host,
3140 lookup_msg(attr_str, type, NULL));
3141 return BGP_ATTR_PARSE_WITHDRAW;
3142 }
3143 return BGP_ATTR_PARSE_PROCEED;
3144}
3145
3146/* Read attribute of update packet. This function is called from
3147 bgp_update_receive() in bgp_packet.c. */
3148bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
3149 bgp_size_t size, struct bgp_nlri *mp_update,
3150 struct bgp_nlri *mp_withdraw)
3151{
3152 bgp_attr_parse_ret_t ret;
3153 uint8_t flag = 0;
3154 uint8_t type = 0;
3155 bgp_size_t length;
3156 uint8_t *startp, *endp;
3157 uint8_t *attr_endp;
3158 uint8_t seen[BGP_ATTR_BITMAP_SIZE];
3159 /* we need the as4_path only until we have synthesized the as_path with
3160 * it */
3161 /* same goes for as4_aggregator */
3162 struct aspath *as4_path = NULL;
3163 as_t as4_aggregator = 0;
3164 struct in_addr as4_aggregator_addr = {.s_addr = 0};
3165 struct transit *transit;
3166
3167 /* Initialize bitmap. */
3168 memset(seen, 0, BGP_ATTR_BITMAP_SIZE);
3169
3170 /* End pointer of BGP attribute. */
3171 endp = BGP_INPUT_PNT(peer) + size;
3172
3173 /* Get attributes to the end of attribute length. */
3174 while (BGP_INPUT_PNT(peer) < endp) {
3175 /* Check remaining length check.*/
3176 if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) {
3177 /* XXX warning: long int format, int arg (arg 5) */
3178 flog_warn(
3179 EC_BGP_ATTRIBUTE_TOO_SMALL,
3180 "%s: error BGP attribute length %lu is smaller than min len",
3181 peer->host,
3182 (unsigned long)(endp
3183 - stream_pnt(BGP_INPUT(peer))));
3184
3185 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3186 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3187 ret = BGP_ATTR_PARSE_ERROR;
3188 goto done;
3189 }
3190
3191 /* Fetch attribute flag and type. */
3192 startp = BGP_INPUT_PNT(peer);
3193 /* "The lower-order four bits of the Attribute Flags octet are
3194 unused. They MUST be zero when sent and MUST be ignored when
3195 received." */
3196 flag = 0xF0 & stream_getc(BGP_INPUT(peer));
3197 type = stream_getc(BGP_INPUT(peer));
3198
3199 /* Check whether Extended-Length applies and is in bounds */
3200 if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
3201 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
3202 flog_warn(
3203 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
3204 "%s: Extended length set, but just %lu bytes of attr header",
3205 peer->host,
3206 (unsigned long)(endp
3207 - stream_pnt(BGP_INPUT(peer))));
3208
3209 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3210 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3211 ret = BGP_ATTR_PARSE_ERROR;
3212 goto done;
3213 }
3214
3215 /* Check extended attribue length bit. */
3216 if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN))
3217 length = stream_getw(BGP_INPUT(peer));
3218 else
3219 length = stream_getc(BGP_INPUT(peer));
3220
3221 /* If any attribute appears more than once in the UPDATE
3222 message, then the Error Subcode is set to Malformed Attribute
3223 List. */
3224
3225 if (CHECK_BITMAP(seen, type)) {
3226 flog_warn(
3227 EC_BGP_ATTRIBUTE_REPEATED,
3228 "%s: error BGP attribute type %d appears twice in a message",
3229 peer->host, type);
3230
3231 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3232 BGP_NOTIFY_UPDATE_MAL_ATTR);
3233 ret = BGP_ATTR_PARSE_ERROR;
3234 goto done;
3235 }
3236
3237 /* Set type to bitmap to check duplicate attribute. `type' is
3238 unsigned char so it never overflow bitmap range. */
3239
3240 SET_BITMAP(seen, type);
3241
3242 /* Overflow check. */
3243 attr_endp = BGP_INPUT_PNT(peer) + length;
3244
3245 if (attr_endp > endp) {
3246 flog_warn(
3247 EC_BGP_ATTRIBUTE_TOO_LARGE,
3248 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3249 peer->host, type, length, size, attr_endp,
3250 endp);
3251 /*
3252 * RFC 4271 6.3
3253 * If any recognized attribute has an Attribute
3254 * Length that conflicts with the expected length
3255 * (based on the attribute type code), then the
3256 * Error Subcode MUST be set to Attribute Length
3257 * Error. The Data field MUST contain the erroneous
3258 * attribute (type, length, and value).
3259 * ----------
3260 * We do not currently have a good way to determine the
3261 * length of the attribute independent of the length
3262 * received in the message. Instead we send the
3263 * minimum between the amount of data we have and the
3264 * amount specified by the attribute length field.
3265 *
3266 * Instead of directly passing in the packet buffer and
3267 * offset we use the stream_get* functions to read into
3268 * a stack buffer, since they perform bounds checking
3269 * and we are working with untrusted data.
3270 */
3271 unsigned char ndata[peer->max_packet_size];
3272 memset(ndata, 0x00, sizeof(ndata));
3273 size_t lfl =
3274 CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 2 : 1;
3275 /* Rewind to end of flag field */
3276 stream_rewind_getp(BGP_INPUT(peer), (1 + lfl));
3277 /* Type */
3278 stream_get(&ndata[0], BGP_INPUT(peer), 1);
3279 /* Length */
3280 stream_get(&ndata[1], BGP_INPUT(peer), lfl);
3281 /* Value */
3282 size_t atl = attr_endp - startp;
3283 size_t ndl = MIN(atl, STREAM_READABLE(BGP_INPUT(peer)));
3284 stream_get(&ndata[lfl + 1], BGP_INPUT(peer), ndl);
3285
3286 bgp_notify_send_with_data(
3287 peer, BGP_NOTIFY_UPDATE_ERR,
3288 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
3289 ndl + lfl + 1);
3290
3291 ret = BGP_ATTR_PARSE_ERROR;
3292 goto done;
3293 }
3294
3295 struct bgp_attr_parser_args attr_args = {
3296 .peer = peer,
3297 .length = length,
3298 .attr = attr,
3299 .type = type,
3300 .flags = flag,
3301 .startp = startp,
3302 .total = attr_endp - startp,
3303 };
3304
3305
3306 /* If any recognized attribute has Attribute Flags that conflict
3307 with the Attribute Type Code, then the Error Subcode is set
3308 to
3309 Attribute Flags Error. The Data field contains the erroneous
3310 attribute (type, length and value). */
3311 if (bgp_attr_flag_invalid(&attr_args)) {
3312 ret = bgp_attr_malformed(
3313 &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
3314 attr_args.total);
3315 if (ret == BGP_ATTR_PARSE_PROCEED)
3316 continue;
3317 goto done;
3318 }
3319
3320 /* OK check attribute and store it's value. */
3321 switch (type) {
3322 case BGP_ATTR_ORIGIN:
3323 ret = bgp_attr_origin(&attr_args);
3324 break;
3325 case BGP_ATTR_AS_PATH:
3326 ret = bgp_attr_aspath(&attr_args);
3327 break;
3328 case BGP_ATTR_AS4_PATH:
3329 ret = bgp_attr_as4_path(&attr_args, &as4_path);
3330 break;
3331 case BGP_ATTR_NEXT_HOP:
3332 ret = bgp_attr_nexthop(&attr_args);
3333 break;
3334 case BGP_ATTR_MULTI_EXIT_DISC:
3335 ret = bgp_attr_med(&attr_args);
3336 break;
3337 case BGP_ATTR_LOCAL_PREF:
3338 ret = bgp_attr_local_pref(&attr_args);
3339 break;
3340 case BGP_ATTR_ATOMIC_AGGREGATE:
3341 ret = bgp_attr_atomic(&attr_args);
3342 break;
3343 case BGP_ATTR_AGGREGATOR:
3344 ret = bgp_attr_aggregator(&attr_args);
3345 break;
3346 case BGP_ATTR_AS4_AGGREGATOR:
3347 ret = bgp_attr_as4_aggregator(&attr_args,
3348 &as4_aggregator,
3349 &as4_aggregator_addr);
3350 break;
3351 case BGP_ATTR_COMMUNITIES:
3352 ret = bgp_attr_community(&attr_args);
3353 break;
3354 case BGP_ATTR_LARGE_COMMUNITIES:
3355 ret = bgp_attr_large_community(&attr_args);
3356 break;
3357 case BGP_ATTR_ORIGINATOR_ID:
3358 ret = bgp_attr_originator_id(&attr_args);
3359 break;
3360 case BGP_ATTR_CLUSTER_LIST:
3361 ret = bgp_attr_cluster_list(&attr_args);
3362 break;
3363 case BGP_ATTR_MP_REACH_NLRI:
3364 ret = bgp_mp_reach_parse(&attr_args, mp_update);
3365 break;
3366 case BGP_ATTR_MP_UNREACH_NLRI:
3367 ret = bgp_mp_unreach_parse(&attr_args, mp_withdraw);
3368 break;
3369 case BGP_ATTR_EXT_COMMUNITIES:
3370 ret = bgp_attr_ext_communities(&attr_args);
3371 break;
3372#ifdef ENABLE_BGP_VNC_ATTR
3373 case BGP_ATTR_VNC:
3374#endif
3375 case BGP_ATTR_ENCAP:
3376 ret = bgp_attr_encap(type, peer, length, attr, flag,
3377 startp);
3378 break;
3379 case BGP_ATTR_PREFIX_SID:
3380 ret = bgp_attr_prefix_sid(&attr_args);
3381 break;
3382 case BGP_ATTR_PMSI_TUNNEL:
3383 ret = bgp_attr_pmsi_tunnel(&attr_args);
3384 break;
3385 case BGP_ATTR_IPV6_EXT_COMMUNITIES:
3386 ret = bgp_attr_ipv6_ext_communities(&attr_args);
3387 break;
3388 default:
3389 ret = bgp_attr_unknown(&attr_args);
3390 break;
3391 }
3392
3393 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) {
3394 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3395 BGP_NOTIFY_UPDATE_MAL_ATTR);
3396 ret = BGP_ATTR_PARSE_ERROR;
3397 goto done;
3398 }
3399
3400 if (ret == BGP_ATTR_PARSE_EOR) {
3401 goto done;
3402 }
3403
3404 if (ret == BGP_ATTR_PARSE_ERROR) {
3405 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
3406 "%s: Attribute %s, parse error", peer->host,
3407 lookup_msg(attr_str, type, NULL));
3408 goto done;
3409 }
3410 if (ret == BGP_ATTR_PARSE_WITHDRAW) {
3411 flog_warn(
3412 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
3413 "%s: Attribute %s, parse error - treating as withdrawal",
3414 peer->host, lookup_msg(attr_str, type, NULL));
3415 goto done;
3416 }
3417
3418 /* Check the fetched length. */
3419 if (BGP_INPUT_PNT(peer) != attr_endp) {
3420 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR,
3421 "%s: BGP attribute %s, fetch error",
3422 peer->host, lookup_msg(attr_str, type, NULL));
3423 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3424 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3425 ret = BGP_ATTR_PARSE_ERROR;
3426 goto done;
3427 }
3428 }
3429
3430 /*
3431 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3432 * About Prefix-SID path attribute,
3433 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3434 * may only appear in a BGP Prefix-SID attribute attached to
3435 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3436 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3437 */
3438 if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST)
3439 attr->label_index = BGP_INVALID_LABEL_INDEX;
3440
3441 /* Check final read pointer is same as end pointer. */
3442 if (BGP_INPUT_PNT(peer) != endp) {
3443 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH,
3444 "%s: BGP attribute %s, length mismatch", peer->host,
3445 lookup_msg(attr_str, type, NULL));
3446 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3447 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3448
3449 ret = BGP_ATTR_PARSE_ERROR;
3450 goto done;
3451 }
3452
3453 /*
3454 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3455 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3456 * This is implemented below and will result in a NOTIFICATION. If the
3457 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3458 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3459 * message SHOULD NOT be sent. This is implemented elsewhere.
3460 *
3461 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3462 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3463 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3464 * speaker that receives the message SHOULD ignore this attribute.
3465 */
3466 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3467 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
3468 if (bgp_attr_nexthop_valid(peer, attr) < 0) {
3469 ret = BGP_ATTR_PARSE_ERROR;
3470 goto done;
3471 }
3472 }
3473
3474 /* Check all mandatory well-known attributes are present */
3475 ret = bgp_attr_check(peer, attr);
3476 if (ret < 0)
3477 goto done;
3478
3479 /*
3480 * At this place we can see whether we got AS4_PATH and/or
3481 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3482 * We can not do this before we've read all attributes because
3483 * the as4 handling does not say whether AS4_PATH has to be sent
3484 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3485 * in relationship to AGGREGATOR.
3486 * So, to be defensive, we are not relying on any order and read
3487 * all attributes first, including these 32bit ones, and now,
3488 * afterwards, we look what and if something is to be done for as4.
3489 *
3490 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3491 * MP_UNREACH_NLRI.
3492 */
3493 /* actually... this doesn't ever return failure currently, but
3494 * better safe than sorry */
3495 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))
3496 && bgp_attr_munge_as4_attrs(peer, attr, as4_path, as4_aggregator,
3497 &as4_aggregator_addr)) {
3498 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3499 BGP_NOTIFY_UPDATE_MAL_ATTR);
3500 ret = BGP_ATTR_PARSE_ERROR;
3501 goto done;
3502 }
3503
3504 /*
3505 * Finally do the checks on the aspath we did not do yet
3506 * because we waited for a potentially synthesized aspath.
3507 */
3508 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
3509 ret = bgp_attr_aspath_check(peer, attr);
3510 if (ret != BGP_ATTR_PARSE_PROCEED)
3511 goto done;
3512 }
3513
3514 ret = BGP_ATTR_PARSE_PROCEED;
3515done:
3516
3517 /*
3518 * At this stage, we have done all fiddling with as4, and the
3519 * resulting info is in attr->aggregator resp. attr->aspath so
3520 * we can chuck as4_aggregator and as4_path alltogether in order
3521 * to save memory
3522 */
3523 if (as4_path) {
3524 /*
3525 * unintern - it is in the hash
3526 * The flag that we got this is still there, but that
3527 * does not do any trouble
3528 */
3529 aspath_unintern(&as4_path);
3530 }
3531
3532 transit = bgp_attr_get_transit(attr);
3533 if (ret != BGP_ATTR_PARSE_ERROR) {
3534 /* Finally intern unknown attribute. */
3535 if (transit)
3536 bgp_attr_set_transit(attr, transit_intern(transit));
3537 if (attr->encap_subtlvs)
3538 attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
3539 ENCAP_SUBTLV_TYPE);
3540#ifdef ENABLE_BGP_VNC
3541 struct bgp_attr_encap_subtlv *vnc_subtlvs =
3542 bgp_attr_get_vnc_subtlvs(attr);
3543
3544 if (vnc_subtlvs)
3545 bgp_attr_set_vnc_subtlvs(
3546 attr,
3547 encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
3548#endif
3549 } else {
3550 if (transit) {
3551 transit_free(transit);
3552 bgp_attr_set_transit(attr, NULL);
3553 }
3554
3555 bgp_attr_flush_encap(attr);
3556 };
3557
3558 /* Sanity checks */
3559 transit = bgp_attr_get_transit(attr);
3560 if (transit)
3561 assert(transit->refcnt > 0);
3562 if (attr->encap_subtlvs)
3563 assert(attr->encap_subtlvs->refcnt > 0);
3564#ifdef ENABLE_BGP_VNC
3565 struct bgp_attr_encap_subtlv *vnc_subtlvs =
3566 bgp_attr_get_vnc_subtlvs(attr);
3567
3568 if (vnc_subtlvs)
3569 assert(vnc_subtlvs->refcnt > 0);
3570#endif
3571
3572 return ret;
3573}
3574
3575/*
3576 * Extract the tunnel type from extended community
3577 */
3578void bgp_attr_extcom_tunnel_type(struct attr *attr,
3579 bgp_encap_types *tunnel_type)
3580{
3581 struct ecommunity *ecom;
3582 uint32_t i;
3583
3584 if (!attr)
3585 return;
3586
3587 ecom = attr->ecommunity;
3588 if (!ecom || !ecom->size)
3589 return;
3590
3591 for (i = 0; i < ecom->size; i++) {
3592 uint8_t *pnt;
3593 uint8_t type, sub_type;
3594
3595 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
3596 type = pnt[0];
3597 sub_type = pnt[1];
3598 if (!(type == ECOMMUNITY_ENCODE_OPAQUE &&
3599 sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP))
3600 continue;
3601 *tunnel_type = ((pnt[6] << 8) | pnt[7]);
3602 return;
3603 }
3604
3605 return;
3606}
3607
3608size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
3609 safi_t safi, struct bpacket_attr_vec_arr *vecarr,
3610 struct attr *attr)
3611{
3612 size_t sizep;
3613 iana_afi_t pkt_afi;
3614 iana_safi_t pkt_safi;
3615 afi_t nh_afi;
3616
3617 /* Set extended bit always to encode the attribute length as 2 bytes */
3618 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
3619 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
3620 sizep = stream_get_endp(s);
3621 stream_putw(s, 0); /* Marker: Attribute length. */
3622
3623
3624 /* Convert AFI, SAFI to values for packet. */
3625 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
3626
3627 stream_putw(s, pkt_afi); /* AFI */
3628 stream_putc(s, pkt_safi); /* SAFI */
3629
3630 /* Nexthop AFI */
3631 if (afi == AFI_IP
3632 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST
3633 || safi == SAFI_MPLS_VPN || safi == SAFI_MULTICAST))
3634 nh_afi = peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : AFI_IP;
3635 else if (safi == SAFI_FLOWSPEC)
3636 nh_afi = afi;
3637 else
3638 nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
3639
3640 /* Nexthop */
3641 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, attr);
3642 switch (nh_afi) {
3643 case AFI_IP:
3644 switch (safi) {
3645 case SAFI_UNICAST:
3646 case SAFI_MULTICAST:
3647 case SAFI_LABELED_UNICAST:
3648 stream_putc(s, 4);
3649 stream_put_ipv4(s, attr->nexthop.s_addr);
3650 break;
3651 case SAFI_MPLS_VPN:
3652 stream_putc(s, 12);
3653 stream_putl(s, 0); /* RD = 0, per RFC */
3654 stream_putl(s, 0);
3655 stream_put(s, &attr->mp_nexthop_global_in, 4);
3656 break;
3657 case SAFI_ENCAP:
3658 case SAFI_EVPN:
3659 stream_putc(s, 4);
3660 stream_put(s, &attr->mp_nexthop_global_in, 4);
3661 break;
3662 case SAFI_FLOWSPEC:
3663 if (attr->mp_nexthop_len == 0)
3664 stream_putc(s, 0); /* no nexthop for flowspec */
3665 else {
3666 stream_putc(s, attr->mp_nexthop_len);
3667 stream_put_ipv4(s, attr->nexthop.s_addr);
3668 }
3669 default:
3670 break;
3671 }
3672 break;
3673 case AFI_IP6:
3674 switch (safi) {
3675 case SAFI_UNICAST:
3676 case SAFI_MULTICAST:
3677 case SAFI_LABELED_UNICAST:
3678 case SAFI_EVPN: {
3679 if (attr->mp_nexthop_len
3680 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3681 stream_putc(s,
3682 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
3683 stream_put(s, &attr->mp_nexthop_global,
3684 IPV6_MAX_BYTELEN);
3685 stream_put(s, &attr->mp_nexthop_local,
3686 IPV6_MAX_BYTELEN);
3687 } else {
3688 stream_putc(s, IPV6_MAX_BYTELEN);
3689 stream_put(s, &attr->mp_nexthop_global,
3690 IPV6_MAX_BYTELEN);
3691 }
3692 } break;
3693 case SAFI_MPLS_VPN: {
3694 if (attr->mp_nexthop_len
3695 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
3696 stream_putc(s, 24);
3697 stream_putl(s, 0); /* RD = 0, per RFC */
3698 stream_putl(s, 0);
3699 stream_put(s, &attr->mp_nexthop_global,
3700 IPV6_MAX_BYTELEN);
3701 } else if (attr->mp_nexthop_len
3702 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3703 stream_putc(s, 48);
3704 stream_putl(s, 0); /* RD = 0, per RFC */
3705 stream_putl(s, 0);
3706 stream_put(s, &attr->mp_nexthop_global,
3707 IPV6_MAX_BYTELEN);
3708 stream_putl(s, 0); /* RD = 0, per RFC */
3709 stream_putl(s, 0);
3710 stream_put(s, &attr->mp_nexthop_local,
3711 IPV6_MAX_BYTELEN);
3712 }
3713 } break;
3714 case SAFI_ENCAP:
3715 stream_putc(s, IPV6_MAX_BYTELEN);
3716 stream_put(s, &attr->mp_nexthop_global,
3717 IPV6_MAX_BYTELEN);
3718 break;
3719 case SAFI_FLOWSPEC:
3720 stream_putc(s, 0); /* no nexthop for flowspec */
3721 default:
3722 break;
3723 }
3724 break;
3725 default:
3726 if (safi != SAFI_FLOWSPEC)
3727 flog_err(
3728 EC_BGP_ATTR_NH_SEND_LEN,
3729 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3730 peer->host, afi, safi, attr->mp_nexthop_len);
3731 break;
3732 }
3733
3734 /* SNPA */
3735 stream_putc(s, 0);
3736 return sizep;
3737}
3738
3739void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
3740 const struct prefix *p,
3741 const struct prefix_rd *prd, mpls_label_t *label,
3742 uint32_t num_labels, bool addpath_capable,
3743 uint32_t addpath_tx_id, struct attr *attr)
3744{
3745 if (safi == SAFI_MPLS_VPN) {
3746 if (addpath_capable)
3747 stream_putl(s, addpath_tx_id);
3748 /* Label, RD, Prefix write. */
3749 stream_putc(s, p->prefixlen + 88);
3750 stream_put(s, label, BGP_LABEL_BYTES);
3751 stream_put(s, prd->val, 8);
3752 stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
3753 } else if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
3754 /* EVPN prefix - contents depend on type */
3755 bgp_evpn_encode_prefix(s, p, prd, label, num_labels, attr,
3756 addpath_capable, addpath_tx_id);
3757 } else if (safi == SAFI_LABELED_UNICAST) {
3758 /* Prefix write with label. */
3759 stream_put_labeled_prefix(s, p, label, addpath_capable,
3760 addpath_tx_id);
3761 } else if (safi == SAFI_FLOWSPEC) {
3762 stream_putc(s, p->u.prefix_flowspec.prefixlen);
3763 stream_put(s, (const void *)p->u.prefix_flowspec.ptr,
3764 p->u.prefix_flowspec.prefixlen);
3765 } else
3766 stream_put_prefix_addpath(s, p, addpath_capable, addpath_tx_id);
3767}
3768
3769size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
3770 const struct prefix *p)
3771{
3772 int size = PSIZE(p->prefixlen);
3773 if (safi == SAFI_MPLS_VPN)
3774 size += 88;
3775 else if (safi == SAFI_LABELED_UNICAST)
3776 size += BGP_LABEL_BYTES;
3777 else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3778 size += 232; // TODO: Maximum possible for type-2, type-3 and
3779 // type-5
3780 return size;
3781}
3782
3783/*
3784 * Encodes the tunnel encapsulation attribute,
3785 * and with ENABLE_BGP_VNC the VNC attribute which uses
3786 * almost the same TLV format
3787 */
3788static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
3789 struct stream *s, struct attr *attr,
3790 uint8_t attrtype)
3791{
3792 unsigned int attrlenfield = 0;
3793 unsigned int attrhdrlen = 0;
3794 struct bgp_attr_encap_subtlv *subtlvs;
3795 struct bgp_attr_encap_subtlv *st;
3796 const char *attrname;
3797
3798 if (!attr || (attrtype == BGP_ATTR_ENCAP
3799 && (!attr->encap_tunneltype
3800 || attr->encap_tunneltype == BGP_ENCAP_TYPE_MPLS)))
3801 return;
3802
3803 switch (attrtype) {
3804 case BGP_ATTR_ENCAP:
3805 attrname = "Tunnel Encap";
3806 subtlvs = attr->encap_subtlvs;
3807 if (subtlvs == NULL) /* nothing to do */
3808 return;
3809 /*
3810 * The tunnel encap attr has an "outer" tlv.
3811 * T = tunneltype,
3812 * L = total length of subtlvs,
3813 * V = concatenated subtlvs.
3814 */
3815 attrlenfield = 2 + 2; /* T + L */
3816 attrhdrlen = 1 + 1; /* subTLV T + L */
3817 break;
3818
3819#ifdef ENABLE_BGP_VNC_ATTR
3820 case BGP_ATTR_VNC:
3821 attrname = "VNC";
3822 subtlvs = bgp_attr_get_vnc_subtlvs(attr);
3823 if (subtlvs == NULL) /* nothing to do */
3824 return;
3825 attrlenfield = 0; /* no outer T + L */
3826 attrhdrlen = 2 + 2; /* subTLV T + L */
3827 break;
3828#endif
3829
3830 default:
3831 assert(0);
3832 }
3833
3834 /* compute attr length */
3835 for (st = subtlvs; st; st = st->next) {
3836 attrlenfield += (attrhdrlen + st->length);
3837 }
3838
3839 if (attrlenfield > 0xffff) {
3840 zlog_info("%s attribute is too long (length=%d), can't send it",
3841 attrname, attrlenfield);
3842 return;
3843 }
3844
3845 if (attrlenfield > 0xff) {
3846 /* 2-octet length field */
3847 stream_putc(s,
3848 BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
3849 | BGP_ATTR_FLAG_EXTLEN);
3850 stream_putc(s, attrtype);
3851 stream_putw(s, attrlenfield & 0xffff);
3852 } else {
3853 /* 1-octet length field */
3854 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL);
3855 stream_putc(s, attrtype);
3856 stream_putc(s, attrlenfield & 0xff);
3857 }
3858
3859 if (attrtype == BGP_ATTR_ENCAP) {
3860 /* write outer T+L */
3861 stream_putw(s, attr->encap_tunneltype);
3862 stream_putw(s, attrlenfield - 4);
3863 }
3864
3865 /* write each sub-tlv */
3866 for (st = subtlvs; st; st = st->next) {
3867 if (attrtype == BGP_ATTR_ENCAP) {
3868 stream_putc(s, st->type);
3869 stream_putc(s, st->length);
3870#ifdef ENABLE_BGP_VNC
3871 } else {
3872 stream_putw(s, st->type);
3873 stream_putw(s, st->length);
3874#endif
3875 }
3876 stream_put(s, st->value, st->length);
3877 }
3878}
3879
3880void bgp_packet_mpattr_end(struct stream *s, size_t sizep)
3881{
3882 /* Set MP attribute length. Don't count the (2) bytes used to encode
3883 the attr length */
3884 stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2);
3885}
3886
3887static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
3888{
3889 if (!BGP_AS_IS_PRIVATE(peer->local_as)
3890 || (BGP_AS_IS_PRIVATE(peer->local_as)
3891 && !CHECK_FLAG(peer->af_flags[afi][safi],
3892 PEER_FLAG_REMOVE_PRIVATE_AS)
3893 && !CHECK_FLAG(peer->af_flags[afi][safi],
3894 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
3895 && !CHECK_FLAG(peer->af_flags[afi][safi],
3896 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
3897 && !CHECK_FLAG(peer->af_flags[afi][safi],
3898 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)))
3899 return true;
3900 return false;
3901}
3902
3903/* Make attribute packet. */
3904bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
3905 struct stream *s, struct attr *attr,
3906 struct bpacket_attr_vec_arr *vecarr,
3907 struct prefix *p, afi_t afi, safi_t safi,
3908 struct peer *from, struct prefix_rd *prd,
3909 mpls_label_t *label, uint32_t num_labels,
3910 bool addpath_capable, uint32_t addpath_tx_id)
3911{
3912 size_t cp;
3913 size_t aspath_sizep;
3914 struct aspath *aspath;
3915 int send_as4_path = 0;
3916 int send_as4_aggregator = 0;
3917 bool use32bit = CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
3918 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV);
3919
3920 if (!bgp)
3921 bgp = peer->bgp;
3922
3923 /* Remember current pointer. */
3924 cp = stream_get_endp(s);
3925
3926 if (p
3927 && !((afi == AFI_IP && safi == SAFI_UNICAST)
3928 && !peer_cap_enhe(peer, afi, safi))) {
3929 size_t mpattrlen_pos = 0;
3930
3931 mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
3932 vecarr, attr);
3933 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
3934 num_labels, addpath_capable,
3935 addpath_tx_id, attr);
3936 bgp_packet_mpattr_end(s, mpattrlen_pos);
3937 }
3938
3939 /* Origin attribute. */
3940 stream_putc(s, BGP_ATTR_FLAG_TRANS);
3941 stream_putc(s, BGP_ATTR_ORIGIN);
3942 stream_putc(s, 1);
3943 stream_putc(s, attr->origin);
3944
3945 /* AS path attribute. */
3946
3947 /* If remote-peer is EBGP */
3948 if (peer->sort == BGP_PEER_EBGP
3949 && (!CHECK_FLAG(peer->af_flags[afi][safi],
3950 PEER_FLAG_AS_PATH_UNCHANGED)
3951 || attr->aspath->segments == NULL)
3952 && (!CHECK_FLAG(peer->af_flags[afi][safi],
3953 PEER_FLAG_RSERVER_CLIENT))) {
3954 aspath = aspath_dup(attr->aspath);
3955
3956 /* Even though we may not be configured for confederations we
3957 * may have
3958 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3959 aspath = aspath_delete_confed_seq(aspath);
3960
3961 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
3962 /* Stuff our path CONFED_ID on the front */
3963 aspath = aspath_add_seq(aspath, bgp->confed_id);
3964 } else {
3965 if (peer->change_local_as) {
3966 /* If replace-as is specified, we only use the
3967 change_local_as when
3968 advertising routes. */
3969 if (!CHECK_FLAG(peer->flags,
3970 PEER_FLAG_LOCAL_AS_REPLACE_AS))
3971 if (bgp_append_local_as(peer, afi,
3972 safi))
3973 aspath = aspath_add_seq(
3974 aspath, peer->local_as);
3975 aspath = aspath_add_seq(aspath,
3976 peer->change_local_as);
3977 } else {
3978 aspath = aspath_add_seq(aspath, peer->local_as);
3979 }
3980 }
3981 } else if (peer->sort == BGP_PEER_CONFED) {
3982 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3983 * thing */
3984 aspath = aspath_dup(attr->aspath);
3985 aspath = aspath_add_confed_seq(aspath, peer->local_as);
3986 } else
3987 aspath = attr->aspath;
3988
3989 /* If peer is not AS4 capable, then:
3990 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3991 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3992 * segment
3993 * types are in it (i.e. exclude them if they are there)
3994 * AND do this only if there is at least one asnum > 65535 in the
3995 * path!
3996 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3997 * change
3998 * all ASnums > 65535 to BGP_AS_TRANS
3999 */
4000
4001 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4002 stream_putc(s, BGP_ATTR_AS_PATH);
4003 aspath_sizep = stream_get_endp(s);
4004 stream_putw(s, 0);
4005 stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, use32bit));
4006
4007 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4008 * in the path
4009 */
4010 if (!use32bit && aspath_has_as4(aspath))
4011 send_as4_path =
4012 1; /* we'll do this later, at the correct place */
4013
4014 /* Nexthop attribute. */
4015 if (afi == AFI_IP && safi == SAFI_UNICAST
4016 && !peer_cap_enhe(peer, afi, safi)) {
4017 afi_t nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
4018
4019 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
4020 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4021 stream_putc(s, BGP_ATTR_NEXT_HOP);
4022 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4023 attr);
4024 stream_putc(s, 4);
4025 stream_put_ipv4(s, attr->nexthop.s_addr);
4026 } else if (peer_cap_enhe(from, afi, safi)
4027 || (nh_afi == AFI_IP6)) {
4028 /*
4029 * Likely this is the case when an IPv4 prefix was
4030 * received with Extended Next-hop capability in this
4031 * or another vrf and is now being advertised to
4032 * non-ENHE peers. Since peer_cap_enhe only checks
4033 * peers in this vrf, also check the nh_afi to catch
4034 * the case where the originator was in another vrf.
4035 * Setting the mandatory (ipv4) next-hop attribute here
4036 * to enable implicit next-hop self with correct A-F
4037 * (ipv4 address family).
4038 */
4039 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4040 stream_putc(s, BGP_ATTR_NEXT_HOP);
4041 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4042 NULL);
4043 stream_putc(s, 4);
4044 stream_put_ipv4(s, 0);
4045 }
4046 }
4047
4048 /* MED attribute. */
4049 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)
4050 || bgp->maxmed_active) {
4051 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4052 stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4053 stream_putc(s, 4);
4054 stream_putl(s, (bgp->maxmed_active ? bgp->maxmed_value
4055 : attr->med));
4056 }
4057
4058 /* Local preference. */
4059 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
4060 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4061 stream_putc(s, BGP_ATTR_LOCAL_PREF);
4062 stream_putc(s, 4);
4063 stream_putl(s, attr->local_pref);
4064 }
4065
4066 /* Atomic aggregate. */
4067 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4068 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4069 stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4070 stream_putc(s, 0);
4071 }
4072
4073 /* Aggregator. */
4074 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4075 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4076 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4077 stream_putc(s, BGP_ATTR_AGGREGATOR);
4078
4079 if (use32bit) {
4080 /* AS4 capable peer */
4081 stream_putc(s, 8);
4082 stream_putl(s, attr->aggregator_as);
4083 } else {
4084 /* 2-byte AS peer */
4085 stream_putc(s, 6);
4086
4087 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4088 * used? */
4089 if (attr->aggregator_as > UINT16_MAX) {
4090 stream_putw(s, BGP_AS_TRANS);
4091
4092 /* we have to send AS4_AGGREGATOR, too.
4093 * we'll do that later in order to send
4094 * attributes in ascending
4095 * order.
4096 */
4097 send_as4_aggregator = 1;
4098 } else
4099 stream_putw(s, (uint16_t)attr->aggregator_as);
4100 }
4101 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4102 }
4103
4104 /* Community attribute. */
4105 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
4106 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
4107 if (attr->community->size * 4 > 255) {
4108 stream_putc(s,
4109 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4110 | BGP_ATTR_FLAG_EXTLEN);
4111 stream_putc(s, BGP_ATTR_COMMUNITIES);
4112 stream_putw(s, attr->community->size * 4);
4113 } else {
4114 stream_putc(s,
4115 BGP_ATTR_FLAG_OPTIONAL
4116 | BGP_ATTR_FLAG_TRANS);
4117 stream_putc(s, BGP_ATTR_COMMUNITIES);
4118 stream_putc(s, attr->community->size * 4);
4119 }
4120 stream_put(s, attr->community->val, attr->community->size * 4);
4121 }
4122
4123 /*
4124 * Large Community attribute.
4125 */
4126 if (CHECK_FLAG(peer->af_flags[afi][safi],
4127 PEER_FLAG_SEND_LARGE_COMMUNITY)
4128 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
4129 if (lcom_length(attr->lcommunity) > 255) {
4130 stream_putc(s,
4131 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4132 | BGP_ATTR_FLAG_EXTLEN);
4133 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4134 stream_putw(s, lcom_length(attr->lcommunity));
4135 } else {
4136 stream_putc(s,
4137 BGP_ATTR_FLAG_OPTIONAL
4138 | BGP_ATTR_FLAG_TRANS);
4139 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4140 stream_putc(s, lcom_length(attr->lcommunity));
4141 }
4142 stream_put(s, attr->lcommunity->val,
4143 lcom_length(attr->lcommunity));
4144 }
4145
4146 /* Route Reflector. */
4147 if (peer->sort == BGP_PEER_IBGP && from
4148 && from->sort == BGP_PEER_IBGP) {
4149 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
4150
4151 /* Originator ID. */
4152 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4153 stream_putc(s, BGP_ATTR_ORIGINATOR_ID);
4154 stream_putc(s, 4);
4155
4156 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
4157 stream_put_in_addr(s, &attr->originator_id);
4158 else
4159 stream_put_in_addr(s, &from->remote_id);
4160
4161 /* Cluster list. */
4162 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4163 stream_putc(s, BGP_ATTR_CLUSTER_LIST);
4164
4165 if (cluster) {
4166 stream_putc(s, cluster->length + 4);
4167 /* If this peer configuration's parent BGP has
4168 * cluster_id. */
4169 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4170 stream_put_in_addr(s, &bgp->cluster_id);
4171 else
4172 stream_put_in_addr(s, &bgp->router_id);
4173 stream_put(s, cluster->list, cluster->length);
4174 } else {
4175 stream_putc(s, 4);
4176 /* If this peer configuration's parent BGP has
4177 * cluster_id. */
4178 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4179 stream_put_in_addr(s, &bgp->cluster_id);
4180 else
4181 stream_put_in_addr(s, &bgp->router_id);
4182 }
4183 }
4184
4185 /* Extended Communities attribute. */
4186 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
4187 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4188 if (peer->sort == BGP_PEER_IBGP
4189 || peer->sort == BGP_PEER_CONFED) {
4190 if (attr->ecommunity->size * 8 > 255) {
4191 stream_putc(s,
4192 BGP_ATTR_FLAG_OPTIONAL
4193 | BGP_ATTR_FLAG_TRANS
4194 | BGP_ATTR_FLAG_EXTLEN);
4195 stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
4196 stream_putw(s, attr->ecommunity->size * 8);
4197 } else {
4198 stream_putc(s,
4199 BGP_ATTR_FLAG_OPTIONAL
4200 | BGP_ATTR_FLAG_TRANS);
4201 stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
4202 stream_putc(s, attr->ecommunity->size * 8);
4203 }
4204 stream_put(s, attr->ecommunity->val,
4205 attr->ecommunity->size * 8);
4206 } else {
4207 uint8_t *pnt;
4208 int tbit;
4209 int ecom_tr_size = 0;
4210 uint32_t i;
4211
4212 for (i = 0; i < attr->ecommunity->size; i++) {
4213 pnt = attr->ecommunity->val + (i * 8);
4214 tbit = *pnt;
4215
4216 if (CHECK_FLAG(tbit,
4217 ECOMMUNITY_FLAG_NON_TRANSITIVE))
4218 continue;
4219
4220 ecom_tr_size++;
4221 }
4222
4223 if (ecom_tr_size) {
4224 if (ecom_tr_size * 8 > 255) {
4225 stream_putc(
4226 s,
4227 BGP_ATTR_FLAG_OPTIONAL
4228 | BGP_ATTR_FLAG_TRANS
4229 | BGP_ATTR_FLAG_EXTLEN);
4230 stream_putc(s,
4231 BGP_ATTR_EXT_COMMUNITIES);
4232 stream_putw(s, ecom_tr_size * 8);
4233 } else {
4234 stream_putc(
4235 s,
4236 BGP_ATTR_FLAG_OPTIONAL
4237 | BGP_ATTR_FLAG_TRANS);
4238 stream_putc(s,
4239 BGP_ATTR_EXT_COMMUNITIES);
4240 stream_putc(s, ecom_tr_size * 8);
4241 }
4242
4243 for (i = 0; i < attr->ecommunity->size; i++) {
4244 pnt = attr->ecommunity->val + (i * 8);
4245 tbit = *pnt;
4246
4247 if (CHECK_FLAG(
4248 tbit,
4249 ECOMMUNITY_FLAG_NON_TRANSITIVE))
4250 continue;
4251
4252 stream_put(s, pnt, 8);
4253 }
4254 }
4255 }
4256 }
4257
4258 /* Label index attribute. */
4259 if (safi == SAFI_LABELED_UNICAST) {
4260 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
4261 uint32_t label_index;
4262
4263 label_index = attr->label_index;
4264
4265 if (label_index != BGP_INVALID_LABEL_INDEX) {
4266 stream_putc(s,
4267 BGP_ATTR_FLAG_OPTIONAL
4268 | BGP_ATTR_FLAG_TRANS);
4269 stream_putc(s, BGP_ATTR_PREFIX_SID);
4270 stream_putc(s, 10);
4271 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
4272 stream_putw(s,
4273 BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
4274 stream_putc(s, 0); // reserved
4275 stream_putw(s, 0); // flags
4276 stream_putl(s, label_index);
4277 }
4278 }
4279 }
4280
4281 /* SRv6 Service Information Attribute. */
4282 if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN) {
4283 if (attr->srv6_l3vpn) {
4284 uint8_t subtlv_len =
4285 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4286 + BGP_ATTR_MIN_LEN
4287 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH;
4288 uint8_t tlv_len = subtlv_len + BGP_ATTR_MIN_LEN + 1;
4289 uint8_t attr_len = tlv_len + BGP_ATTR_MIN_LEN;
4290 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4291 | BGP_ATTR_FLAG_TRANS);
4292 stream_putc(s, BGP_ATTR_PREFIX_SID);
4293 stream_putc(s, attr_len);
4294 stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE);
4295 stream_putw(s, tlv_len);
4296 stream_putc(s, 0); /* reserved */
4297 stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO);
4298 stream_putw(s, subtlv_len);
4299 stream_putc(s, 0); /* reserved */
4300 stream_put(s, &attr->srv6_l3vpn->sid,
4301 sizeof(attr->srv6_l3vpn->sid)); /* sid */
4302 stream_putc(s, 0); /* sid_flags */
4303 stream_putw(s, 0xffff); /* endpoint */
4304 stream_putc(s, 0); /* reserved */
4305 stream_putc(
4306 s,
4307 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE);
4308 stream_putw(
4309 s,
4310 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH);
4311 stream_putc(s, attr->srv6_l3vpn->loc_block_len);
4312 stream_putc(s, attr->srv6_l3vpn->loc_node_len);
4313 stream_putc(s, attr->srv6_l3vpn->func_len);
4314 stream_putc(s, attr->srv6_l3vpn->arg_len);
4315 stream_putc(s, attr->srv6_l3vpn->transposition_len);
4316 stream_putc(s, attr->srv6_l3vpn->transposition_offset);
4317 } else if (attr->srv6_vpn) {
4318 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4319 | BGP_ATTR_FLAG_TRANS);
4320 stream_putc(s, BGP_ATTR_PREFIX_SID);
4321 stream_putc(s, 22); /* tlv len */
4322 stream_putc(s, BGP_PREFIX_SID_VPN_SID);
4323 stream_putw(s, 0x13); /* tlv len */
4324 stream_putc(s, 0x00); /* reserved */
4325 stream_putc(s, 0x01); /* sid_type */
4326 stream_putc(s, 0x00); /* sif_flags */
4327 stream_put(s, &attr->srv6_vpn->sid,
4328 sizeof(attr->srv6_vpn->sid)); /* sid */
4329 }
4330 }
4331
4332 if (send_as4_path) {
4333 /* If the peer is NOT As4 capable, AND */
4334 /* there are ASnums > 65535 in path THEN
4335 * give out AS4_PATH */
4336
4337 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4338 * path segments!
4339 * Hm, I wonder... confederation things *should* only be at
4340 * the beginning of an aspath, right? Then we should use
4341 * aspath_delete_confed_seq for this, because it is already
4342 * there! (JK)
4343 * Folks, talk to me: what is reasonable here!?
4344 */
4345 aspath = aspath_delete_confed_seq(aspath);
4346
4347 stream_putc(s,
4348 BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4349 | BGP_ATTR_FLAG_EXTLEN);
4350 stream_putc(s, BGP_ATTR_AS4_PATH);
4351 aspath_sizep = stream_get_endp(s);
4352 stream_putw(s, 0);
4353 stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, 1));
4354 }
4355
4356 if (aspath != attr->aspath)
4357 aspath_free(aspath);
4358
4359 if (send_as4_aggregator) {
4360 /* send AS4_AGGREGATOR, at this place */
4361 /* this section of code moved here in order to ensure the
4362 * correct
4363 * *ascending* order of attributes
4364 */
4365 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4366 stream_putc(s, BGP_ATTR_AS4_AGGREGATOR);
4367 stream_putc(s, 8);
4368 stream_putl(s, attr->aggregator_as);
4369 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4370 }
4371
4372 if (((afi == AFI_IP || afi == AFI_IP6)
4373 && (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
4374 || (afi == AFI_L2VPN && safi == SAFI_EVPN)) {
4375 /* Tunnel Encap attribute */
4376 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
4377
4378#ifdef ENABLE_BGP_VNC_ATTR
4379 /* VNC attribute */
4380 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC);
4381#endif
4382 }
4383
4384 /* PMSI Tunnel */
4385 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
4386 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4387 stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
4388 stream_putc(s, 9); // Length
4389 stream_putc(s, 0); // Flags
4390 stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr));
4391 stream_put(s, &(attr->label),
4392 BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
4393 stream_put_ipv4(s, attr->nexthop.s_addr);
4394 // Unicast tunnel endpoint IP address
4395 }
4396
4397 /* Unknown transit attribute. */
4398 struct transit *transit = bgp_attr_get_transit(attr);
4399
4400 if (transit)
4401 stream_put(s, transit->val, transit->length);
4402
4403 /* Return total size of attribute. */
4404 return stream_get_endp(s) - cp;
4405}
4406
4407size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
4408{
4409 unsigned long attrlen_pnt;
4410 iana_afi_t pkt_afi;
4411 iana_safi_t pkt_safi;
4412
4413 /* Set extended bit always to encode the attribute length as 2 bytes */
4414 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
4415 stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI);
4416
4417 attrlen_pnt = stream_get_endp(s);
4418 stream_putw(s, 0); /* Length of this attribute. */
4419
4420 /* Convert AFI, SAFI to values for packet. */
4421 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
4422
4423 stream_putw(s, pkt_afi);
4424 stream_putc(s, pkt_safi);
4425
4426 return attrlen_pnt;
4427}
4428
4429void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
4430 afi_t afi, safi_t safi,
4431 const struct prefix_rd *prd,
4432 mpls_label_t *label, uint32_t num_labels,
4433 bool addpath_capable, uint32_t addpath_tx_id,
4434 struct attr *attr)
4435{
4436 uint8_t wlabel[3] = {0x80, 0x00, 0x00};
4437
4438 if (safi == SAFI_LABELED_UNICAST) {
4439 label = (mpls_label_t *)wlabel;
4440 num_labels = 1;
4441 }
4442
4443 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
4444 addpath_capable, addpath_tx_id, attr);
4445}
4446
4447void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt)
4448{
4449 bgp_packet_mpattr_end(s, attrlen_pnt);
4450}
4451
4452/* Initialization of attribute. */
4453void bgp_attr_init(void)
4454{
4455 aspath_init();
4456 attrhash_init();
4457 community_init();
4458 ecommunity_init();
4459 lcommunity_init();
4460 cluster_init();
4461 transit_init();
4462 encap_init();
4463 srv6_init();
4464}
4465
4466void bgp_attr_finish(void)
4467{
4468 aspath_finish();
4469 attrhash_finish();
4470 community_finish();
4471 ecommunity_finish();
4472 lcommunity_finish();
4473 cluster_finish();
4474 transit_finish();
4475 encap_finish();
4476 srv6_finish();
4477}
4478
4479/* Make attribute packet. */
4480void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
4481 const struct prefix *prefix)
4482{
4483 unsigned long cp;
4484 unsigned long len;
4485 size_t aspath_lenp;
4486 struct aspath *aspath;
4487 bool addpath_capable = false;
4488 uint32_t addpath_tx_id = 0;
4489
4490 /* Remember current pointer. */
4491 cp = stream_get_endp(s);
4492
4493 /* Place holder of length. */
4494 stream_putw(s, 0);
4495
4496 /* Origin attribute. */
4497 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4498 stream_putc(s, BGP_ATTR_ORIGIN);
4499 stream_putc(s, 1);
4500 stream_putc(s, attr->origin);
4501
4502 aspath = attr->aspath;
4503
4504 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4505 stream_putc(s, BGP_ATTR_AS_PATH);
4506 aspath_lenp = stream_get_endp(s);
4507 stream_putw(s, 0);
4508
4509 stream_putw_at(s, aspath_lenp, aspath_put(s, aspath, 1));
4510
4511 /* Nexthop attribute. */
4512 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4513 if (prefix != NULL && prefix->family != AF_INET6) {
4514 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4515 stream_putc(s, BGP_ATTR_NEXT_HOP);
4516 stream_putc(s, 4);
4517 stream_put_ipv4(s, attr->nexthop.s_addr);
4518 }
4519
4520 /* MED attribute. */
4521 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
4522 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4523 stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4524 stream_putc(s, 4);
4525 stream_putl(s, attr->med);
4526 }
4527
4528 /* Local preference. */
4529 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
4530 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4531 stream_putc(s, BGP_ATTR_LOCAL_PREF);
4532 stream_putc(s, 4);
4533 stream_putl(s, attr->local_pref);
4534 }
4535
4536 /* Atomic aggregate. */
4537 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4538 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4539 stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4540 stream_putc(s, 0);
4541 }
4542
4543 /* Aggregator. */
4544 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4545 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4546 stream_putc(s, BGP_ATTR_AGGREGATOR);
4547 stream_putc(s, 8);
4548 stream_putl(s, attr->aggregator_as);
4549 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4550 }
4551
4552 /* Community attribute. */
4553 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
4554 if (attr->community->size * 4 > 255) {
4555 stream_putc(s,
4556 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4557 | BGP_ATTR_FLAG_EXTLEN);
4558 stream_putc(s, BGP_ATTR_COMMUNITIES);
4559 stream_putw(s, attr->community->size * 4);
4560 } else {
4561 stream_putc(s,
4562 BGP_ATTR_FLAG_OPTIONAL
4563 | BGP_ATTR_FLAG_TRANS);
4564 stream_putc(s, BGP_ATTR_COMMUNITIES);
4565 stream_putc(s, attr->community->size * 4);
4566 }
4567 stream_put(s, attr->community->val, attr->community->size * 4);
4568 }
4569
4570 /* Large Community attribute. */
4571 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
4572 if (lcom_length(attr->lcommunity) > 255) {
4573 stream_putc(s,
4574 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4575 | BGP_ATTR_FLAG_EXTLEN);
4576 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4577 stream_putw(s, lcom_length(attr->lcommunity));
4578 } else {
4579 stream_putc(s,
4580 BGP_ATTR_FLAG_OPTIONAL
4581 | BGP_ATTR_FLAG_TRANS);
4582 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4583 stream_putc(s, lcom_length(attr->lcommunity));
4584 }
4585
4586 stream_put(s, attr->lcommunity->val,
4587 lcom_length(attr->lcommunity));
4588 }
4589
4590 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4591 if (prefix != NULL && prefix->family == AF_INET6
4592 && (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
4593 || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)) {
4594 int sizep;
4595
4596 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4597 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
4598 sizep = stream_get_endp(s);
4599
4600 /* MP header */
4601 stream_putc(s, 0); /* Marker: Attribute length. */
4602 stream_putw(s, AFI_IP6); /* AFI */
4603 stream_putc(s, SAFI_UNICAST); /* SAFI */
4604
4605 /* Next hop */
4606 stream_putc(s, attr->mp_nexthop_len);
4607 stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN);
4608 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
4609 stream_put(s, &attr->mp_nexthop_local,
4610 IPV6_MAX_BYTELEN);
4611
4612 /* SNPA */
4613 stream_putc(s, 0);
4614
4615 /* Prefix */
4616 stream_put_prefix_addpath(s, prefix, addpath_capable,
4617 addpath_tx_id);
4618
4619 /* Set MP attribute length. */
4620 stream_putc_at(s, sizep, (stream_get_endp(s) - sizep) - 1);
4621 }
4622
4623 /* Prefix SID */
4624 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
4625 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
4626 stream_putc(s,
4627 BGP_ATTR_FLAG_OPTIONAL
4628 | BGP_ATTR_FLAG_TRANS);
4629 stream_putc(s, BGP_ATTR_PREFIX_SID);
4630 stream_putc(s, 10);
4631 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
4632 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
4633 stream_putc(s, 0); // reserved
4634 stream_putw(s, 0); // flags
4635 stream_putl(s, attr->label_index);
4636 }
4637 }
4638
4639 /* Return total size of attribute. */
4640 len = stream_get_endp(s) - cp - 2;
4641 stream_putw_at(s, cp, len);
4642}