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