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