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