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