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