]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_attr.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[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();
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();
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
1609 /*
1610 * peer with AS4 => will get 4Byte ASnums
1611 * otherwise, will get 16 Bit
1612 */
1613 attr->aspath = aspath_parse(
1614 peer->curr, length,
1615 CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1616 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV));
1617
1618 /* In case of IBGP, length will be zero. */
1619 if (!attr->aspath) {
1620 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1621 "Malformed AS path from %s, length is %d", peer->host,
1622 length);
1623 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1624 0);
1625 }
1626
1627 /* Conformant BGP speakers SHOULD NOT send BGP
1628 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1629 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1630 * withdraw" error handling behavior as per [RFC7606].
1631 */
1632 if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
1633 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1634 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1635 peer);
1636 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1637 0);
1638 }
1639
1640 /* Set aspath attribute flag. */
1641 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1642
1643 return BGP_ATTR_PARSE_PROCEED;
1644 }
1645
1646 static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
1647 struct attr *const attr)
1648 {
1649 /* These checks were part of bgp_attr_aspath, but with
1650 * as4 we should to check aspath things when
1651 * aspath synthesizing with as4_path has already taken place.
1652 * Otherwise we check ASPATH and use the synthesized thing, and that is
1653 * not right.
1654 * So do the checks later, i.e. here
1655 */
1656 struct aspath *aspath;
1657
1658 /* Confederation sanity check. */
1659 if ((peer->sort == BGP_PEER_CONFED
1660 && !aspath_left_confed_check(attr->aspath))
1661 || (peer->sort == BGP_PEER_EBGP
1662 && aspath_confed_check(attr->aspath))) {
1663 flog_err(EC_BGP_ATTR_MAL_AS_PATH, "Malformed AS path from %s",
1664 peer->host);
1665 return BGP_ATTR_PARSE_WITHDRAW;
1666 }
1667
1668 /* First AS check for EBGP. */
1669 if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
1670 if (peer->sort == BGP_PEER_EBGP
1671 && !aspath_firstas_check(attr->aspath, peer->as)) {
1672 flog_err(EC_BGP_ATTR_FIRST_AS,
1673 "%s incorrect first AS (must be %u)",
1674 peer->host, peer->as);
1675 return BGP_ATTR_PARSE_WITHDRAW;
1676 }
1677 }
1678
1679 /* Codification of AS 0 Processing */
1680 if (peer->sort == BGP_PEER_EBGP && aspath_check_as_zero(attr->aspath)) {
1681 flog_err(
1682 EC_BGP_ATTR_MAL_AS_PATH,
1683 "Malformed AS path, AS number is 0 in the path from %s",
1684 peer->host);
1685 return BGP_ATTR_PARSE_WITHDRAW;
1686 }
1687
1688 /* local-as prepend */
1689 if (peer->change_local_as
1690 && !CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) {
1691 aspath = aspath_dup(attr->aspath);
1692 aspath = aspath_add_seq(aspath, peer->change_local_as);
1693 aspath_unintern(&attr->aspath);
1694 attr->aspath = aspath_intern(aspath);
1695 }
1696
1697 return BGP_ATTR_PARSE_PROCEED;
1698 }
1699
1700 /* Parse AS4 path information. This function is another wrapper of
1701 aspath_parse. */
1702 static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
1703 struct aspath **as4_path)
1704 {
1705 struct peer *const peer = args->peer;
1706 struct attr *const attr = args->attr;
1707 const bgp_size_t length = args->length;
1708
1709 *as4_path = aspath_parse(peer->curr, length, 1);
1710
1711 /* In case of IBGP, length will be zero. */
1712 if (!*as4_path) {
1713 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1714 "Malformed AS4 path from %s, length is %d", peer->host,
1715 length);
1716 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1717 0);
1718 }
1719
1720 /* Conformant BGP speakers SHOULD NOT send BGP
1721 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1722 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1723 * withdraw" error handling behavior as per [RFC7606].
1724 */
1725 if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
1726 flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1727 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1728 peer);
1729 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1730 0);
1731 }
1732
1733 /* Set aspath attribute flag. */
1734 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
1735
1736 return BGP_ATTR_PARSE_PROCEED;
1737 }
1738
1739 /*
1740 * Check that the nexthop attribute is valid.
1741 */
1742 enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
1743 struct attr *attr)
1744 {
1745 struct bgp *bgp = peer->bgp;
1746
1747 if (ipv4_martian(&attr->nexthop) && !bgp->allow_martian) {
1748 uint8_t data[7]; /* type(2) + length(1) + nhop(4) */
1749
1750 flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %pI4",
1751 &attr->nexthop);
1752 data[0] = BGP_ATTR_FLAG_TRANS;
1753 data[1] = BGP_ATTR_NEXT_HOP;
1754 data[2] = BGP_ATTR_NHLEN_IPV4;
1755 memcpy(&data[3], &attr->nexthop.s_addr, BGP_ATTR_NHLEN_IPV4);
1756 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
1757 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
1758 data, 7);
1759 return BGP_ATTR_PARSE_ERROR;
1760 }
1761
1762 return BGP_ATTR_PARSE_PROCEED;
1763 }
1764
1765 /* Nexthop attribute. */
1766 static enum bgp_attr_parse_ret
1767 bgp_attr_nexthop(struct bgp_attr_parser_args *args)
1768 {
1769 struct peer *const peer = args->peer;
1770 struct attr *const attr = args->attr;
1771 const bgp_size_t length = args->length;
1772
1773 /* Check nexthop attribute length. */
1774 if (length != 4) {
1775 flog_err(EC_BGP_ATTR_LEN,
1776 "Nexthop attribute length isn't four [%d]", length);
1777
1778 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1779 args->total);
1780 }
1781
1782 attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
1783 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1784
1785 return BGP_ATTR_PARSE_PROCEED;
1786 }
1787
1788 /* MED atrribute. */
1789 static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
1790 {
1791 struct peer *const peer = args->peer;
1792 struct attr *const attr = args->attr;
1793 const bgp_size_t length = args->length;
1794
1795 /* Length check. */
1796 if (length != 4) {
1797 flog_err(EC_BGP_ATTR_LEN,
1798 "MED attribute length isn't four [%d]", length);
1799
1800 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1801 args->total);
1802 }
1803
1804 attr->med = stream_getl(peer->curr);
1805
1806 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1807
1808 return BGP_ATTR_PARSE_PROCEED;
1809 }
1810
1811 /* Local preference attribute. */
1812 static enum bgp_attr_parse_ret
1813 bgp_attr_local_pref(struct bgp_attr_parser_args *args)
1814 {
1815 struct peer *const peer = args->peer;
1816 struct attr *const attr = args->attr;
1817 const bgp_size_t length = args->length;
1818
1819 /* if received from an internal neighbor, it SHALL be considered
1820 * malformed if its length is not equal to 4. If malformed, the
1821 * UPDATE message SHALL be handled using the approach of "treat-as-
1822 * withdraw".
1823 */
1824 if (peer->sort == BGP_PEER_IBGP && length != 4) {
1825 flog_err(EC_BGP_ATTR_LEN,
1826 "LOCAL_PREF attribute length isn't 4 [%u]", length);
1827 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1828 args->total);
1829 }
1830
1831 /* If it is contained in an UPDATE message that is received from an
1832 external peer, then this attribute MUST be ignored by the
1833 receiving speaker. */
1834 if (peer->sort == BGP_PEER_EBGP) {
1835 STREAM_FORWARD_GETP(peer->curr, length);
1836 return BGP_ATTR_PARSE_PROCEED;
1837 }
1838
1839 STREAM_GETL(peer->curr, attr->local_pref);
1840
1841 /* Set the local-pref flag. */
1842 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1843
1844 return BGP_ATTR_PARSE_PROCEED;
1845
1846 stream_failure:
1847 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1848 args->total);
1849 }
1850
1851 /* Atomic aggregate. */
1852 static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
1853 {
1854 struct peer *const peer = args->peer;
1855 struct attr *const attr = args->attr;
1856 const bgp_size_t length = args->length;
1857
1858 /* Length check. */
1859 if (length != 0) {
1860 flog_err(EC_BGP_ATTR_LEN,
1861 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1862 length);
1863 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1864 args->total);
1865 }
1866
1867 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1868 goto atomic_ignore;
1869
1870 /* Set atomic aggregate flag. */
1871 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1872
1873 return BGP_ATTR_PARSE_PROCEED;
1874
1875 atomic_ignore:
1876 stream_forward_getp(peer->curr, length);
1877
1878 return bgp_attr_ignore(peer, args->type);
1879 }
1880
1881 /* Aggregator attribute */
1882 static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
1883 {
1884 struct peer *const peer = args->peer;
1885 struct attr *const attr = args->attr;
1886 const bgp_size_t length = args->length;
1887 as_t aggregator_as;
1888
1889 int wantedlen = 6;
1890
1891 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1892 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1893 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV))
1894 wantedlen = 8;
1895
1896 if (length != wantedlen) {
1897 flog_err(EC_BGP_ATTR_LEN,
1898 "AGGREGATOR attribute length isn't %u [%u]", wantedlen,
1899 length);
1900 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1901 args->total);
1902 }
1903
1904 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1905 goto aggregator_ignore;
1906
1907 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV))
1908 aggregator_as = stream_getl(peer->curr);
1909 else
1910 aggregator_as = stream_getw(peer->curr);
1911
1912 attr->aggregator_as = aggregator_as;
1913 attr->aggregator_addr.s_addr = stream_get_ipv4(peer->curr);
1914
1915 /* Codification of AS 0 Processing */
1916 if (aggregator_as == BGP_AS_ZERO) {
1917 flog_err(EC_BGP_ATTR_LEN,
1918 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1919 peer->host, aspath_print(attr->aspath));
1920
1921 if (bgp_debug_update(peer, NULL, NULL, 1)) {
1922 char attr_str[BUFSIZ] = {0};
1923
1924 bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1925
1926 zlog_debug("%s: attributes: %s", __func__, attr_str);
1927 }
1928 } else {
1929 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
1930 }
1931
1932 return BGP_ATTR_PARSE_PROCEED;
1933
1934 aggregator_ignore:
1935 stream_forward_getp(peer->curr, length);
1936
1937 return bgp_attr_ignore(peer, args->type);
1938 }
1939
1940 /* New Aggregator attribute */
1941 static enum bgp_attr_parse_ret
1942 bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
1943 as_t *as4_aggregator_as,
1944 struct in_addr *as4_aggregator_addr)
1945 {
1946 struct peer *const peer = args->peer;
1947 struct attr *const attr = args->attr;
1948 const bgp_size_t length = args->length;
1949 as_t aggregator_as;
1950
1951 if (length != 8) {
1952 flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
1953 length);
1954 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1955 0);
1956 }
1957
1958 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1959 goto as4_aggregator_ignore;
1960
1961 aggregator_as = stream_getl(peer->curr);
1962
1963 *as4_aggregator_as = aggregator_as;
1964 as4_aggregator_addr->s_addr = stream_get_ipv4(peer->curr);
1965
1966 /* Codification of AS 0 Processing */
1967 if (aggregator_as == BGP_AS_ZERO) {
1968 flog_err(EC_BGP_ATTR_LEN,
1969 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1970 peer->host, aspath_print(attr->aspath));
1971
1972 if (bgp_debug_update(peer, NULL, NULL, 1)) {
1973 char attr_str[BUFSIZ] = {0};
1974
1975 bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1976
1977 zlog_debug("%s: attributes: %s", __func__, attr_str);
1978 }
1979 } else {
1980 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
1981 }
1982
1983 return BGP_ATTR_PARSE_PROCEED;
1984
1985 as4_aggregator_ignore:
1986 stream_forward_getp(peer->curr, length);
1987
1988 return bgp_attr_ignore(peer, args->type);
1989 }
1990
1991 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1992 */
1993 static enum bgp_attr_parse_ret
1994 bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
1995 struct aspath *as4_path, as_t as4_aggregator,
1996 struct in_addr *as4_aggregator_addr)
1997 {
1998 int ignore_as4_path = 0;
1999 struct aspath *newpath;
2000
2001 if (!attr->aspath) {
2002 /* NULL aspath shouldn't be possible as bgp_attr_parse should
2003 * have
2004 * checked that all well-known, mandatory attributes were
2005 * present.
2006 *
2007 * Can only be a problem with peer itself - hard error
2008 */
2009 return BGP_ATTR_PARSE_ERROR;
2010 }
2011
2012 if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) {
2013 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
2014 * if given.
2015 * It is worth a warning though, because the peer really
2016 * should not send them
2017 */
2018 if (BGP_DEBUG(as4, AS4)) {
2019 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
2020 zlog_debug("[AS4] %s %s AS4_PATH", peer->host,
2021 "AS4 capable peer, yet it sent");
2022
2023 if (attr->flag
2024 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
2025 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2026 peer->host,
2027 "AS4 capable peer, yet it sent");
2028 }
2029
2030 return BGP_ATTR_PARSE_PROCEED;
2031 }
2032
2033 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2034 * because that may override AS4_PATH
2035 */
2036 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) {
2037 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
2038 /* received both.
2039 * if the as_number in aggregator is not AS_TRANS,
2040 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2041 * and the Aggregator shall be taken as
2042 * info on the aggregating node, and the AS_PATH
2043 * shall be taken as the AS_PATH
2044 * otherwise
2045 * the Aggregator shall be ignored and the
2046 * AS4_AGGREGATOR shall be taken as the
2047 * Aggregating node and the AS_PATH is to be
2048 * constructed "as in all other cases"
2049 */
2050 if (attr->aggregator_as != BGP_AS_TRANS) {
2051 /* ignore */
2052 if (BGP_DEBUG(as4, AS4))
2053 zlog_debug(
2054 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2055 peer->host);
2056 ignore_as4_path = 1;
2057 } else {
2058 /* "New_aggregator shall be taken as aggregator"
2059 */
2060 attr->aggregator_as = as4_aggregator;
2061 attr->aggregator_addr.s_addr =
2062 as4_aggregator_addr->s_addr;
2063 }
2064 } else {
2065 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2066 * That is bogus - but reading the conditions
2067 * we have to handle AS4_AGGREGATOR as if it were
2068 * AGGREGATOR in that case
2069 */
2070 if (BGP_DEBUG(as4, AS4))
2071 zlog_debug(
2072 "[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",
2073 peer->host);
2074 attr->aggregator_as = as4_aggregator;
2075 /* sweep it under the carpet and simulate a "good"
2076 * AGGREGATOR */
2077 attr->flag |= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
2078 }
2079 }
2080
2081 /* need to reconcile NEW_AS_PATH and AS_PATH */
2082 if (!ignore_as4_path
2083 && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) {
2084 newpath = aspath_reconcile_as4(attr->aspath, as4_path);
2085 if (!newpath)
2086 return BGP_ATTR_PARSE_ERROR;
2087
2088 aspath_unintern(&attr->aspath);
2089 attr->aspath = aspath_intern(newpath);
2090 }
2091 return BGP_ATTR_PARSE_PROCEED;
2092 }
2093
2094 /* Community attribute. */
2095 static enum bgp_attr_parse_ret
2096 bgp_attr_community(struct bgp_attr_parser_args *args)
2097 {
2098 struct peer *const peer = args->peer;
2099 struct attr *const attr = args->attr;
2100 const bgp_size_t length = args->length;
2101
2102 if (length == 0) {
2103 bgp_attr_set_community(attr, NULL);
2104 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2105 args->total);
2106 }
2107
2108 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2109 goto community_ignore;
2110
2111 bgp_attr_set_community(
2112 attr,
2113 community_parse((uint32_t *)stream_pnt(peer->curr), length));
2114
2115 /* XXX: fix community_parse to use stream API and remove this */
2116 stream_forward_getp(peer->curr, length);
2117
2118 /* The Community attribute SHALL be considered malformed if its
2119 * length is not a non-zero multiple of 4.
2120 */
2121 if (!bgp_attr_get_community(attr))
2122 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2123 args->total);
2124
2125 return BGP_ATTR_PARSE_PROCEED;
2126
2127 community_ignore:
2128 stream_forward_getp(peer->curr, length);
2129
2130 return bgp_attr_ignore(peer, args->type);
2131 }
2132
2133 /* Originator ID attribute. */
2134 static enum bgp_attr_parse_ret
2135 bgp_attr_originator_id(struct bgp_attr_parser_args *args)
2136 {
2137 struct peer *const peer = args->peer;
2138 struct attr *const attr = args->attr;
2139 const bgp_size_t length = args->length;
2140
2141 /* if received from an internal neighbor, it SHALL be considered
2142 * malformed if its length is not equal to 4. If malformed, the
2143 * UPDATE message SHALL be handled using the approach of "treat-as-
2144 * withdraw".
2145 */
2146 if (length != 4) {
2147 flog_err(EC_BGP_ATTR_LEN, "Bad originator ID length %d",
2148 length);
2149
2150 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2151 args->total);
2152 }
2153
2154 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2155 goto originator_id_ignore;
2156
2157 attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
2158
2159 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
2160
2161 return BGP_ATTR_PARSE_PROCEED;
2162
2163 originator_id_ignore:
2164 stream_forward_getp(peer->curr, length);
2165
2166 return bgp_attr_ignore(peer, args->type);
2167 }
2168
2169 /* Cluster list attribute. */
2170 static enum bgp_attr_parse_ret
2171 bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
2172 {
2173 struct peer *const peer = args->peer;
2174 struct attr *const attr = args->attr;
2175 const bgp_size_t length = args->length;
2176
2177 /* if received from an internal neighbor, it SHALL be considered
2178 * malformed if its length is not a non-zero multiple of 4. If
2179 * malformed, the UPDATE message SHALL be handled using the approach
2180 * of "treat-as-withdraw".
2181 */
2182 if (length == 0 || length % 4) {
2183 flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
2184
2185 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2186 args->total);
2187 }
2188
2189 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2190 goto cluster_list_ignore;
2191
2192 bgp_attr_set_cluster(
2193 attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
2194 length));
2195
2196 /* XXX: Fix cluster_parse to use stream API and then remove this */
2197 stream_forward_getp(peer->curr, length);
2198
2199 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
2200
2201 return BGP_ATTR_PARSE_PROCEED;
2202
2203 cluster_list_ignore:
2204 stream_forward_getp(peer->curr, length);
2205
2206 return bgp_attr_ignore(peer, args->type);
2207 }
2208
2209 /* Multiprotocol reachability information parse. */
2210 int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
2211 struct bgp_nlri *mp_update)
2212 {
2213 iana_afi_t pkt_afi;
2214 afi_t afi;
2215 iana_safi_t pkt_safi;
2216 safi_t safi;
2217 bgp_size_t nlri_len;
2218 size_t start;
2219 struct stream *s;
2220 struct peer *const peer = args->peer;
2221 struct attr *const attr = args->attr;
2222 const bgp_size_t length = args->length;
2223
2224 /* Set end of packet. */
2225 s = BGP_INPUT(peer);
2226 start = stream_get_getp(s);
2227
2228 /* safe to read statically sized header? */
2229 #define BGP_MP_REACH_MIN_SIZE 5
2230 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2231 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) {
2232 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2233 __func__, peer->host, (unsigned long)length);
2234 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2235 }
2236
2237 /* Load AFI, SAFI. */
2238 pkt_afi = stream_getw(s);
2239 pkt_safi = stream_getc(s);
2240
2241 /* Convert AFI, SAFI to internal values, check. */
2242 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2243 /* Log if AFI or SAFI is unrecognized. This is not an error
2244 * unless
2245 * the attribute is otherwise malformed.
2246 */
2247 if (bgp_debug_update(peer, NULL, NULL, 0))
2248 zlog_debug(
2249 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2250 peer->host, iana_afi2str(pkt_afi),
2251 iana_safi2str(pkt_safi));
2252 return BGP_ATTR_PARSE_ERROR;
2253 }
2254
2255 /* Get nexthop length. */
2256 attr->mp_nexthop_len = stream_getc(s);
2257
2258 if (LEN_LEFT < attr->mp_nexthop_len) {
2259 zlog_info(
2260 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2261 __func__, peer->host, attr->mp_nexthop_len);
2262 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2263 }
2264
2265 /* Nexthop length check. */
2266 switch (attr->mp_nexthop_len) {
2267 case 0:
2268 if (safi != SAFI_FLOWSPEC) {
2269 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2270 __func__, peer->host, attr->mp_nexthop_len);
2271 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2272 }
2273 break;
2274 case BGP_ATTR_NHLEN_VPNV4:
2275 stream_getl(s); /* RD high */
2276 stream_getl(s); /* RD low */
2277 /*
2278 * NOTE: intentional fall through
2279 * - for consistency in rx processing
2280 *
2281 * The following comment is to signal GCC this intention
2282 * and suppress the warning
2283 */
2284 /* FALLTHRU */
2285 case BGP_ATTR_NHLEN_IPV4:
2286 stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
2287 /* Probably needed for RFC 2283 */
2288 if (attr->nexthop.s_addr == INADDR_ANY)
2289 memcpy(&attr->nexthop.s_addr,
2290 &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
2291 break;
2292 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2293 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2294 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) {
2295 stream_getl(s); /* RD high */
2296 stream_getl(s); /* RD low */
2297 }
2298 stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2299 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2300 if (!peer->nexthop.ifp) {
2301 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2302 peer->host);
2303 return BGP_ATTR_PARSE_WITHDRAW;
2304 }
2305 attr->nh_ifindex = peer->nexthop.ifp->ifindex;
2306 }
2307 break;
2308 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2309 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
2310 if (attr->mp_nexthop_len
2311 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2312 stream_getl(s); /* RD high */
2313 stream_getl(s); /* RD low */
2314 }
2315 stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2316 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2317 if (!peer->nexthop.ifp) {
2318 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",
2319 peer->host);
2320 return BGP_ATTR_PARSE_WITHDRAW;
2321 }
2322 attr->nh_ifindex = peer->nexthop.ifp->ifindex;
2323 }
2324 if (attr->mp_nexthop_len
2325 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2326 stream_getl(s); /* RD high */
2327 stream_getl(s); /* RD low */
2328 }
2329 stream_get(&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
2330 if (!IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) {
2331 if (bgp_debug_update(peer, NULL, NULL, 1))
2332 zlog_debug(
2333 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2334 peer->host, &attr->mp_nexthop_global,
2335 &attr->mp_nexthop_local);
2336
2337 attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
2338 }
2339 if (!peer->nexthop.ifp) {
2340 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2341 peer->host);
2342 return BGP_ATTR_PARSE_WITHDRAW;
2343 }
2344 attr->nh_lla_ifindex = peer->nexthop.ifp->ifindex;
2345 break;
2346 default:
2347 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2348 __func__, peer->host, attr->mp_nexthop_len);
2349 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2350 }
2351
2352 if (!LEN_LEFT) {
2353 zlog_info("%s: %s sent SNPA which couldn't be read",
2354 __func__, peer->host);
2355 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2356 }
2357
2358 {
2359 uint8_t val;
2360 if ((val = stream_getc(s)))
2361 flog_warn(
2362 EC_BGP_DEFUNCT_SNPA_LEN,
2363 "%s sent non-zero value, %u, for defunct SNPA-length field",
2364 peer->host, val);
2365 }
2366
2367 /* must have nrli_len, what is left of the attribute */
2368 nlri_len = LEN_LEFT;
2369 if (nlri_len > STREAM_READABLE(s)) {
2370 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2371 __func__, peer->host);
2372 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2373 }
2374
2375 if (!nlri_len) {
2376 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2377 __func__, peer->host);
2378
2379 mp_update->afi = afi;
2380 mp_update->safi = safi;
2381 return BGP_ATTR_PARSE_EOR;
2382 }
2383
2384 mp_update->afi = afi;
2385 mp_update->safi = safi;
2386 mp_update->nlri = stream_pnt(s);
2387 mp_update->length = nlri_len;
2388
2389 stream_forward_getp(s, nlri_len);
2390
2391 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
2392
2393 return BGP_ATTR_PARSE_PROCEED;
2394 #undef LEN_LEFT
2395 }
2396
2397 /* Multiprotocol unreachable parse */
2398 int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
2399 struct bgp_nlri *mp_withdraw)
2400 {
2401 struct stream *s;
2402 iana_afi_t pkt_afi;
2403 afi_t afi;
2404 iana_safi_t pkt_safi;
2405 safi_t safi;
2406 uint16_t withdraw_len;
2407 struct peer *const peer = args->peer;
2408 struct attr *const attr = args->attr;
2409 const bgp_size_t length = args->length;
2410
2411 s = peer->curr;
2412
2413 #define BGP_MP_UNREACH_MIN_SIZE 3
2414 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
2415 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2416
2417 pkt_afi = stream_getw(s);
2418 pkt_safi = stream_getc(s);
2419
2420 /* Convert AFI, SAFI to internal values, check. */
2421 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2422 /* Log if AFI or SAFI is unrecognized. This is not an error
2423 * unless
2424 * the attribute is otherwise malformed.
2425 */
2426 if (bgp_debug_update(peer, NULL, NULL, 0))
2427 zlog_debug(
2428 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2429 peer->host, iana_afi2str(pkt_afi),
2430 iana_safi2str(pkt_safi));
2431 return BGP_ATTR_PARSE_ERROR;
2432 }
2433
2434 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
2435
2436 mp_withdraw->afi = afi;
2437 mp_withdraw->safi = safi;
2438 mp_withdraw->nlri = stream_pnt(s);
2439 mp_withdraw->length = withdraw_len;
2440
2441 stream_forward_getp(s, withdraw_len);
2442
2443 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI);
2444
2445 return BGP_ATTR_PARSE_PROCEED;
2446 }
2447
2448 /* Large Community attribute. */
2449 static enum bgp_attr_parse_ret
2450 bgp_attr_large_community(struct bgp_attr_parser_args *args)
2451 {
2452 struct peer *const peer = args->peer;
2453 struct attr *const attr = args->attr;
2454 const bgp_size_t length = args->length;
2455
2456 /*
2457 * Large community follows new attribute format.
2458 */
2459 if (length == 0) {
2460 bgp_attr_set_lcommunity(attr, NULL);
2461 /* Empty extcomm doesn't seem to be invalid per se */
2462 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2463 args->total);
2464 }
2465
2466 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2467 goto large_community_ignore;
2468
2469 bgp_attr_set_lcommunity(
2470 attr, lcommunity_parse(stream_pnt(peer->curr), length));
2471 /* XXX: fix ecommunity_parse to use stream API */
2472 stream_forward_getp(peer->curr, length);
2473
2474 if (!bgp_attr_get_lcommunity(attr))
2475 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2476 args->total);
2477
2478 return BGP_ATTR_PARSE_PROCEED;
2479
2480 large_community_ignore:
2481 stream_forward_getp(peer->curr, length);
2482
2483 return bgp_attr_ignore(peer, args->type);
2484 }
2485
2486 /* Extended Community attribute. */
2487 static enum bgp_attr_parse_ret
2488 bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
2489 {
2490 struct peer *const peer = args->peer;
2491 struct attr *const attr = args->attr;
2492 const bgp_size_t length = args->length;
2493 uint8_t sticky = 0;
2494 bool proxy = false;
2495 struct ecommunity *ecomm;
2496
2497 if (length == 0) {
2498 bgp_attr_set_ecommunity(attr, NULL);
2499 /* Empty extcomm doesn't seem to be invalid per se */
2500 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2501 args->total);
2502 }
2503
2504 ecomm = ecommunity_parse(
2505 stream_pnt(peer->curr), length,
2506 CHECK_FLAG(peer->flags,
2507 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2508 bgp_attr_set_ecommunity(attr, ecomm);
2509 /* XXX: fix ecommunity_parse to use stream API */
2510 stream_forward_getp(peer->curr, length);
2511
2512 /* The Extended Community attribute SHALL be considered malformed if
2513 * its length is not a non-zero multiple of 8.
2514 */
2515 if (!bgp_attr_get_ecommunity(attr))
2516 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2517 args->total);
2518
2519 /* Extract DF election preference and mobility sequence number */
2520 attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
2521
2522 /* Extract MAC mobility sequence number, if any. */
2523 attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
2524 attr->sticky = sticky;
2525
2526 /* Check if this is a Gateway MAC-IP advertisement */
2527 attr->default_gw = bgp_attr_default_gw(attr);
2528
2529 /* Handle scenario where router flag ecommunity is not
2530 * set but default gw ext community is present.
2531 * Use default gateway, set and propogate R-bit.
2532 */
2533 if (attr->default_gw)
2534 attr->router_flag = 1;
2535
2536 /* Check EVPN Neighbor advertisement flags, R-bit */
2537 bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy);
2538 if (proxy)
2539 attr->es_flags |= ATTR_ES_PROXY_ADVERT;
2540
2541 /* Extract the Rmac, if any */
2542 if (bgp_attr_rmac(attr, &attr->rmac)) {
2543 if (bgp_debug_update(peer, NULL, NULL, 1)
2544 && bgp_mac_exist(&attr->rmac))
2545 zlog_debug("%s: router mac %pEA is self mac", __func__,
2546 &attr->rmac);
2547 }
2548
2549 /* Get the tunnel type from encap extended community */
2550 bgp_attr_extcom_tunnel_type(attr,
2551 (bgp_encap_types *)&attr->encap_tunneltype);
2552
2553 /* Extract link bandwidth, if any. */
2554 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr),
2555 &attr->link_bw);
2556
2557 return BGP_ATTR_PARSE_PROCEED;
2558 }
2559
2560 /* IPv6 Extended Community attribute. */
2561 static enum bgp_attr_parse_ret
2562 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
2563 {
2564 struct peer *const peer = args->peer;
2565 struct attr *const attr = args->attr;
2566 const bgp_size_t length = args->length;
2567 struct ecommunity *ipv6_ecomm = NULL;
2568
2569 if (length == 0) {
2570 bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2571 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2572 args->total);
2573 }
2574
2575 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2576 goto ipv6_ext_community_ignore;
2577
2578 ipv6_ecomm = ecommunity_parse_ipv6(
2579 stream_pnt(peer->curr), length,
2580 CHECK_FLAG(peer->flags,
2581 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2582 bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2583
2584 /* XXX: fix ecommunity_parse to use stream API */
2585 stream_forward_getp(peer->curr, length);
2586
2587 if (!ipv6_ecomm)
2588 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2589 args->total);
2590
2591 return BGP_ATTR_PARSE_PROCEED;
2592
2593 ipv6_ext_community_ignore:
2594 stream_forward_getp(peer->curr, length);
2595
2596 return bgp_attr_ignore(peer, args->type);
2597 }
2598
2599 /* Parse Tunnel Encap attribute in an UPDATE */
2600 static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
2601 bgp_size_t length, /* IN: attr's length field */
2602 struct attr *attr, /* IN: caller already allocated */
2603 uint8_t flag, /* IN: attr's flags field */
2604 uint8_t *startp)
2605 {
2606 bgp_size_t total;
2607 uint16_t tunneltype = 0;
2608
2609 total = length + (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
2610
2611 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
2612 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
2613 zlog_info(
2614 "Tunnel Encap attribute flag isn't optional and transitive %d",
2615 flag);
2616 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
2617 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2618 startp, total);
2619 return -1;
2620 }
2621
2622 if (BGP_ATTR_ENCAP == type) {
2623 /* read outer TLV type and length */
2624 uint16_t tlv_length;
2625
2626 if (length < 4) {
2627 zlog_info(
2628 "Tunnel Encap attribute not long enough to contain outer T,L");
2629 bgp_notify_send_with_data(
2630 peer, BGP_NOTIFY_UPDATE_ERR,
2631 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
2632 return -1;
2633 }
2634 tunneltype = stream_getw(BGP_INPUT(peer));
2635 tlv_length = stream_getw(BGP_INPUT(peer));
2636 length -= 4;
2637
2638 if (tlv_length != length) {
2639 zlog_info("%s: tlv_length(%d) != length(%d)",
2640 __func__, tlv_length, length);
2641 }
2642 }
2643
2644 while (length >= 4) {
2645 uint16_t subtype = 0;
2646 uint16_t sublength = 0;
2647 struct bgp_attr_encap_subtlv *tlv;
2648
2649 if (BGP_ATTR_ENCAP == type) {
2650 subtype = stream_getc(BGP_INPUT(peer));
2651 sublength = stream_getc(BGP_INPUT(peer));
2652 length -= 2;
2653 #ifdef ENABLE_BGP_VNC
2654 } else {
2655 subtype = stream_getw(BGP_INPUT(peer));
2656 sublength = stream_getw(BGP_INPUT(peer));
2657 length -= 4;
2658 #endif
2659 }
2660
2661 if (sublength > length) {
2662 zlog_info(
2663 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2664 sublength, length);
2665 bgp_notify_send_with_data(
2666 peer, BGP_NOTIFY_UPDATE_ERR,
2667 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
2668 return -1;
2669 }
2670
2671 /* alloc and copy sub-tlv */
2672 /* TBD make sure these are freed when attributes are released */
2673 tlv = XCALLOC(MTYPE_ENCAP_TLV,
2674 sizeof(struct bgp_attr_encap_subtlv) + sublength);
2675 tlv->type = subtype;
2676 tlv->length = sublength;
2677 stream_get(tlv->value, peer->curr, sublength);
2678 length -= sublength;
2679
2680 /* attach tlv to encap chain */
2681 if (BGP_ATTR_ENCAP == type) {
2682 struct bgp_attr_encap_subtlv *stlv_last;
2683 for (stlv_last = attr->encap_subtlvs;
2684 stlv_last && stlv_last->next;
2685 stlv_last = stlv_last->next)
2686 ;
2687 if (stlv_last) {
2688 stlv_last->next = tlv;
2689 } else {
2690 attr->encap_subtlvs = tlv;
2691 }
2692 #ifdef ENABLE_BGP_VNC
2693 } else {
2694 struct bgp_attr_encap_subtlv *stlv_last;
2695 struct bgp_attr_encap_subtlv *vnc_subtlvs =
2696 bgp_attr_get_vnc_subtlvs(attr);
2697
2698 for (stlv_last = vnc_subtlvs;
2699 stlv_last && stlv_last->next;
2700 stlv_last = stlv_last->next)
2701 ;
2702 if (stlv_last)
2703 stlv_last->next = tlv;
2704 else
2705 bgp_attr_set_vnc_subtlvs(attr, tlv);
2706 #endif
2707 }
2708 }
2709
2710 if (BGP_ATTR_ENCAP == type) {
2711 attr->encap_tunneltype = tunneltype;
2712 }
2713
2714 if (length) {
2715 /* spurious leftover data */
2716 zlog_info(
2717 "Tunnel Encap attribute length is bad: %d leftover octets",
2718 length);
2719 bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
2720 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2721 startp, total);
2722 return -1;
2723 }
2724
2725 return 0;
2726 }
2727
2728
2729 /* SRv6 Service Data Sub-Sub-TLV attribute
2730 * draft-ietf-bess-srv6-services-07
2731 */
2732 static enum bgp_attr_parse_ret
2733 bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
2734 {
2735 struct peer *const peer = args->peer;
2736 struct attr *const attr = args->attr;
2737 uint8_t type, loc_block_len, loc_node_len, func_len, arg_len,
2738 transposition_len, transposition_offset;
2739 uint16_t length;
2740 size_t headersz = sizeof(type) + sizeof(length);
2741
2742 if (STREAM_READABLE(peer->curr) < headersz) {
2743 flog_err(
2744 EC_BGP_ATTR_LEN,
2745 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2746 headersz, STREAM_READABLE(peer->curr));
2747 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2748 args->total);
2749 }
2750
2751 type = stream_getc(peer->curr);
2752 length = stream_getw(peer->curr);
2753
2754 if (STREAM_READABLE(peer->curr) < length) {
2755 flog_err(
2756 EC_BGP_ATTR_LEN,
2757 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2758 length, STREAM_READABLE(peer->curr));
2759 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2760 args->total);
2761 }
2762
2763 if (length < BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2764 flog_err(
2765 EC_BGP_ATTR_LEN,
2766 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2767 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2768 length);
2769 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2770 args->total);
2771 }
2772
2773 if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
2774 if (STREAM_READABLE(peer->curr) <
2775 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2776 flog_err(
2777 EC_BGP_ATTR_LEN,
2778 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2779 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2780 STREAM_READABLE(peer->curr));
2781 return bgp_attr_malformed(
2782 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2783 args->total);
2784 }
2785
2786 loc_block_len = stream_getc(peer->curr);
2787 loc_node_len = stream_getc(peer->curr);
2788 func_len = stream_getc(peer->curr);
2789 arg_len = stream_getc(peer->curr);
2790 transposition_len = stream_getc(peer->curr);
2791 transposition_offset = stream_getc(peer->curr);
2792
2793 /* Log SRv6 Service Data Sub-Sub-TLV */
2794 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
2795 zlog_debug(
2796 "%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",
2797 __func__, loc_block_len, loc_node_len, func_len,
2798 arg_len, transposition_len,
2799 transposition_offset);
2800 }
2801
2802 attr->srv6_l3vpn->loc_block_len = loc_block_len;
2803 attr->srv6_l3vpn->loc_node_len = loc_node_len;
2804 attr->srv6_l3vpn->func_len = func_len;
2805 attr->srv6_l3vpn->arg_len = arg_len;
2806 attr->srv6_l3vpn->transposition_len = transposition_len;
2807 attr->srv6_l3vpn->transposition_offset = transposition_offset;
2808 }
2809
2810 else {
2811 if (bgp_debug_update(peer, NULL, NULL, 1))
2812 zlog_debug(
2813 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2814 peer->host, type);
2815
2816 stream_forward_getp(peer->curr, length);
2817 }
2818
2819 return BGP_ATTR_PARSE_PROCEED;
2820 }
2821
2822 /* SRv6 Service Sub-TLV attribute
2823 * draft-ietf-bess-srv6-services-07
2824 */
2825 static enum bgp_attr_parse_ret
2826 bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
2827 {
2828 struct peer *const peer = args->peer;
2829 struct attr *const attr = args->attr;
2830 struct in6_addr ipv6_sid;
2831 uint8_t type, sid_flags;
2832 uint16_t length, endpoint_behavior;
2833 size_t headersz = sizeof(type) + sizeof(length);
2834 enum bgp_attr_parse_ret err;
2835
2836 if (STREAM_READABLE(peer->curr) < headersz) {
2837 flog_err(
2838 EC_BGP_ATTR_LEN,
2839 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2840 headersz, STREAM_READABLE(peer->curr));
2841 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2842 args->total);
2843 }
2844
2845 type = stream_getc(peer->curr);
2846 length = stream_getw(peer->curr);
2847
2848 if (STREAM_READABLE(peer->curr) < length) {
2849 flog_err(
2850 EC_BGP_ATTR_LEN,
2851 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2852 length, STREAM_READABLE(peer->curr));
2853 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2854 args->total);
2855 }
2856
2857 if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
2858 if (STREAM_READABLE(peer->curr) <
2859 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2860 flog_err(
2861 EC_BGP_ATTR_LEN,
2862 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2863 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH,
2864 STREAM_READABLE(peer->curr));
2865 return bgp_attr_malformed(
2866 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2867 args->total);
2868 }
2869 stream_getc(peer->curr);
2870 stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
2871 sid_flags = stream_getc(peer->curr);
2872 endpoint_behavior = stream_getw(peer->curr);
2873 stream_getc(peer->curr);
2874
2875 /* Log SRv6 Service Sub-TLV */
2876 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
2877 zlog_debug(
2878 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2879 __func__, &ipv6_sid, sid_flags,
2880 endpoint_behavior);
2881
2882 /* Configure from Info */
2883 if (attr->srv6_l3vpn) {
2884 flog_err(EC_BGP_ATTRIBUTE_REPEATED,
2885 "Prefix SID SRv6 L3VPN field repeated");
2886 return bgp_attr_malformed(
2887 args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
2888 }
2889 attr->srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
2890 sizeof(struct bgp_attr_srv6_l3vpn));
2891 sid_copy(&attr->srv6_l3vpn->sid, &ipv6_sid);
2892 attr->srv6_l3vpn->sid_flags = sid_flags;
2893 attr->srv6_l3vpn->endpoint_behavior = endpoint_behavior;
2894 attr->srv6_l3vpn->loc_block_len = 0;
2895 attr->srv6_l3vpn->loc_node_len = 0;
2896 attr->srv6_l3vpn->func_len = 0;
2897 attr->srv6_l3vpn->arg_len = 0;
2898 attr->srv6_l3vpn->transposition_len = 0;
2899 attr->srv6_l3vpn->transposition_offset = 0;
2900
2901 // Sub-Sub-TLV found
2902 if (length > BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2903 err = bgp_attr_srv6_service_data(args);
2904
2905 if (err != BGP_ATTR_PARSE_PROCEED)
2906 return err;
2907 }
2908
2909 attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
2910 }
2911
2912 /* Placeholder code for unsupported type */
2913 else {
2914 if (bgp_debug_update(peer, NULL, NULL, 1))
2915 zlog_debug(
2916 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2917 peer->host, type);
2918
2919 stream_forward_getp(peer->curr, length);
2920 }
2921
2922 return BGP_ATTR_PARSE_PROCEED;
2923 }
2924
2925 /*
2926 * Read an individual SID value returning how much data we have read
2927 * Returns 0 if there was an error that needs to be passed up the stack
2928 */
2929 static enum bgp_attr_parse_ret
2930 bgp_attr_psid_sub(uint8_t type, uint16_t length,
2931 struct bgp_attr_parser_args *args)
2932 {
2933 struct peer *const peer = args->peer;
2934 struct attr *const attr = args->attr;
2935 uint32_t label_index;
2936 struct in6_addr ipv6_sid;
2937 uint32_t srgb_base;
2938 uint32_t srgb_range;
2939 int srgb_count;
2940 uint8_t sid_type, sid_flags;
2941
2942 if (type == BGP_PREFIX_SID_LABEL_INDEX) {
2943 if (STREAM_READABLE(peer->curr) < length
2944 || length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
2945 flog_err(EC_BGP_ATTR_LEN,
2946 "Prefix SID label index length is %hu instead of %u",
2947 length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
2948 return bgp_attr_malformed(args,
2949 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2950 args->total);
2951 }
2952
2953 /* Ignore flags and reserved */
2954 stream_getc(peer->curr);
2955 stream_getw(peer->curr);
2956
2957 /* Fetch the label index and see if it is valid. */
2958 label_index = stream_getl(peer->curr);
2959 if (label_index == BGP_INVALID_LABEL_INDEX)
2960 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2961 args->total);
2962
2963 /* Store label index; subsequently, we'll check on
2964 * address-family */
2965 attr->label_index = label_index;
2966 }
2967
2968 /* Placeholder code for the IPv6 SID type */
2969 else if (type == BGP_PREFIX_SID_IPV6) {
2970 if (STREAM_READABLE(peer->curr) < length
2971 || length != BGP_PREFIX_SID_IPV6_LENGTH) {
2972 flog_err(EC_BGP_ATTR_LEN,
2973 "Prefix SID IPv6 length is %hu instead of %u",
2974 length, BGP_PREFIX_SID_IPV6_LENGTH);
2975 return bgp_attr_malformed(args,
2976 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2977 args->total);
2978 }
2979
2980 /* Ignore reserved */
2981 stream_getc(peer->curr);
2982 stream_getw(peer->curr);
2983
2984 stream_get(&ipv6_sid, peer->curr, 16);
2985 }
2986
2987 /* Placeholder code for the Originator SRGB type */
2988 else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
2989 /*
2990 * ietf-idr-bgp-prefix-sid-05:
2991 * Length is the total length of the value portion of the
2992 * TLV: 2 + multiple of 6.
2993 *
2994 * peer->curr stream readp should be at the beginning of the 16
2995 * bit flag field at this point in the code.
2996 */
2997
2998 /*
2999 * Check that the TLV length field is sane: at least 2 bytes of
3000 * flag, and at least 1 SRGB (these are 6 bytes each)
3001 */
3002 if (length < (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH)) {
3003 flog_err(
3004 EC_BGP_ATTR_LEN,
3005 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
3006 length,
3007 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
3008 return bgp_attr_malformed(
3009 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3010 args->total);
3011 }
3012
3013 /*
3014 * Check that we actually have at least as much data as
3015 * specified by the length field
3016 */
3017 if (STREAM_READABLE(peer->curr) < length) {
3018 flog_err(EC_BGP_ATTR_LEN,
3019 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
3020 length, STREAM_READABLE(peer->curr));
3021 return bgp_attr_malformed(
3022 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3023 args->total);
3024 }
3025
3026 /*
3027 * Check that the portion of the TLV containing the sequence of
3028 * SRGBs corresponds to a multiple of the SRGB size; to get
3029 * that length, we skip the 16 bit flags field
3030 */
3031 stream_getw(peer->curr);
3032 length -= 2;
3033 if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) {
3034 flog_err(
3035 EC_BGP_ATTR_LEN,
3036 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
3037 length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
3038 return bgp_attr_malformed(
3039 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3040 args->total);
3041 }
3042
3043 srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH;
3044
3045 for (int i = 0; i < srgb_count; i++) {
3046 stream_get(&srgb_base, peer->curr, 3);
3047 stream_get(&srgb_range, peer->curr, 3);
3048 }
3049 }
3050
3051 /* Placeholder code for the VPN-SID Service type */
3052 else if (type == BGP_PREFIX_SID_VPN_SID) {
3053 if (STREAM_READABLE(peer->curr) < length
3054 || length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
3055 flog_err(EC_BGP_ATTR_LEN,
3056 "Prefix SID VPN SID length is %hu instead of %u",
3057 length, BGP_PREFIX_SID_VPN_SID_LENGTH);
3058 return bgp_attr_malformed(args,
3059 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3060 args->total);
3061 }
3062
3063 /* Parse VPN-SID Sub-TLV */
3064 stream_getc(peer->curr); /* reserved */
3065 sid_type = stream_getc(peer->curr); /* sid_type */
3066 sid_flags = stream_getc(peer->curr); /* sid_flags */
3067 stream_get(&ipv6_sid, peer->curr,
3068 sizeof(ipv6_sid)); /* sid_value */
3069
3070 /* Log VPN-SID Sub-TLV */
3071 if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
3072 zlog_debug(
3073 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3074 __func__, &ipv6_sid, sid_type, sid_flags);
3075
3076 /* Configure from Info */
3077 if (attr->srv6_vpn) {
3078 flog_err(EC_BGP_ATTRIBUTE_REPEATED,
3079 "Prefix SID SRv6 VPN field repeated");
3080 return bgp_attr_malformed(
3081 args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
3082 }
3083 attr->srv6_vpn = XCALLOC(MTYPE_BGP_SRV6_VPN,
3084 sizeof(struct bgp_attr_srv6_vpn));
3085 attr->srv6_vpn->sid_flags = sid_flags;
3086 sid_copy(&attr->srv6_vpn->sid, &ipv6_sid);
3087 attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
3088 }
3089
3090 /* Placeholder code for the SRv6 L3 Service type */
3091 else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
3092 if (STREAM_READABLE(peer->curr) < length) {
3093 flog_err(
3094 EC_BGP_ATTR_LEN,
3095 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3096 length, STREAM_READABLE(peer->curr));
3097 return bgp_attr_malformed(args,
3098 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3099 args->total);
3100 }
3101
3102 /* ignore reserved */
3103 stream_getc(peer->curr);
3104
3105 return bgp_attr_srv6_service(args);
3106 }
3107
3108 /* Placeholder code for Unsupported TLV */
3109 else {
3110
3111 if (STREAM_READABLE(peer->curr) < length) {
3112 flog_err(
3113 EC_BGP_ATTR_LEN,
3114 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3115 length, STREAM_READABLE(peer->curr));
3116 return bgp_attr_malformed(
3117 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3118 args->total);
3119 }
3120
3121 if (bgp_debug_update(peer, NULL, NULL, 1))
3122 zlog_debug(
3123 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3124 peer->host, type);
3125
3126 stream_forward_getp(peer->curr, length);
3127 }
3128
3129 return BGP_ATTR_PARSE_PROCEED;
3130 }
3131
3132 /* Prefix SID attribute
3133 * draft-ietf-idr-bgp-prefix-sid-05
3134 */
3135 enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
3136 {
3137 struct peer *const peer = args->peer;
3138 struct attr *const attr = args->attr;
3139 enum bgp_attr_parse_ret ret;
3140
3141 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
3142
3143 uint8_t type;
3144 uint16_t length;
3145 size_t headersz = sizeof(type) + sizeof(length);
3146 size_t psid_parsed_length = 0;
3147
3148 while (STREAM_READABLE(peer->curr) > 0
3149 && psid_parsed_length < args->length) {
3150
3151 if (STREAM_READABLE(peer->curr) < headersz) {
3152 flog_err(
3153 EC_BGP_ATTR_LEN,
3154 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3155 headersz, STREAM_READABLE(peer->curr));
3156 return bgp_attr_malformed(
3157 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3158 args->total);
3159 }
3160
3161 type = stream_getc(peer->curr);
3162 length = stream_getw(peer->curr);
3163
3164 if (STREAM_READABLE(peer->curr) < length) {
3165 flog_err(
3166 EC_BGP_ATTR_LEN,
3167 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3168 length, STREAM_READABLE(peer->curr));
3169 return bgp_attr_malformed(args,
3170 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3171 args->total);
3172 }
3173
3174 ret = bgp_attr_psid_sub(type, length, args);
3175
3176 if (ret != BGP_ATTR_PARSE_PROCEED)
3177 return ret;
3178
3179 psid_parsed_length += length + headersz;
3180
3181 if (psid_parsed_length > args->length) {
3182 flog_err(
3183 EC_BGP_ATTR_LEN,
3184 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3185 length + headersz, psid_parsed_length - (length + headersz));
3186 return bgp_attr_malformed(
3187 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3188 args->total);
3189 }
3190 }
3191
3192 return BGP_ATTR_PARSE_PROCEED;
3193 }
3194
3195 /* PMSI tunnel attribute (RFC 6514)
3196 * Basic validation checks done here.
3197 */
3198 static enum bgp_attr_parse_ret
3199 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
3200 {
3201 struct peer *const peer = args->peer;
3202 struct attr *const attr = args->attr;
3203 const bgp_size_t length = args->length;
3204 uint8_t tnl_type;
3205 int attr_parse_len = 2 + BGP_LABEL_BYTES;
3206
3207 /* Verify that the receiver is expecting "ingress replication" as we
3208 * can only support that.
3209 */
3210 if (length < attr_parse_len) {
3211 flog_err(EC_BGP_ATTR_LEN, "Bad PMSI tunnel attribute length %d",
3212 length);
3213 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3214 args->total);
3215 }
3216 stream_getc(peer->curr); /* Flags */
3217 tnl_type = stream_getc(peer->curr);
3218 if (tnl_type > PMSI_TNLTYPE_MAX) {
3219 flog_err(EC_BGP_ATTR_PMSI_TYPE,
3220 "Invalid PMSI tunnel attribute type %d", tnl_type);
3221 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
3222 args->total);
3223 }
3224 if (tnl_type == PMSI_TNLTYPE_INGR_REPL) {
3225 if (length != 9) {
3226 flog_err(EC_BGP_ATTR_PMSI_LEN,
3227 "Bad PMSI tunnel attribute length %d for IR",
3228 length);
3229 return bgp_attr_malformed(
3230 args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3231 args->total);
3232 }
3233 }
3234
3235 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
3236 bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
3237 stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES);
3238
3239 /* Forward read pointer of input stream. */
3240 stream_forward_getp(peer->curr, length - attr_parse_len);
3241
3242 return BGP_ATTR_PARSE_PROCEED;
3243 }
3244
3245 /* AIGP attribute (rfc7311) */
3246 static enum bgp_attr_parse_ret bgp_attr_aigp(struct bgp_attr_parser_args *args)
3247 {
3248 struct peer *const peer = args->peer;
3249 struct attr *const attr = args->attr;
3250 const bgp_size_t length = args->length;
3251 uint8_t *s = stream_pnt(peer->curr);
3252 uint64_t aigp = 0;
3253
3254 /* If an AIGP attribute is received on a BGP session for which
3255 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3256 * as if it were an unrecognized non-transitive attribute.
3257 * That is, it "MUST be quietly ignored and not passed along to
3258 * other BGP peers".
3259 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3260 * sessions between members of the same BGP Confederation,
3261 * the default value of AIGP_SESSION SHOULD be "enabled".
3262 */
3263 if (peer->sort == BGP_PEER_EBGP &&
3264 !CHECK_FLAG(peer->flags, PEER_FLAG_AIGP)) {
3265 zlog_warn(
3266 "%pBP received AIGP attribute, but eBGP peer do not support it",
3267 peer);
3268 goto aigp_ignore;
3269 }
3270
3271 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
3272 goto aigp_ignore;
3273
3274 if (!bgp_attr_aigp_valid(s, length))
3275 goto aigp_ignore;
3276
3277 /* Extract AIGP Metric TLV */
3278 if (bgp_attr_aigp_get_tlv_metric(s, length, &aigp))
3279 bgp_attr_set_aigp_metric(attr, aigp);
3280
3281 aigp_ignore:
3282 stream_forward_getp(peer->curr, length);
3283
3284 return bgp_attr_ignore(peer, args->type);
3285 }
3286
3287 /* OTC attribute. */
3288 static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
3289 {
3290 struct peer *const peer = args->peer;
3291 struct attr *const attr = args->attr;
3292 const bgp_size_t length = args->length;
3293
3294 /* Length check. */
3295 if (length != 4) {
3296 flog_err(EC_BGP_ATTR_LEN, "OTC attribute length isn't 4 [%u]",
3297 length);
3298 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3299 args->total);
3300 }
3301
3302 if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
3303 goto otc_ignore;
3304
3305 attr->otc = stream_getl(peer->curr);
3306 if (!attr->otc) {
3307 flog_err(EC_BGP_ATTR_MAL_AS_PATH, "OTC attribute value is 0");
3308 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
3309 args->total);
3310 }
3311
3312 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
3313
3314 return BGP_ATTR_PARSE_PROCEED;
3315
3316 otc_ignore:
3317 stream_forward_getp(peer->curr, length);
3318
3319 return bgp_attr_ignore(peer, args->type);
3320 }
3321
3322 /* BGP unknown attribute treatment. */
3323 static enum bgp_attr_parse_ret
3324 bgp_attr_unknown(struct bgp_attr_parser_args *args)
3325 {
3326 bgp_size_t total = args->total;
3327 struct transit *transit;
3328 struct peer *const peer = args->peer;
3329 struct attr *const attr = args->attr;
3330 uint8_t *const startp = args->startp;
3331 const uint8_t type = args->type;
3332 const uint8_t flag = args->flags;
3333 const bgp_size_t length = args->length;
3334
3335 if (bgp_debug_update(peer, NULL, NULL, 1))
3336 zlog_debug(
3337 "%s Unknown attribute is received (type %d, length %d)",
3338 peer->host, type, length);
3339
3340 /* Forward read pointer of input stream. */
3341 stream_forward_getp(peer->curr, length);
3342
3343 if (peer->discard_attrs[type] || peer->withdraw_attrs[type])
3344 return bgp_attr_ignore(peer, type);
3345
3346 /* If any of the mandatory well-known attributes are not recognized,
3347 then the Error Subcode is set to Unrecognized Well-known
3348 Attribute. The Data field contains the unrecognized attribute
3349 (type, length and value). */
3350 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
3351 return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_UNREC_ATTR,
3352 args->total);
3353 }
3354
3355 /* Unrecognized non-transitive optional attributes must be quietly
3356 ignored and not passed along to other BGP peers. */
3357 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
3358 return BGP_ATTR_PARSE_PROCEED;
3359
3360 /* If a path with recognized transitive optional attribute is
3361 accepted and passed along to other BGP peers and the Partial bit
3362 in the Attribute Flags octet is set to 1 by some previous AS, it
3363 is not set back to 0 by the current AS. */
3364 SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL);
3365
3366 /* Store transitive attribute to the end of attr->transit. */
3367 transit = bgp_attr_get_transit(attr);
3368 if (!transit)
3369 transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
3370
3371 transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val,
3372 transit->length + total);
3373
3374 memcpy(transit->val + transit->length, startp, total);
3375 transit->length += total;
3376 bgp_attr_set_transit(attr, transit);
3377
3378 return BGP_ATTR_PARSE_PROCEED;
3379 }
3380
3381 /* Well-known attribute check. */
3382 static int bgp_attr_check(struct peer *peer, struct attr *attr)
3383 {
3384 uint8_t type = 0;
3385
3386 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3387 * empty UPDATE. */
3388 if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
3389 return BGP_ATTR_PARSE_PROCEED;
3390
3391 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3392 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3393 are present, it should. Check for any other attribute being present
3394 instead.
3395 */
3396 if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
3397 CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
3398 return BGP_ATTR_PARSE_PROCEED;
3399
3400 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
3401 type = BGP_ATTR_ORIGIN;
3402
3403 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
3404 type = BGP_ATTR_AS_PATH;
3405
3406 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3407 * and
3408 * NLRI is empty. We can't easily check NLRI empty here though.
3409 */
3410 if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3411 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)))
3412 type = BGP_ATTR_NEXT_HOP;
3413
3414 if (peer->sort == BGP_PEER_IBGP
3415 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
3416 type = BGP_ATTR_LOCAL_PREF;
3417
3418 /* If any of the well-known mandatory attributes are not present
3419 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3420 */
3421 if (type) {
3422 flog_warn(EC_BGP_MISSING_ATTRIBUTE,
3423 "%s Missing well-known attribute %s.", peer->host,
3424 lookup_msg(attr_str, type, NULL));
3425 return BGP_ATTR_PARSE_WITHDRAW;
3426 }
3427 return BGP_ATTR_PARSE_PROCEED;
3428 }
3429
3430 /* Read attribute of update packet. This function is called from
3431 bgp_update_receive() in bgp_packet.c. */
3432 enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
3433 bgp_size_t size,
3434 struct bgp_nlri *mp_update,
3435 struct bgp_nlri *mp_withdraw)
3436 {
3437 enum bgp_attr_parse_ret ret;
3438 uint8_t flag = 0;
3439 uint8_t type = 0;
3440 bgp_size_t length;
3441 uint8_t *startp, *endp;
3442 uint8_t *attr_endp;
3443 uint8_t seen[BGP_ATTR_BITMAP_SIZE];
3444 /* we need the as4_path only until we have synthesized the as_path with
3445 * it */
3446 /* same goes for as4_aggregator */
3447 struct aspath *as4_path = NULL;
3448 as_t as4_aggregator = 0;
3449 struct in_addr as4_aggregator_addr = {.s_addr = 0};
3450 struct transit *transit;
3451
3452 /* Initialize bitmap. */
3453 memset(seen, 0, BGP_ATTR_BITMAP_SIZE);
3454
3455 /* End pointer of BGP attribute. */
3456 endp = BGP_INPUT_PNT(peer) + size;
3457
3458 /* Get attributes to the end of attribute length. */
3459 while (BGP_INPUT_PNT(peer) < endp) {
3460 /* Check remaining length check.*/
3461 if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) {
3462 /* XXX warning: long int format, int arg (arg 5) */
3463 flog_warn(
3464 EC_BGP_ATTRIBUTE_TOO_SMALL,
3465 "%s: error BGP attribute length %lu is smaller than min len",
3466 peer->host,
3467 (unsigned long)(endp
3468 - stream_pnt(BGP_INPUT(peer))));
3469
3470 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3471 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3472 ret = BGP_ATTR_PARSE_ERROR;
3473 goto done;
3474 }
3475
3476 /* Fetch attribute flag and type. */
3477 startp = BGP_INPUT_PNT(peer);
3478 /* "The lower-order four bits of the Attribute Flags octet are
3479 unused. They MUST be zero when sent and MUST be ignored when
3480 received." */
3481 flag = 0xF0 & stream_getc(BGP_INPUT(peer));
3482 type = stream_getc(BGP_INPUT(peer));
3483
3484 /* Check whether Extended-Length applies and is in bounds */
3485 if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
3486 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
3487 flog_warn(
3488 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
3489 "%s: Extended length set, but just %lu bytes of attr header",
3490 peer->host,
3491 (unsigned long)(endp
3492 - stream_pnt(BGP_INPUT(peer))));
3493
3494 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3495 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3496 ret = BGP_ATTR_PARSE_ERROR;
3497 goto done;
3498 }
3499
3500 /* Check extended attribue length bit. */
3501 if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN))
3502 length = stream_getw(BGP_INPUT(peer));
3503 else
3504 length = stream_getc(BGP_INPUT(peer));
3505
3506 /* If any attribute appears more than once in the UPDATE
3507 message, then the Error Subcode is set to Malformed Attribute
3508 List. */
3509
3510 if (CHECK_BITMAP(seen, type)) {
3511 flog_warn(
3512 EC_BGP_ATTRIBUTE_REPEATED,
3513 "%s: error BGP attribute type %d appears twice in a message",
3514 peer->host, type);
3515
3516 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3517 BGP_NOTIFY_UPDATE_MAL_ATTR);
3518 ret = BGP_ATTR_PARSE_ERROR;
3519 goto done;
3520 }
3521
3522 /* Set type to bitmap to check duplicate attribute. `type' is
3523 unsigned char so it never overflow bitmap range. */
3524
3525 SET_BITMAP(seen, type);
3526
3527 /* Overflow check. */
3528 attr_endp = BGP_INPUT_PNT(peer) + length;
3529
3530 if (attr_endp > endp) {
3531 flog_warn(
3532 EC_BGP_ATTRIBUTE_TOO_LARGE,
3533 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3534 peer->host, type, length, size, attr_endp,
3535 endp);
3536 /*
3537 * RFC 4271 6.3
3538 * If any recognized attribute has an Attribute
3539 * Length that conflicts with the expected length
3540 * (based on the attribute type code), then the
3541 * Error Subcode MUST be set to Attribute Length
3542 * Error. The Data field MUST contain the erroneous
3543 * attribute (type, length, and value).
3544 * ----------
3545 * We do not currently have a good way to determine the
3546 * length of the attribute independent of the length
3547 * received in the message. Instead we send the
3548 * minimum between the amount of data we have and the
3549 * amount specified by the attribute length field.
3550 *
3551 * Instead of directly passing in the packet buffer and
3552 * offset we use the stream_get* functions to read into
3553 * a stack buffer, since they perform bounds checking
3554 * and we are working with untrusted data.
3555 */
3556 unsigned char ndata[peer->max_packet_size];
3557 memset(ndata, 0x00, sizeof(ndata));
3558 size_t lfl =
3559 CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 2 : 1;
3560 /* Rewind to end of flag field */
3561 stream_rewind_getp(BGP_INPUT(peer), (1 + lfl));
3562 /* Type */
3563 stream_get(&ndata[0], BGP_INPUT(peer), 1);
3564 /* Length */
3565 stream_get(&ndata[1], BGP_INPUT(peer), lfl);
3566 /* Value */
3567 size_t atl = attr_endp - startp;
3568 size_t ndl = MIN(atl, STREAM_READABLE(BGP_INPUT(peer)));
3569 stream_get(&ndata[lfl + 1], BGP_INPUT(peer), ndl);
3570
3571 bgp_notify_send_with_data(
3572 peer, BGP_NOTIFY_UPDATE_ERR,
3573 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
3574 ndl + lfl + 1);
3575
3576 ret = BGP_ATTR_PARSE_ERROR;
3577 goto done;
3578 }
3579
3580 struct bgp_attr_parser_args attr_args = {
3581 .peer = peer,
3582 .length = length,
3583 .attr = attr,
3584 .type = type,
3585 .flags = flag,
3586 .startp = startp,
3587 .total = attr_endp - startp,
3588 };
3589
3590
3591 /* If any recognized attribute has Attribute Flags that conflict
3592 with the Attribute Type Code, then the Error Subcode is set
3593 to
3594 Attribute Flags Error. The Data field contains the erroneous
3595 attribute (type, length and value). */
3596 if (bgp_attr_flag_invalid(&attr_args)) {
3597 ret = bgp_attr_malformed(
3598 &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
3599 attr_args.total);
3600 if (ret == BGP_ATTR_PARSE_PROCEED)
3601 continue;
3602 goto done;
3603 }
3604
3605 /* OK check attribute and store it's value. */
3606 switch (type) {
3607 case BGP_ATTR_ORIGIN:
3608 ret = bgp_attr_origin(&attr_args);
3609 break;
3610 case BGP_ATTR_AS_PATH:
3611 ret = bgp_attr_aspath(&attr_args);
3612 break;
3613 case BGP_ATTR_AS4_PATH:
3614 ret = bgp_attr_as4_path(&attr_args, &as4_path);
3615 break;
3616 case BGP_ATTR_NEXT_HOP:
3617 ret = bgp_attr_nexthop(&attr_args);
3618 break;
3619 case BGP_ATTR_MULTI_EXIT_DISC:
3620 ret = bgp_attr_med(&attr_args);
3621 break;
3622 case BGP_ATTR_LOCAL_PREF:
3623 ret = bgp_attr_local_pref(&attr_args);
3624 break;
3625 case BGP_ATTR_ATOMIC_AGGREGATE:
3626 ret = bgp_attr_atomic(&attr_args);
3627 break;
3628 case BGP_ATTR_AGGREGATOR:
3629 ret = bgp_attr_aggregator(&attr_args);
3630 break;
3631 case BGP_ATTR_AS4_AGGREGATOR:
3632 ret = bgp_attr_as4_aggregator(&attr_args,
3633 &as4_aggregator,
3634 &as4_aggregator_addr);
3635 break;
3636 case BGP_ATTR_COMMUNITIES:
3637 ret = bgp_attr_community(&attr_args);
3638 break;
3639 case BGP_ATTR_LARGE_COMMUNITIES:
3640 ret = bgp_attr_large_community(&attr_args);
3641 break;
3642 case BGP_ATTR_ORIGINATOR_ID:
3643 ret = bgp_attr_originator_id(&attr_args);
3644 break;
3645 case BGP_ATTR_CLUSTER_LIST:
3646 ret = bgp_attr_cluster_list(&attr_args);
3647 break;
3648 case BGP_ATTR_MP_REACH_NLRI:
3649 ret = bgp_mp_reach_parse(&attr_args, mp_update);
3650 break;
3651 case BGP_ATTR_MP_UNREACH_NLRI:
3652 ret = bgp_mp_unreach_parse(&attr_args, mp_withdraw);
3653 break;
3654 case BGP_ATTR_EXT_COMMUNITIES:
3655 ret = bgp_attr_ext_communities(&attr_args);
3656 break;
3657 #ifdef ENABLE_BGP_VNC_ATTR
3658 case BGP_ATTR_VNC:
3659 #endif
3660 case BGP_ATTR_ENCAP:
3661 ret = bgp_attr_encap(type, peer, length, attr, flag,
3662 startp);
3663 break;
3664 case BGP_ATTR_PREFIX_SID:
3665 ret = bgp_attr_prefix_sid(&attr_args);
3666 break;
3667 case BGP_ATTR_PMSI_TUNNEL:
3668 ret = bgp_attr_pmsi_tunnel(&attr_args);
3669 break;
3670 case BGP_ATTR_IPV6_EXT_COMMUNITIES:
3671 ret = bgp_attr_ipv6_ext_communities(&attr_args);
3672 break;
3673 case BGP_ATTR_OTC:
3674 ret = bgp_attr_otc(&attr_args);
3675 break;
3676 case BGP_ATTR_AIGP:
3677 ret = bgp_attr_aigp(&attr_args);
3678 break;
3679 default:
3680 ret = bgp_attr_unknown(&attr_args);
3681 break;
3682 }
3683
3684 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) {
3685 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3686 BGP_NOTIFY_UPDATE_MAL_ATTR);
3687 ret = BGP_ATTR_PARSE_ERROR;
3688 goto done;
3689 }
3690
3691 if (ret == BGP_ATTR_PARSE_EOR) {
3692 goto done;
3693 }
3694
3695 if (ret == BGP_ATTR_PARSE_ERROR) {
3696 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
3697 "%s: Attribute %s, parse error", peer->host,
3698 lookup_msg(attr_str, type, NULL));
3699 goto done;
3700 }
3701 if (ret == BGP_ATTR_PARSE_WITHDRAW) {
3702 flog_warn(
3703 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
3704 "%s: Attribute %s, parse error - treating as withdrawal",
3705 peer->host, lookup_msg(attr_str, type, NULL));
3706 goto done;
3707 }
3708
3709 /* Check the fetched length. */
3710 if (BGP_INPUT_PNT(peer) != attr_endp) {
3711 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR,
3712 "%s: BGP attribute %s, fetch error",
3713 peer->host, lookup_msg(attr_str, type, NULL));
3714 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3715 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3716 ret = BGP_ATTR_PARSE_ERROR;
3717 goto done;
3718 }
3719 }
3720
3721 /*
3722 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3723 * About Prefix-SID path attribute,
3724 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3725 * may only appear in a BGP Prefix-SID attribute attached to
3726 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3727 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3728 */
3729 if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST)
3730 attr->label_index = BGP_INVALID_LABEL_INDEX;
3731
3732 /* Check final read pointer is same as end pointer. */
3733 if (BGP_INPUT_PNT(peer) != endp) {
3734 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH,
3735 "%s: BGP attribute %s, length mismatch", peer->host,
3736 lookup_msg(attr_str, type, NULL));
3737 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3738 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3739
3740 ret = BGP_ATTR_PARSE_ERROR;
3741 goto done;
3742 }
3743
3744 /*
3745 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3746 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3747 * This is implemented below and will result in a NOTIFICATION. If the
3748 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3749 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3750 * message SHOULD NOT be sent. This is implemented elsewhere.
3751 *
3752 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3753 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3754 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3755 * speaker that receives the message SHOULD ignore this attribute.
3756 */
3757 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3758 && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
3759 if (bgp_attr_nexthop_valid(peer, attr) < 0) {
3760 ret = BGP_ATTR_PARSE_ERROR;
3761 goto done;
3762 }
3763 }
3764
3765 /* Check all mandatory well-known attributes are present */
3766 ret = bgp_attr_check(peer, attr);
3767 if (ret < 0)
3768 goto done;
3769
3770 /*
3771 * At this place we can see whether we got AS4_PATH and/or
3772 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3773 * We can not do this before we've read all attributes because
3774 * the as4 handling does not say whether AS4_PATH has to be sent
3775 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3776 * in relationship to AGGREGATOR.
3777 * So, to be defensive, we are not relying on any order and read
3778 * all attributes first, including these 32bit ones, and now,
3779 * afterwards, we look what and if something is to be done for as4.
3780 *
3781 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3782 * MP_UNREACH_NLRI.
3783 */
3784 /* actually... this doesn't ever return failure currently, but
3785 * better safe than sorry */
3786 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))
3787 && bgp_attr_munge_as4_attrs(peer, attr, as4_path, as4_aggregator,
3788 &as4_aggregator_addr)) {
3789 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3790 BGP_NOTIFY_UPDATE_MAL_ATTR);
3791 ret = BGP_ATTR_PARSE_ERROR;
3792 goto done;
3793 }
3794
3795 /*
3796 * Finally do the checks on the aspath we did not do yet
3797 * because we waited for a potentially synthesized aspath.
3798 */
3799 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
3800 ret = bgp_attr_aspath_check(peer, attr);
3801 if (ret != BGP_ATTR_PARSE_PROCEED)
3802 goto done;
3803 }
3804
3805 ret = BGP_ATTR_PARSE_PROCEED;
3806 done:
3807
3808 /*
3809 * At this stage, we have done all fiddling with as4, and the
3810 * resulting info is in attr->aggregator resp. attr->aspath so
3811 * we can chuck as4_aggregator and as4_path alltogether in order
3812 * to save memory
3813 */
3814 /*
3815 * unintern - it is in the hash
3816 * The flag that we got this is still there, but that
3817 * does not do any trouble
3818 */
3819 aspath_unintern(&as4_path);
3820
3821 transit = bgp_attr_get_transit(attr);
3822 if (ret != BGP_ATTR_PARSE_ERROR) {
3823 /* Finally intern unknown attribute. */
3824 if (transit)
3825 bgp_attr_set_transit(attr, transit_intern(transit));
3826 if (attr->encap_subtlvs)
3827 attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
3828 ENCAP_SUBTLV_TYPE);
3829 #ifdef ENABLE_BGP_VNC
3830 struct bgp_attr_encap_subtlv *vnc_subtlvs =
3831 bgp_attr_get_vnc_subtlvs(attr);
3832
3833 if (vnc_subtlvs)
3834 bgp_attr_set_vnc_subtlvs(
3835 attr,
3836 encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
3837 #endif
3838 } else {
3839 if (transit) {
3840 transit_free(transit);
3841 bgp_attr_set_transit(attr, NULL);
3842 }
3843
3844 bgp_attr_flush_encap(attr);
3845 };
3846
3847 /* Sanity checks */
3848 transit = bgp_attr_get_transit(attr);
3849 if (transit)
3850 assert(transit->refcnt > 0);
3851 if (attr->encap_subtlvs)
3852 assert(attr->encap_subtlvs->refcnt > 0);
3853 #ifdef ENABLE_BGP_VNC
3854 struct bgp_attr_encap_subtlv *vnc_subtlvs =
3855 bgp_attr_get_vnc_subtlvs(attr);
3856
3857 if (vnc_subtlvs)
3858 assert(vnc_subtlvs->refcnt > 0);
3859 #endif
3860
3861 return ret;
3862 }
3863
3864 /*
3865 * Extract the tunnel type from extended community
3866 */
3867 void bgp_attr_extcom_tunnel_type(struct attr *attr,
3868 bgp_encap_types *tunnel_type)
3869 {
3870 struct ecommunity *ecom;
3871 uint32_t i;
3872
3873 if (!attr)
3874 return;
3875
3876 ecom = bgp_attr_get_ecommunity(attr);
3877 if (!ecom || !ecom->size)
3878 return;
3879
3880 for (i = 0; i < ecom->size; i++) {
3881 uint8_t *pnt;
3882 uint8_t type, sub_type;
3883
3884 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
3885 type = pnt[0];
3886 sub_type = pnt[1];
3887 if (!(type == ECOMMUNITY_ENCODE_OPAQUE &&
3888 sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP))
3889 continue;
3890 *tunnel_type = ((pnt[6] << 8) | pnt[7]);
3891 return;
3892 }
3893
3894 return;
3895 }
3896
3897 size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
3898 safi_t safi, struct bpacket_attr_vec_arr *vecarr,
3899 struct attr *attr)
3900 {
3901 size_t sizep;
3902 iana_afi_t pkt_afi = IANA_AFI_IPV4;
3903 iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
3904 afi_t nh_afi;
3905
3906 /* Set extended bit always to encode the attribute length as 2 bytes */
3907 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
3908 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
3909 sizep = stream_get_endp(s);
3910 stream_putw(s, 0); /* Marker: Attribute length. */
3911
3912
3913 /* Convert AFI, SAFI to values for packet. */
3914 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
3915
3916 stream_putw(s, pkt_afi); /* AFI */
3917 stream_putc(s, pkt_safi); /* SAFI */
3918
3919 /* Nexthop AFI */
3920 if (afi == AFI_IP
3921 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST
3922 || safi == SAFI_MPLS_VPN || safi == SAFI_MULTICAST))
3923 nh_afi = peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : AFI_IP;
3924 else if (safi == SAFI_FLOWSPEC)
3925 nh_afi = afi;
3926 else
3927 nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
3928
3929 /* Nexthop */
3930 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, attr);
3931 switch (nh_afi) {
3932 case AFI_IP:
3933 switch (safi) {
3934 case SAFI_UNICAST:
3935 case SAFI_MULTICAST:
3936 case SAFI_LABELED_UNICAST:
3937 stream_putc(s, 4);
3938 stream_put_ipv4(s, attr->nexthop.s_addr);
3939 break;
3940 case SAFI_MPLS_VPN:
3941 stream_putc(s, 12);
3942 stream_putl(s, 0); /* RD = 0, per RFC */
3943 stream_putl(s, 0);
3944 stream_put(s, &attr->mp_nexthop_global_in, 4);
3945 break;
3946 case SAFI_ENCAP:
3947 case SAFI_EVPN:
3948 stream_putc(s, 4);
3949 stream_put(s, &attr->mp_nexthop_global_in, 4);
3950 break;
3951 case SAFI_FLOWSPEC:
3952 if (attr->mp_nexthop_len == 0)
3953 stream_putc(s, 0); /* no nexthop for flowspec */
3954 else {
3955 stream_putc(s, attr->mp_nexthop_len);
3956 stream_put_ipv4(s, attr->nexthop.s_addr);
3957 }
3958 break;
3959 case SAFI_UNSPEC:
3960 case SAFI_MAX:
3961 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3962 break;
3963 }
3964 break;
3965 case AFI_IP6:
3966 switch (safi) {
3967 case SAFI_UNICAST:
3968 case SAFI_MULTICAST:
3969 case SAFI_LABELED_UNICAST:
3970 case SAFI_EVPN: {
3971 if (attr->mp_nexthop_len
3972 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3973 stream_putc(s,
3974 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
3975 stream_put(s, &attr->mp_nexthop_global,
3976 IPV6_MAX_BYTELEN);
3977 stream_put(s, &attr->mp_nexthop_local,
3978 IPV6_MAX_BYTELEN);
3979 } else {
3980 stream_putc(s, IPV6_MAX_BYTELEN);
3981 stream_put(s, &attr->mp_nexthop_global,
3982 IPV6_MAX_BYTELEN);
3983 }
3984 } break;
3985 case SAFI_MPLS_VPN: {
3986 if (attr->mp_nexthop_len ==
3987 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
3988 stream_putc(s, 48);
3989 stream_putl(s, 0); /* RD = 0, per RFC */
3990 stream_putl(s, 0);
3991 stream_put(s, &attr->mp_nexthop_global,
3992 IPV6_MAX_BYTELEN);
3993 stream_putl(s, 0); /* RD = 0, per RFC */
3994 stream_putl(s, 0);
3995 stream_put(s, &attr->mp_nexthop_local,
3996 IPV6_MAX_BYTELEN);
3997 } else {
3998 stream_putc(s, 24);
3999 stream_putl(s, 0); /* RD = 0, per RFC */
4000 stream_putl(s, 0);
4001 stream_put(s, &attr->mp_nexthop_global,
4002 IPV6_MAX_BYTELEN);
4003 }
4004 } break;
4005 case SAFI_ENCAP:
4006 stream_putc(s, IPV6_MAX_BYTELEN);
4007 stream_put(s, &attr->mp_nexthop_global,
4008 IPV6_MAX_BYTELEN);
4009 break;
4010 case SAFI_FLOWSPEC:
4011 stream_putc(s, 0); /* no nexthop for flowspec */
4012 break;
4013 case SAFI_UNSPEC:
4014 case SAFI_MAX:
4015 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
4016 break;
4017 }
4018 break;
4019 case AFI_L2VPN:
4020 if (safi != SAFI_FLOWSPEC)
4021 flog_err(
4022 EC_BGP_ATTR_NH_SEND_LEN,
4023 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
4024 peer->host, afi, safi, attr->mp_nexthop_len);
4025 break;
4026 case AFI_UNSPEC:
4027 case AFI_MAX:
4028 assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
4029 break;
4030 }
4031
4032 /* SNPA */
4033 stream_putc(s, 0);
4034 return sizep;
4035 }
4036
4037 void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
4038 const struct prefix *p,
4039 const struct prefix_rd *prd, mpls_label_t *label,
4040 uint32_t num_labels, bool addpath_capable,
4041 uint32_t addpath_tx_id, struct attr *attr)
4042 {
4043 switch (safi) {
4044 case SAFI_UNSPEC:
4045 case SAFI_MAX:
4046 assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
4047 break;
4048 case SAFI_MPLS_VPN:
4049 if (addpath_capable)
4050 stream_putl(s, addpath_tx_id);
4051 /* Label, RD, Prefix write. */
4052 stream_putc(s, p->prefixlen + 88);
4053 stream_put(s, label, BGP_LABEL_BYTES);
4054 stream_put(s, prd->val, 8);
4055 stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
4056 break;
4057 case SAFI_EVPN:
4058 if (afi == AFI_L2VPN)
4059 /* EVPN prefix - contents depend on type */
4060 bgp_evpn_encode_prefix(s, p, prd, label, num_labels,
4061 attr, addpath_capable,
4062 addpath_tx_id);
4063 else
4064 assert(!"Add encoding bits here for other AFI's");
4065 break;
4066 case SAFI_LABELED_UNICAST:
4067 /* Prefix write with label. */
4068 stream_put_labeled_prefix(s, p, label, addpath_capable,
4069 addpath_tx_id);
4070 break;
4071 case SAFI_FLOWSPEC:
4072 stream_putc(s, p->u.prefix_flowspec.prefixlen);
4073 stream_put(s, (const void *)p->u.prefix_flowspec.ptr,
4074 p->u.prefix_flowspec.prefixlen);
4075 break;
4076
4077 case SAFI_UNICAST:
4078 case SAFI_MULTICAST:
4079 stream_put_prefix_addpath(s, p, addpath_capable, addpath_tx_id);
4080 break;
4081 case SAFI_ENCAP:
4082 assert(!"Please add proper encoding of SAFI_ENCAP");
4083 break;
4084 }
4085 }
4086
4087 size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
4088 const struct prefix *p)
4089 {
4090 int size = PSIZE(p->prefixlen);
4091
4092 switch (safi) {
4093 case SAFI_UNSPEC:
4094 case SAFI_MAX:
4095 assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4096 break;
4097 case SAFI_UNICAST:
4098 case SAFI_MULTICAST:
4099 break;
4100 case SAFI_MPLS_VPN:
4101 size += 88;
4102 break;
4103 case SAFI_ENCAP:
4104 /* This has to be wrong, but I don't know what to put here */
4105 assert(!"Do we try to use this?");
4106 break;
4107 case SAFI_LABELED_UNICAST:
4108 size += BGP_LABEL_BYTES;
4109 break;
4110 case SAFI_EVPN:
4111 /*
4112 * TODO: Maximum possible for type-2, type-3 and type-5
4113 */
4114 if (afi == AFI_L2VPN)
4115 size += 232;
4116 else
4117 assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4118 break;
4119 case SAFI_FLOWSPEC:
4120 size = ((struct prefix_fs *)p)->prefix.prefixlen;
4121 break;
4122 }
4123
4124 return size;
4125 }
4126
4127 /*
4128 * Encodes the tunnel encapsulation attribute,
4129 * and with ENABLE_BGP_VNC the VNC attribute which uses
4130 * almost the same TLV format
4131 */
4132 static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
4133 struct stream *s, struct attr *attr,
4134 uint8_t attrtype)
4135 {
4136 unsigned int attrlenfield = 0;
4137 unsigned int attrhdrlen = 0;
4138 struct bgp_attr_encap_subtlv *subtlvs;
4139 struct bgp_attr_encap_subtlv *st;
4140 const char *attrname;
4141
4142 if (!attr || (attrtype == BGP_ATTR_ENCAP
4143 && (!attr->encap_tunneltype
4144 || attr->encap_tunneltype == BGP_ENCAP_TYPE_MPLS)))
4145 return;
4146
4147 switch (attrtype) {
4148 case BGP_ATTR_ENCAP:
4149 attrname = "Tunnel Encap";
4150 subtlvs = attr->encap_subtlvs;
4151 if (subtlvs == NULL) /* nothing to do */
4152 return;
4153 /*
4154 * The tunnel encap attr has an "outer" tlv.
4155 * T = tunneltype,
4156 * L = total length of subtlvs,
4157 * V = concatenated subtlvs.
4158 */
4159 attrlenfield = 2 + 2; /* T + L */
4160 attrhdrlen = 1 + 1; /* subTLV T + L */
4161 break;
4162
4163 #ifdef ENABLE_BGP_VNC_ATTR
4164 case BGP_ATTR_VNC:
4165 attrname = "VNC";
4166 subtlvs = bgp_attr_get_vnc_subtlvs(attr);
4167 if (subtlvs == NULL) /* nothing to do */
4168 return;
4169 attrlenfield = 0; /* no outer T + L */
4170 attrhdrlen = 2 + 2; /* subTLV T + L */
4171 break;
4172 #endif
4173
4174 default:
4175 assert(0);
4176 }
4177
4178 /* compute attr length */
4179 for (st = subtlvs; st; st = st->next) {
4180 attrlenfield += (attrhdrlen + st->length);
4181 }
4182
4183 if (attrlenfield > 0xffff) {
4184 zlog_info("%s attribute is too long (length=%d), can't send it",
4185 attrname, attrlenfield);
4186 return;
4187 }
4188
4189 if (attrlenfield > 0xff) {
4190 /* 2-octet length field */
4191 stream_putc(s,
4192 BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4193 | BGP_ATTR_FLAG_EXTLEN);
4194 stream_putc(s, attrtype);
4195 stream_putw(s, attrlenfield & 0xffff);
4196 } else {
4197 /* 1-octet length field */
4198 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL);
4199 stream_putc(s, attrtype);
4200 stream_putc(s, attrlenfield & 0xff);
4201 }
4202
4203 if (attrtype == BGP_ATTR_ENCAP) {
4204 /* write outer T+L */
4205 stream_putw(s, attr->encap_tunneltype);
4206 stream_putw(s, attrlenfield - 4);
4207 }
4208
4209 /* write each sub-tlv */
4210 for (st = subtlvs; st; st = st->next) {
4211 if (attrtype == BGP_ATTR_ENCAP) {
4212 stream_putc(s, st->type);
4213 stream_putc(s, st->length);
4214 #ifdef ENABLE_BGP_VNC
4215 } else {
4216 stream_putw(s, st->type);
4217 stream_putw(s, st->length);
4218 #endif
4219 }
4220 stream_put(s, st->value, st->length);
4221 }
4222 }
4223
4224 void bgp_packet_mpattr_end(struct stream *s, size_t sizep)
4225 {
4226 /* Set MP attribute length. Don't count the (2) bytes used to encode
4227 the attr length */
4228 stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2);
4229 }
4230
4231 static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
4232 {
4233 if (!BGP_AS_IS_PRIVATE(peer->local_as)
4234 || (BGP_AS_IS_PRIVATE(peer->local_as)
4235 && !CHECK_FLAG(peer->af_flags[afi][safi],
4236 PEER_FLAG_REMOVE_PRIVATE_AS)
4237 && !CHECK_FLAG(peer->af_flags[afi][safi],
4238 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
4239 && !CHECK_FLAG(peer->af_flags[afi][safi],
4240 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
4241 && !CHECK_FLAG(peer->af_flags[afi][safi],
4242 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)))
4243 return true;
4244 return false;
4245 }
4246
4247 /* Make attribute packet. */
4248 bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
4249 struct stream *s, struct attr *attr,
4250 struct bpacket_attr_vec_arr *vecarr,
4251 struct prefix *p, afi_t afi, safi_t safi,
4252 struct peer *from, struct prefix_rd *prd,
4253 mpls_label_t *label, uint32_t num_labels,
4254 bool addpath_capable, uint32_t addpath_tx_id,
4255 struct bgp_path_info *bpi)
4256 {
4257 size_t cp;
4258 size_t aspath_sizep;
4259 struct aspath *aspath;
4260 int send_as4_path = 0;
4261 int send_as4_aggregator = 0;
4262 bool use32bit = CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
4263 && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV);
4264
4265 if (!bgp)
4266 bgp = peer->bgp;
4267
4268 /* Remember current pointer. */
4269 cp = stream_get_endp(s);
4270
4271 if (p
4272 && !((afi == AFI_IP && safi == SAFI_UNICAST)
4273 && !peer_cap_enhe(peer, afi, safi))) {
4274 size_t mpattrlen_pos = 0;
4275
4276 mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
4277 vecarr, attr);
4278 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
4279 num_labels, addpath_capable,
4280 addpath_tx_id, attr);
4281 bgp_packet_mpattr_end(s, mpattrlen_pos);
4282 }
4283
4284 /* Origin attribute. */
4285 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4286 stream_putc(s, BGP_ATTR_ORIGIN);
4287 stream_putc(s, 1);
4288 stream_putc(s, attr->origin);
4289
4290 /* AS path attribute. */
4291
4292 /* If remote-peer is EBGP */
4293 if (peer->sort == BGP_PEER_EBGP
4294 && (!CHECK_FLAG(peer->af_flags[afi][safi],
4295 PEER_FLAG_AS_PATH_UNCHANGED)
4296 || attr->aspath->segments == NULL)
4297 && (!CHECK_FLAG(peer->af_flags[afi][safi],
4298 PEER_FLAG_RSERVER_CLIENT))) {
4299 aspath = aspath_dup(attr->aspath);
4300
4301 /* Even though we may not be configured for confederations we
4302 * may have
4303 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4304 aspath = aspath_delete_confed_seq(aspath);
4305
4306 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
4307 /* Stuff our path CONFED_ID on the front */
4308 aspath = aspath_add_seq(aspath, bgp->confed_id);
4309 } else {
4310 if (peer->change_local_as) {
4311 /* If replace-as is specified, we only use the
4312 change_local_as when
4313 advertising routes. */
4314 if (!CHECK_FLAG(peer->flags,
4315 PEER_FLAG_LOCAL_AS_REPLACE_AS))
4316 if (bgp_append_local_as(peer, afi,
4317 safi))
4318 aspath = aspath_add_seq(
4319 aspath, peer->local_as);
4320 aspath = aspath_add_seq(aspath,
4321 peer->change_local_as);
4322 } else {
4323 aspath = aspath_add_seq(aspath, peer->local_as);
4324 }
4325 }
4326 } else if (peer->sort == BGP_PEER_CONFED) {
4327 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4328 * thing */
4329 aspath = aspath_dup(attr->aspath);
4330 aspath = aspath_add_confed_seq(aspath, peer->local_as);
4331 } else
4332 aspath = attr->aspath;
4333
4334 /* If peer is not AS4 capable, then:
4335 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4336 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4337 * segment
4338 * types are in it (i.e. exclude them if they are there)
4339 * AND do this only if there is at least one asnum > 65535 in the
4340 * path!
4341 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4342 * change
4343 * all ASnums > 65535 to BGP_AS_TRANS
4344 */
4345
4346 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4347 stream_putc(s, BGP_ATTR_AS_PATH);
4348 aspath_sizep = stream_get_endp(s);
4349 stream_putw(s, 0);
4350 stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, use32bit));
4351
4352 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4353 * in the path
4354 */
4355 if (!use32bit && aspath_has_as4(aspath))
4356 send_as4_path =
4357 1; /* we'll do this later, at the correct place */
4358
4359 /* Nexthop attribute. */
4360 if (afi == AFI_IP && safi == SAFI_UNICAST
4361 && !peer_cap_enhe(peer, afi, safi)) {
4362 afi_t nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
4363
4364 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
4365 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4366 stream_putc(s, BGP_ATTR_NEXT_HOP);
4367 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4368 attr);
4369 stream_putc(s, 4);
4370 stream_put_ipv4(s, attr->nexthop.s_addr);
4371 } else if (peer_cap_enhe(from, afi, safi)
4372 || (nh_afi == AFI_IP6)) {
4373 /*
4374 * Likely this is the case when an IPv4 prefix was
4375 * received with Extended Next-hop capability in this
4376 * or another vrf and is now being advertised to
4377 * non-ENHE peers. Since peer_cap_enhe only checks
4378 * peers in this vrf, also check the nh_afi to catch
4379 * the case where the originator was in another vrf.
4380 * Setting the mandatory (ipv4) next-hop attribute here
4381 * to enable implicit next-hop self with correct A-F
4382 * (ipv4 address family).
4383 */
4384 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4385 stream_putc(s, BGP_ATTR_NEXT_HOP);
4386 bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4387 NULL);
4388 stream_putc(s, 4);
4389 stream_put_ipv4(s, 0);
4390 }
4391 }
4392
4393 /* MED attribute. */
4394 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)
4395 || bgp->maxmed_active) {
4396 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4397 stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4398 stream_putc(s, 4);
4399 stream_putl(s, (bgp->maxmed_active ? bgp->maxmed_value
4400 : attr->med));
4401 }
4402
4403 /* Local preference. */
4404 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
4405 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4406 stream_putc(s, BGP_ATTR_LOCAL_PREF);
4407 stream_putc(s, 4);
4408 stream_putl(s, attr->local_pref);
4409 }
4410
4411 /* Atomic aggregate. */
4412 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4413 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4414 stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4415 stream_putc(s, 0);
4416 }
4417
4418 /* Aggregator. */
4419 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4420 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4421 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4422 stream_putc(s, BGP_ATTR_AGGREGATOR);
4423
4424 if (use32bit) {
4425 /* AS4 capable peer */
4426 stream_putc(s, 8);
4427 stream_putl(s, attr->aggregator_as);
4428 } else {
4429 /* 2-byte AS peer */
4430 stream_putc(s, 6);
4431
4432 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4433 * used? */
4434 if (attr->aggregator_as > UINT16_MAX) {
4435 stream_putw(s, BGP_AS_TRANS);
4436
4437 /* we have to send AS4_AGGREGATOR, too.
4438 * we'll do that later in order to send
4439 * attributes in ascending
4440 * order.
4441 */
4442 send_as4_aggregator = 1;
4443 } else
4444 stream_putw(s, (uint16_t)attr->aggregator_as);
4445 }
4446 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4447 }
4448
4449 /* Community attribute. */
4450 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
4451 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
4452 struct community *comm = NULL;
4453
4454 comm = bgp_attr_get_community(attr);
4455 if (comm->size * 4 > 255) {
4456 stream_putc(s,
4457 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4458 | BGP_ATTR_FLAG_EXTLEN);
4459 stream_putc(s, BGP_ATTR_COMMUNITIES);
4460 stream_putw(s, comm->size * 4);
4461 } else {
4462 stream_putc(s,
4463 BGP_ATTR_FLAG_OPTIONAL
4464 | BGP_ATTR_FLAG_TRANS);
4465 stream_putc(s, BGP_ATTR_COMMUNITIES);
4466 stream_putc(s, comm->size * 4);
4467 }
4468 stream_put(s, comm->val, comm->size * 4);
4469 }
4470
4471 /*
4472 * Large Community attribute.
4473 */
4474 if (CHECK_FLAG(peer->af_flags[afi][safi],
4475 PEER_FLAG_SEND_LARGE_COMMUNITY)
4476 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
4477 if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
4478 stream_putc(s,
4479 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4480 | BGP_ATTR_FLAG_EXTLEN);
4481 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4482 stream_putw(s,
4483 lcom_length(bgp_attr_get_lcommunity(attr)));
4484 } else {
4485 stream_putc(s,
4486 BGP_ATTR_FLAG_OPTIONAL
4487 | BGP_ATTR_FLAG_TRANS);
4488 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4489 stream_putc(s,
4490 lcom_length(bgp_attr_get_lcommunity(attr)));
4491 }
4492 stream_put(s, bgp_attr_get_lcommunity(attr)->val,
4493 lcom_length(bgp_attr_get_lcommunity(attr)));
4494 }
4495
4496 /* Route Reflector. */
4497 if (peer->sort == BGP_PEER_IBGP && from
4498 && from->sort == BGP_PEER_IBGP) {
4499 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
4500
4501 /* Originator ID. */
4502 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4503 stream_putc(s, BGP_ATTR_ORIGINATOR_ID);
4504 stream_putc(s, 4);
4505
4506 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
4507 stream_put_in_addr(s, &attr->originator_id);
4508 else
4509 stream_put_in_addr(s, &from->remote_id);
4510
4511 /* Cluster list. */
4512 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4513 stream_putc(s, BGP_ATTR_CLUSTER_LIST);
4514
4515 if (cluster) {
4516 stream_putc(s, cluster->length + 4);
4517 /* If this peer configuration's parent BGP has
4518 * cluster_id. */
4519 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4520 stream_put_in_addr(s, &bgp->cluster_id);
4521 else
4522 stream_put_in_addr(s, &bgp->router_id);
4523 stream_put(s, cluster->list, cluster->length);
4524 } else {
4525 stream_putc(s, 4);
4526 /* If this peer configuration's parent BGP has
4527 * cluster_id. */
4528 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4529 stream_put_in_addr(s, &bgp->cluster_id);
4530 else
4531 stream_put_in_addr(s, &bgp->router_id);
4532 }
4533 }
4534
4535 /* Extended Communities attribute. */
4536 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
4537 && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4538 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
4539 bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
4540 PEER_FLAG_RSERVER_CLIENT) &&
4541 from &&
4542 CHECK_FLAG(from->af_flags[afi][safi],
4543 PEER_FLAG_RSERVER_CLIENT);
4544
4545 if (peer->sort == BGP_PEER_IBGP ||
4546 peer->sort == BGP_PEER_CONFED || transparent) {
4547 if (ecomm->size * 8 > 255) {
4548 stream_putc(s,
4549 BGP_ATTR_FLAG_OPTIONAL
4550 | BGP_ATTR_FLAG_TRANS
4551 | BGP_ATTR_FLAG_EXTLEN);
4552 stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
4553 stream_putw(s, ecomm->size * 8);
4554 } else {
4555 stream_putc(s,
4556 BGP_ATTR_FLAG_OPTIONAL
4557 | BGP_ATTR_FLAG_TRANS);
4558 stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
4559 stream_putc(s, ecomm->size * 8);
4560 }
4561 stream_put(s, ecomm->val, ecomm->size * 8);
4562 } else {
4563 uint8_t *pnt;
4564 int tbit;
4565 int ecom_tr_size = 0;
4566 uint32_t i;
4567
4568 for (i = 0; i < ecomm->size; i++) {
4569 pnt = ecomm->val + (i * 8);
4570 tbit = *pnt;
4571
4572 if (CHECK_FLAG(tbit,
4573 ECOMMUNITY_FLAG_NON_TRANSITIVE))
4574 continue;
4575
4576 ecom_tr_size++;
4577 }
4578
4579 if (ecom_tr_size) {
4580 if (ecom_tr_size * 8 > 255) {
4581 stream_putc(
4582 s,
4583 BGP_ATTR_FLAG_OPTIONAL
4584 | BGP_ATTR_FLAG_TRANS
4585 | BGP_ATTR_FLAG_EXTLEN);
4586 stream_putc(s,
4587 BGP_ATTR_EXT_COMMUNITIES);
4588 stream_putw(s, ecom_tr_size * 8);
4589 } else {
4590 stream_putc(
4591 s,
4592 BGP_ATTR_FLAG_OPTIONAL
4593 | BGP_ATTR_FLAG_TRANS);
4594 stream_putc(s,
4595 BGP_ATTR_EXT_COMMUNITIES);
4596 stream_putc(s, ecom_tr_size * 8);
4597 }
4598
4599 for (i = 0; i < ecomm->size; i++) {
4600 pnt = ecomm->val + (i * 8);
4601 tbit = *pnt;
4602
4603 if (CHECK_FLAG(
4604 tbit,
4605 ECOMMUNITY_FLAG_NON_TRANSITIVE))
4606 continue;
4607
4608 stream_put(s, pnt, 8);
4609 }
4610 }
4611 }
4612 }
4613
4614 /* Label index attribute. */
4615 if (safi == SAFI_LABELED_UNICAST) {
4616 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
4617 uint32_t label_index;
4618
4619 label_index = attr->label_index;
4620
4621 if (label_index != BGP_INVALID_LABEL_INDEX) {
4622 stream_putc(s,
4623 BGP_ATTR_FLAG_OPTIONAL
4624 | BGP_ATTR_FLAG_TRANS);
4625 stream_putc(s, BGP_ATTR_PREFIX_SID);
4626 stream_putc(s, 10);
4627 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
4628 stream_putw(s,
4629 BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
4630 stream_putc(s, 0); // reserved
4631 stream_putw(s, 0); // flags
4632 stream_putl(s, label_index);
4633 }
4634 }
4635 }
4636
4637 /* SRv6 Service Information Attribute. */
4638 if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN) {
4639 if (attr->srv6_l3vpn) {
4640 uint8_t subtlv_len =
4641 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4642 + BGP_ATTR_MIN_LEN
4643 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH;
4644 uint8_t tlv_len = subtlv_len + BGP_ATTR_MIN_LEN + 1;
4645 uint8_t attr_len = tlv_len + BGP_ATTR_MIN_LEN;
4646 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4647 | BGP_ATTR_FLAG_TRANS);
4648 stream_putc(s, BGP_ATTR_PREFIX_SID);
4649 stream_putc(s, attr_len);
4650 stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE);
4651 stream_putw(s, tlv_len);
4652 stream_putc(s, 0); /* reserved */
4653 stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO);
4654 stream_putw(s, subtlv_len);
4655 stream_putc(s, 0); /* reserved */
4656 stream_put(s, &attr->srv6_l3vpn->sid,
4657 sizeof(attr->srv6_l3vpn->sid)); /* sid */
4658 stream_putc(s, 0); /* sid_flags */
4659 stream_putw(s,
4660 attr->srv6_l3vpn
4661 ->endpoint_behavior); /* endpoint */
4662 stream_putc(s, 0); /* reserved */
4663 stream_putc(
4664 s,
4665 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE);
4666 stream_putw(
4667 s,
4668 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH);
4669 stream_putc(s, attr->srv6_l3vpn->loc_block_len);
4670 stream_putc(s, attr->srv6_l3vpn->loc_node_len);
4671 stream_putc(s, attr->srv6_l3vpn->func_len);
4672 stream_putc(s, attr->srv6_l3vpn->arg_len);
4673 stream_putc(s, attr->srv6_l3vpn->transposition_len);
4674 stream_putc(s, attr->srv6_l3vpn->transposition_offset);
4675 } else if (attr->srv6_vpn) {
4676 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4677 | BGP_ATTR_FLAG_TRANS);
4678 stream_putc(s, BGP_ATTR_PREFIX_SID);
4679 stream_putc(s, 22); /* tlv len */
4680 stream_putc(s, BGP_PREFIX_SID_VPN_SID);
4681 stream_putw(s, 0x13); /* tlv len */
4682 stream_putc(s, 0x00); /* reserved */
4683 stream_putc(s, 0x01); /* sid_type */
4684 stream_putc(s, 0x00); /* sif_flags */
4685 stream_put(s, &attr->srv6_vpn->sid,
4686 sizeof(attr->srv6_vpn->sid)); /* sid */
4687 }
4688 }
4689
4690 if (send_as4_path) {
4691 /* If the peer is NOT As4 capable, AND */
4692 /* there are ASnums > 65535 in path THEN
4693 * give out AS4_PATH */
4694
4695 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4696 * path segments!
4697 * Hm, I wonder... confederation things *should* only be at
4698 * the beginning of an aspath, right? Then we should use
4699 * aspath_delete_confed_seq for this, because it is already
4700 * there! (JK)
4701 * Folks, talk to me: what is reasonable here!?
4702 */
4703 aspath = aspath_delete_confed_seq(aspath);
4704
4705 stream_putc(s,
4706 BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4707 | BGP_ATTR_FLAG_EXTLEN);
4708 stream_putc(s, BGP_ATTR_AS4_PATH);
4709 aspath_sizep = stream_get_endp(s);
4710 stream_putw(s, 0);
4711 stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, 1));
4712 }
4713
4714 if (aspath != attr->aspath)
4715 aspath_free(aspath);
4716
4717 if (send_as4_aggregator) {
4718 /* send AS4_AGGREGATOR, at this place */
4719 /* this section of code moved here in order to ensure the
4720 * correct
4721 * *ascending* order of attributes
4722 */
4723 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4724 stream_putc(s, BGP_ATTR_AS4_AGGREGATOR);
4725 stream_putc(s, 8);
4726 stream_putl(s, attr->aggregator_as);
4727 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4728 }
4729
4730 if (((afi == AFI_IP || afi == AFI_IP6)
4731 && (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
4732 || (afi == AFI_L2VPN && safi == SAFI_EVPN)) {
4733 /* Tunnel Encap attribute */
4734 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
4735
4736 #ifdef ENABLE_BGP_VNC_ATTR
4737 /* VNC attribute */
4738 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC);
4739 #endif
4740 }
4741
4742 /* PMSI Tunnel */
4743 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
4744 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4745 stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
4746 stream_putc(s, 9); // Length
4747 stream_putc(s, 0); // Flags
4748 stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr));
4749 stream_put(s, &(attr->label),
4750 BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
4751 stream_put_ipv4(s, attr->nexthop.s_addr);
4752 // Unicast tunnel endpoint IP address
4753 }
4754
4755 /* OTC */
4756 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
4757 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4758 stream_putc(s, BGP_ATTR_OTC);
4759 stream_putc(s, 4);
4760 stream_putl(s, attr->otc);
4761 }
4762
4763 /* AIGP */
4764 if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
4765 (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
4766 peer->sort != BGP_PEER_EBGP)) {
4767 /* At the moment only AIGP Metric TLV exists for AIGP
4768 * attribute. If more comes in, do not forget to update
4769 * attr_len variable to include new ones.
4770 */
4771 uint8_t attr_len = BGP_AIGP_TLV_METRIC_LEN;
4772
4773 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4774 stream_putc(s, BGP_ATTR_AIGP);
4775 stream_putc(s, attr_len);
4776 stream_put_bgp_aigp_tlv_metric(s, bpi);
4777 }
4778
4779 /* Unknown transit attribute. */
4780 struct transit *transit = bgp_attr_get_transit(attr);
4781
4782 if (transit)
4783 stream_put(s, transit->val, transit->length);
4784
4785 /* Return total size of attribute. */
4786 return stream_get_endp(s) - cp;
4787 }
4788
4789 size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
4790 {
4791 unsigned long attrlen_pnt;
4792 iana_afi_t pkt_afi = IANA_AFI_IPV4;
4793 iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
4794
4795 /* Set extended bit always to encode the attribute length as 2 bytes */
4796 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
4797 stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI);
4798
4799 attrlen_pnt = stream_get_endp(s);
4800 stream_putw(s, 0); /* Length of this attribute. */
4801
4802 /* Convert AFI, SAFI to values for packet. */
4803 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
4804
4805 stream_putw(s, pkt_afi);
4806 stream_putc(s, pkt_safi);
4807
4808 return attrlen_pnt;
4809 }
4810
4811 void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
4812 afi_t afi, safi_t safi,
4813 const struct prefix_rd *prd,
4814 mpls_label_t *label, uint32_t num_labels,
4815 bool addpath_capable, uint32_t addpath_tx_id,
4816 struct attr *attr)
4817 {
4818 uint8_t wlabel[4] = {0x80, 0x00, 0x00};
4819
4820 if (safi == SAFI_LABELED_UNICAST) {
4821 label = (mpls_label_t *)wlabel;
4822 num_labels = 1;
4823 }
4824
4825 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
4826 addpath_capable, addpath_tx_id, attr);
4827 }
4828
4829 void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt)
4830 {
4831 bgp_packet_mpattr_end(s, attrlen_pnt);
4832 }
4833
4834 /* Initialization of attribute. */
4835 void bgp_attr_init(void)
4836 {
4837 aspath_init();
4838 attrhash_init();
4839 community_init();
4840 ecommunity_init();
4841 lcommunity_init();
4842 cluster_init();
4843 transit_init();
4844 encap_init();
4845 srv6_init();
4846 }
4847
4848 void bgp_attr_finish(void)
4849 {
4850 aspath_finish();
4851 attrhash_finish();
4852 community_finish();
4853 ecommunity_finish();
4854 lcommunity_finish();
4855 cluster_finish();
4856 transit_finish();
4857 encap_finish();
4858 srv6_finish();
4859 }
4860
4861 /* Make attribute packet. */
4862 void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
4863 const struct prefix *prefix)
4864 {
4865 unsigned long cp;
4866 unsigned long len;
4867 size_t aspath_lenp;
4868 struct aspath *aspath;
4869 bool addpath_capable = false;
4870 uint32_t addpath_tx_id = 0;
4871 struct attr *attr = bpi->attr;
4872
4873 /* Remember current pointer. */
4874 cp = stream_get_endp(s);
4875
4876 /* Place holder of length. */
4877 stream_putw(s, 0);
4878
4879 /* Origin attribute. */
4880 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4881 stream_putc(s, BGP_ATTR_ORIGIN);
4882 stream_putc(s, 1);
4883 stream_putc(s, attr->origin);
4884
4885 aspath = attr->aspath;
4886
4887 stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4888 stream_putc(s, BGP_ATTR_AS_PATH);
4889 aspath_lenp = stream_get_endp(s);
4890 stream_putw(s, 0);
4891
4892 stream_putw_at(s, aspath_lenp, aspath_put(s, aspath, 1));
4893
4894 /* Nexthop attribute. */
4895 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4896 if (prefix != NULL && prefix->family != AF_INET6) {
4897 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4898 stream_putc(s, BGP_ATTR_NEXT_HOP);
4899 stream_putc(s, 4);
4900 stream_put_ipv4(s, attr->nexthop.s_addr);
4901 }
4902
4903 /* MED attribute. */
4904 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
4905 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4906 stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4907 stream_putc(s, 4);
4908 stream_putl(s, attr->med);
4909 }
4910
4911 /* Local preference. */
4912 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
4913 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4914 stream_putc(s, BGP_ATTR_LOCAL_PREF);
4915 stream_putc(s, 4);
4916 stream_putl(s, attr->local_pref);
4917 }
4918
4919 /* Atomic aggregate. */
4920 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4921 stream_putc(s, BGP_ATTR_FLAG_TRANS);
4922 stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4923 stream_putc(s, 0);
4924 }
4925
4926 /* Aggregator. */
4927 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4928 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4929 stream_putc(s, BGP_ATTR_AGGREGATOR);
4930 stream_putc(s, 8);
4931 stream_putl(s, attr->aggregator_as);
4932 stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4933 }
4934
4935 /* Community attribute. */
4936 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
4937 struct community *comm = NULL;
4938
4939 comm = bgp_attr_get_community(attr);
4940 if (comm->size * 4 > 255) {
4941 stream_putc(s,
4942 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4943 | BGP_ATTR_FLAG_EXTLEN);
4944 stream_putc(s, BGP_ATTR_COMMUNITIES);
4945 stream_putw(s, comm->size * 4);
4946 } else {
4947 stream_putc(s,
4948 BGP_ATTR_FLAG_OPTIONAL
4949 | BGP_ATTR_FLAG_TRANS);
4950 stream_putc(s, BGP_ATTR_COMMUNITIES);
4951 stream_putc(s, comm->size * 4);
4952 }
4953 stream_put(s, comm->val, comm->size * 4);
4954 }
4955
4956 /* Large Community attribute. */
4957 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
4958 if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
4959 stream_putc(s,
4960 BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4961 | BGP_ATTR_FLAG_EXTLEN);
4962 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4963 stream_putw(s,
4964 lcom_length(bgp_attr_get_lcommunity(attr)));
4965 } else {
4966 stream_putc(s,
4967 BGP_ATTR_FLAG_OPTIONAL
4968 | BGP_ATTR_FLAG_TRANS);
4969 stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4970 stream_putc(s,
4971 lcom_length(bgp_attr_get_lcommunity(attr)));
4972 }
4973
4974 stream_put(s, bgp_attr_get_lcommunity(attr)->val,
4975 lcom_length(bgp_attr_get_lcommunity(attr)));
4976 }
4977
4978 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4979 if (prefix != NULL && prefix->family == AF_INET6
4980 && (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
4981 || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)) {
4982 int sizep;
4983
4984 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4985 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
4986 sizep = stream_get_endp(s);
4987
4988 /* MP header */
4989 stream_putc(s, 0); /* Marker: Attribute length. */
4990 stream_putw(s, AFI_IP6); /* AFI */
4991 stream_putc(s, SAFI_UNICAST); /* SAFI */
4992
4993 /* Next hop */
4994 stream_putc(s, attr->mp_nexthop_len);
4995 stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN);
4996 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
4997 stream_put(s, &attr->mp_nexthop_local,
4998 IPV6_MAX_BYTELEN);
4999
5000 /* SNPA */
5001 stream_putc(s, 0);
5002
5003 /* Prefix */
5004 stream_put_prefix_addpath(s, prefix, addpath_capable,
5005 addpath_tx_id);
5006
5007 /* Set MP attribute length. */
5008 stream_putc_at(s, sizep, (stream_get_endp(s) - sizep) - 1);
5009 }
5010
5011 /* Prefix SID */
5012 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
5013 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
5014 stream_putc(s,
5015 BGP_ATTR_FLAG_OPTIONAL
5016 | BGP_ATTR_FLAG_TRANS);
5017 stream_putc(s, BGP_ATTR_PREFIX_SID);
5018 stream_putc(s, 10);
5019 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
5020 stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
5021 stream_putc(s, 0); // reserved
5022 stream_putw(s, 0); // flags
5023 stream_putl(s, attr->label_index);
5024 }
5025 }
5026
5027 /* OTC */
5028 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
5029 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
5030 stream_putc(s, BGP_ATTR_OTC);
5031 stream_putc(s, 4);
5032 stream_putl(s, attr->otc);
5033 }
5034
5035 /* AIGP */
5036 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
5037 /* At the moment only AIGP Metric TLV exists for AIGP
5038 * attribute. If more comes in, do not forget to update
5039 * attr_len variable to include new ones.
5040 */
5041 uint8_t attr_len = BGP_AIGP_TLV_METRIC_LEN;
5042
5043 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
5044 stream_putc(s, BGP_ATTR_AIGP);
5045 stream_putc(s, attr_len);
5046 stream_put_bgp_aigp_tlv_metric(s, bpi);
5047 }
5048
5049 /* Return total size of attribute. */
5050 len = stream_get_endp(s) - cp - 2;
5051 stream_putw_at(s, cp, len);
5052 }
5053
5054 void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
5055 const char *discard_attrs, bool set)
5056 {
5057 int i, num_attributes;
5058 char **attributes;
5059 afi_t afi;
5060 safi_t safi;
5061
5062
5063 /* If `no` command specified without arbitrary attributes,
5064 * then flush all.
5065 */
5066 if (!discard_attrs) {
5067 for (i = 0; i < BGP_ATTR_MAX; i++)
5068 peer->discard_attrs[i] = false;
5069 goto discard_soft_clear;
5070 }
5071
5072 if (discard_attrs) {
5073 frrstr_split(discard_attrs, " ", &attributes, &num_attributes);
5074
5075 if (set)
5076 for (i = 0; i < BGP_ATTR_MAX; i++)
5077 peer->discard_attrs[i] = false;
5078
5079 for (i = 0; i < num_attributes; i++) {
5080 uint8_t attr_num = strtoul(attributes[i], NULL, 10);
5081
5082 XFREE(MTYPE_TMP, attributes[i]);
5083
5084 /* Some of the attributes, just can't be ignored. */
5085 if (attr_num == BGP_ATTR_ORIGIN ||
5086 attr_num == BGP_ATTR_AS_PATH ||
5087 attr_num == BGP_ATTR_NEXT_HOP ||
5088 attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
5089 attr_num == BGP_ATTR_MP_REACH_NLRI ||
5090 attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
5091 attr_num == BGP_ATTR_EXT_COMMUNITIES) {
5092 vty_out(vty,
5093 "%% Can't discard path-attribute %s, ignoring.\n",
5094 lookup_msg(attr_str, attr_num, NULL));
5095 continue;
5096 }
5097
5098 /* Ignore local-pref, originator-id, cluster-list only
5099 * for eBGP.
5100 */
5101 if (peer->sort != BGP_PEER_EBGP &&
5102 (attr_num == BGP_ATTR_LOCAL_PREF ||
5103 attr_num == BGP_ATTR_ORIGINATOR_ID ||
5104 attr_num == BGP_ATTR_CLUSTER_LIST)) {
5105 vty_out(vty,
5106 "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
5107 lookup_msg(attr_str, attr_num, NULL));
5108 continue;
5109 }
5110
5111 peer->discard_attrs[attr_num] = set;
5112 }
5113 XFREE(MTYPE_TMP, attributes);
5114 discard_soft_clear:
5115 /* Configuring path attributes to be discarded will trigger
5116 * an inbound Route Refresh to ensure that the routing table
5117 * is up to date.
5118 */
5119 FOREACH_AFI_SAFI (afi, safi)
5120 peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
5121 }
5122 }
5123
5124 void bgp_path_attribute_withdraw_vty(struct vty *vty, struct peer *peer,
5125 const char *withdraw_attrs, bool set)
5126 {
5127 int i, num_attributes;
5128 char **attributes;
5129 afi_t afi;
5130 safi_t safi;
5131
5132 /* If `no` command specified without arbitrary attributes,
5133 * then flush all.
5134 */
5135 if (!withdraw_attrs) {
5136 for (i = 0; i < BGP_ATTR_MAX; i++)
5137 peer->withdraw_attrs[i] = false;
5138 goto withdraw_soft_clear;
5139 }
5140
5141 if (withdraw_attrs) {
5142 frrstr_split(withdraw_attrs, " ", &attributes, &num_attributes);
5143
5144 if (set)
5145 for (i = 0; i < BGP_ATTR_MAX; i++)
5146 peer->withdraw_attrs[i] = false;
5147
5148 for (i = 0; i < num_attributes; i++) {
5149 uint8_t attr_num = strtoul(attributes[i], NULL, 10);
5150
5151 XFREE(MTYPE_TMP, attributes[i]);
5152
5153 /* Some of the attributes, just can't be ignored. */
5154 if (attr_num == BGP_ATTR_ORIGIN ||
5155 attr_num == BGP_ATTR_AS_PATH ||
5156 attr_num == BGP_ATTR_NEXT_HOP ||
5157 attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
5158 attr_num == BGP_ATTR_MP_REACH_NLRI ||
5159 attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
5160 attr_num == BGP_ATTR_EXT_COMMUNITIES) {
5161 vty_out(vty,
5162 "%% Can't treat-as-withdraw path-attribute %s, ignoring.\n",
5163 lookup_msg(attr_str, attr_num, NULL));
5164 continue;
5165 }
5166
5167 /* Ignore local-pref, originator-id, cluster-list only
5168 * for eBGP.
5169 */
5170 if (peer->sort != BGP_PEER_EBGP &&
5171 (attr_num == BGP_ATTR_LOCAL_PREF ||
5172 attr_num == BGP_ATTR_ORIGINATOR_ID ||
5173 attr_num == BGP_ATTR_CLUSTER_LIST)) {
5174 vty_out(vty,
5175 "%% Can treat-as-withdraw path-attribute %s only for eBGP, ignoring.\n",
5176 lookup_msg(attr_str, attr_num, NULL));
5177 continue;
5178 }
5179
5180 peer->withdraw_attrs[attr_num] = set;
5181 }
5182 XFREE(MTYPE_TMP, attributes);
5183 withdraw_soft_clear:
5184 /* Configuring path attributes to be treated as withdraw will
5185 * trigger
5186 * an inbound Route Refresh to ensure that the routing table
5187 * is up to date.
5188 */
5189 FOREACH_AFI_SAFI (afi, safi)
5190 peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
5191 }
5192 }
5193
5194 enum bgp_attr_parse_ret bgp_attr_ignore(struct peer *peer, uint8_t type)
5195 {
5196 bool discard = peer->discard_attrs[type];
5197 bool withdraw = peer->withdraw_attrs[type];
5198
5199 if (bgp_debug_update(peer, NULL, NULL, 1) && (discard || withdraw))
5200 zlog_debug("%pBP: Ignoring attribute %s (%s)", peer,
5201 lookup_msg(attr_str, type, NULL),
5202 withdraw ? "treat-as-withdraw" : "discard");
5203
5204 return withdraw ? BGP_ATTR_PARSE_WITHDRAW : BGP_ATTR_PARSE_PROCEED;
5205 }