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