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