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