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