]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_attr.c
Merge pull request #718 from qlyoung/fix-vtysh-shit
[mirror_frr.git] / bgpd / bgp_attr.c
CommitLineData
718e3744 1/* BGP attributes management routines.
896014f4
DL
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 */
718e3744 20
21#include <zebra.h>
22
23#include "linklist.h"
24#include "prefix.h"
25#include "memory.h"
26#include "vector.h"
718e3744 27#include "stream.h"
28#include "log.h"
29#include "hash.h"
c8e7b895 30#include "jhash.h"
3f9c7369 31#include "queue.h"
f4c89855 32#include "table.h"
039f3a34 33#include "filter.h"
4dcadbef 34#include "command.h"
718e3744 35
36#include "bgpd/bgpd.h"
37#include "bgpd/bgp_attr.h"
38#include "bgpd/bgp_route.h"
39#include "bgpd/bgp_aspath.h"
40#include "bgpd/bgp_community.h"
41#include "bgpd/bgp_debug.h"
42#include "bgpd/bgp_packet.h"
43#include "bgpd/bgp_ecommunity.h"
57d187bc 44#include "bgpd/bgp_lcommunity.h"
3f9c7369 45#include "bgpd/bgp_updgrp.h"
6407da5a 46#include "bgpd/bgp_encap_types.h"
65efcfce 47#if ENABLE_BGP_VNC
f8b6f499 48# include "bgpd/rfapi/bgp_rfapi_cfg.h"
65efcfce
LB
49# include "bgp_encap_types.h"
50# include "bgp_vnc_types.h"
51#endif
b18825eb
PG
52#include "bgp_encap_types.h"
53#include "bgp_evpn.h"
6b0655a2 54
718e3744 55/* Attribute strings for logging. */
9bddac4b 56static const struct message attr_str [] =
718e3744 57{
58 { BGP_ATTR_ORIGIN, "ORIGIN" },
59 { BGP_ATTR_AS_PATH, "AS_PATH" },
60 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
61 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
62 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
63 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
64 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
65 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
66 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
f8627ff1 67 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
718e3744 68 { BGP_ATTR_DPA, "DPA" },
69 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
70 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
71 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
72 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
0b2aa3a0
PJ
73 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
74 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
75 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
76 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
f4c89855 77 { BGP_ATTR_ENCAP, "ENCAP" },
65efcfce
LB
78#if ENABLE_BGP_VNC
79 { BGP_ATTR_VNC, "VNC" },
80#endif
d39cdd93 81 { BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" },
c5a543b4 82 { BGP_ATTR_PREFIX_SID, "PREFIX_SID" }
718e3744 83};
837d16cc 84static const int attr_str_max = array_size(attr_str);
afcb7679
DO
85
86static const struct message attr_flag_str[] =
87{
88 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
89 { BGP_ATTR_FLAG_TRANS, "Transitive" },
90 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
91 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
92 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
93};
6b0655a2 94
9bddac4b 95static struct hash *cluster_hash;
718e3744 96
94f2b392 97static void *
923de654 98cluster_hash_alloc (void *p)
718e3744 99{
ffd0c037 100 const struct cluster_list *val = (const struct cluster_list *) p;
718e3744 101 struct cluster_list *cluster;
102
103 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
104 cluster->length = val->length;
105
106 if (cluster->length)
107 {
108 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
109 memcpy (cluster->list, val->list, val->length);
110 }
111 else
112 cluster->list = NULL;
113
114 cluster->refcnt = 0;
115
116 return cluster;
117}
118
119/* Cluster list related functions. */
94f2b392 120static struct cluster_list *
5228ad27 121cluster_parse (struct in_addr * pnt, int length)
718e3744 122{
123 struct cluster_list tmp;
124 struct cluster_list *cluster;
125
126 tmp.length = length;
5228ad27 127 tmp.list = pnt;
718e3744 128
129 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
130 cluster->refcnt++;
131 return cluster;
132}
133
134int
135cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
136{
137 int i;
138
139 for (i = 0; i < cluster->length / 4; i++)
140 if (cluster->list[i].s_addr == originator.s_addr)
141 return 1;
142 return 0;
143}
144
94f2b392 145static unsigned int
923de654 146cluster_hash_key_make (void *p)
718e3744 147{
c8e7b895 148 const struct cluster_list *cluster = p;
718e3744 149
c8e7b895 150 return jhash(cluster->list, cluster->length, 0);
718e3744 151}
152
94f2b392 153static int
ffe11cfb 154cluster_hash_cmp (const void *p1, const void *p2)
718e3744 155{
ffe11cfb
SH
156 const struct cluster_list * cluster1 = p1;
157 const struct cluster_list * cluster2 = p2;
923de654 158
ffe11cfb
SH
159 return (cluster1->length == cluster2->length &&
160 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
718e3744 161}
162
94f2b392 163static void
718e3744 164cluster_free (struct cluster_list *cluster)
165{
166 if (cluster->list)
167 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
168 XFREE (MTYPE_CLUSTER, cluster);
169}
170
94f2b392 171static struct cluster_list *
718e3744 172cluster_dup (struct cluster_list *cluster)
173{
174 struct cluster_list *new;
175
393deb9b 176 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
718e3744 177 new->length = cluster->length;
178
179 if (cluster->length)
180 {
181 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
182 memcpy (new->list, cluster->list, cluster->length);
183 }
184 else
185 new->list = NULL;
186
187 return new;
188}
189
94f2b392 190static struct cluster_list *
718e3744 191cluster_intern (struct cluster_list *cluster)
192{
193 struct cluster_list *find;
194
195 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
196 find->refcnt++;
197
198 return find;
199}
200
201void
202cluster_unintern (struct cluster_list *cluster)
203{
718e3744 204 if (cluster->refcnt)
205 cluster->refcnt--;
206
207 if (cluster->refcnt == 0)
208 {
9206f9ec 209 hash_release (cluster_hash, cluster);
718e3744 210 cluster_free (cluster);
211 }
212}
213
94f2b392 214static void
215cluster_init (void)
718e3744 216{
217 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
218}
228da428
CC
219
220static void
221cluster_finish (void)
222{
289d2501 223 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
228da428
CC
224 hash_free (cluster_hash);
225 cluster_hash = NULL;
226}
6b0655a2 227
bede7744
LB
228static struct hash *encap_hash = NULL;
229#if ENABLE_BGP_VNC
230static struct hash *vnc_hash = NULL;
231#endif
232
f4c89855
LB
233struct bgp_attr_encap_subtlv *
234encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
235{
236 struct bgp_attr_encap_subtlv *new;
237 struct bgp_attr_encap_subtlv *tail;
238 struct bgp_attr_encap_subtlv *p;
239
240 for (p = orig, tail = new = NULL; p; p = p->next) {
241 int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length;
242 if (tail) {
243 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
244 tail = tail->next;
245 } else {
246 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
247 }
248 assert(tail);
249 memcpy(tail, p, size);
250 tail->next = NULL;
251 }
252
253 return new;
254}
255
256static void
257encap_free(struct bgp_attr_encap_subtlv *p)
258{
259 struct bgp_attr_encap_subtlv *next;
260 while (p) {
261 next = p->next;
262 p->next = NULL;
263 XFREE(MTYPE_ENCAP_TLV, p);
264 p = next;
265 }
266}
267
268void
269bgp_attr_flush_encap(struct attr *attr)
270{
271 if (!attr || !attr->extra)
272 return;
273
274 if (attr->extra->encap_subtlvs) {
275 encap_free(attr->extra->encap_subtlvs);
276 attr->extra->encap_subtlvs = NULL;
277 }
65efcfce
LB
278#if ENABLE_BGP_VNC
279 if (attr->extra->vnc_subtlvs) {
280 encap_free(attr->extra->vnc_subtlvs);
281 attr->extra->vnc_subtlvs = NULL;
282 }
283#endif
f4c89855
LB
284}
285
286/*
287 * Compare encap sub-tlv chains
288 *
289 * 1 = equivalent
290 * 0 = not equivalent
291 *
292 * This algorithm could be made faster if needed
293 */
294static int
295encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
296{
297 struct bgp_attr_encap_subtlv *p;
298 struct bgp_attr_encap_subtlv *q;
299
f4c89855
LB
300 if (h1 == h2)
301 return 1;
bede7744
LB
302 if (h1 == NULL || h2 == NULL)
303 return 0;
f4c89855
LB
304
305 for (p = h1; p; p = p->next) {
306 for (q = h2; q; q = q->next) {
307 if ((p->type == q->type) &&
308 (p->length == q->length) &&
309 !memcmp(p->value, q->value, p->length)) {
310
311 break;
312 }
313 }
314 if (!q)
315 return 0;
316 }
317
318 for (p = h2; p; p = p->next) {
319 for (q = h1; q; q = q->next) {
320 if ((p->type == q->type) &&
321 (p->length == q->length) &&
322 !memcmp(p->value, q->value, p->length)) {
323
324 break;
325 }
326 }
327 if (!q)
328 return 0;
329 }
330
331 return 1;
332}
333
bede7744
LB
334static void *
335encap_hash_alloc (void *p)
336{
337 /* Encap structure is already allocated. */
338 return p;
339}
340
341typedef enum
342{
343 ENCAP_SUBTLV_TYPE,
344#if ENABLE_BGP_VNC
345 VNC_SUBTLV_TYPE
346#endif
347} encap_subtlv_type;
348
349static struct bgp_attr_encap_subtlv *
350encap_intern (struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type)
351{
352 struct bgp_attr_encap_subtlv *find;
353 struct hash *hash = encap_hash;
354#if ENABLE_BGP_VNC
355 if (type == VNC_SUBTLV_TYPE)
356 hash = vnc_hash;
357#endif
358
359 find = hash_get (hash, encap, encap_hash_alloc);
360 if (find != encap)
361 encap_free (encap);
362 find->refcnt++;
363
364 return find;
365}
366
367static void
368encap_unintern (struct bgp_attr_encap_subtlv **encapp, encap_subtlv_type type)
369{
370 struct bgp_attr_encap_subtlv *encap = *encapp;
371 if (encap->refcnt)
372 encap->refcnt--;
373
374 if (encap->refcnt == 0)
375 {
376 struct hash *hash = encap_hash;
377#if ENABLE_BGP_VNC
378 if (type == VNC_SUBTLV_TYPE)
379 hash = vnc_hash;
380#endif
381 hash_release (hash, encap);
382 encap_free (encap);
383 *encapp = NULL;
384 }
385}
386
387static unsigned int
388encap_hash_key_make (void *p)
389{
390 const struct bgp_attr_encap_subtlv * encap = p;
391
392 return jhash(encap->value, encap->length, 0);
393}
394
395static int
396encap_hash_cmp (const void *p1, const void *p2)
397{
398 return encap_same((struct bgp_attr_encap_subtlv *)p1,
399 (struct bgp_attr_encap_subtlv *)p2);
400}
401
402static void
403encap_init (void)
404{
405 encap_hash = hash_create (encap_hash_key_make, encap_hash_cmp);
406#if ENABLE_BGP_VNC
407 vnc_hash = hash_create (encap_hash_key_make, encap_hash_cmp);
408#endif
409}
410
411static void
412encap_finish (void)
413{
414 hash_clean (encap_hash, (void (*)(void *))encap_free);
415 hash_free (encap_hash);
416 encap_hash = NULL;
417#if ENABLE_BGP_VNC
418 hash_clean (vnc_hash, (void (*)(void *))encap_free);
419 hash_free (vnc_hash);
420 vnc_hash = NULL;
421#endif
422}
423
684a7227
PG
424static bool
425overlay_index_same(const struct attr_extra *ae1, const struct attr_extra *ae2)
426{
427 if(!ae1 && ae2)
428 return false;
429 if(!ae2 && ae1)
430 return false;
431 if(!ae1 && !ae2)
c298dae2 432 return true;
684a7227
PG
433 return !memcmp(&(ae1->evpn_overlay), &(ae2->evpn_overlay), sizeof(struct overlay_index));
434}
435
718e3744 436/* Unknown transit attribute. */
9bddac4b 437static struct hash *transit_hash;
718e3744 438
94f2b392 439static void
718e3744 440transit_free (struct transit *transit)
441{
442 if (transit->val)
443 XFREE (MTYPE_TRANSIT_VAL, transit->val);
444 XFREE (MTYPE_TRANSIT, transit);
445}
446
73ac8160
DS
447static struct transit *
448transit_dup (struct transit *transit)
449{
450 struct transit *new;
451
452 new = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
453 new->length = transit->length;
454 if (new->length)
455 {
456 new->val = XMALLOC (MTYPE_TRANSIT_VAL, transit->length);
457 memcpy (new->val, transit->val, transit->length);
458 }
459 else
460 new->val = NULL;
461
462 return new;
463}
923de654 464
94f2b392 465static void *
923de654 466transit_hash_alloc (void *p)
718e3744 467{
468 /* Transit structure is already allocated. */
923de654 469 return p;
718e3744 470}
471
94f2b392 472static struct transit *
718e3744 473transit_intern (struct transit *transit)
474{
475 struct transit *find;
476
477 find = hash_get (transit_hash, transit, transit_hash_alloc);
478 if (find != transit)
479 transit_free (transit);
480 find->refcnt++;
481
482 return find;
483}
484
485void
486transit_unintern (struct transit *transit)
487{
718e3744 488 if (transit->refcnt)
489 transit->refcnt--;
490
491 if (transit->refcnt == 0)
492 {
9206f9ec 493 hash_release (transit_hash, transit);
718e3744 494 transit_free (transit);
495 }
496}
497
94f2b392 498static unsigned int
923de654 499transit_hash_key_make (void *p)
718e3744 500{
c8e7b895 501 const struct transit * transit = p;
718e3744 502
c8e7b895 503 return jhash(transit->val, transit->length, 0);
718e3744 504}
505
94f2b392 506static int
ffe11cfb 507transit_hash_cmp (const void *p1, const void *p2)
718e3744 508{
ffe11cfb
SH
509 const struct transit * transit1 = p1;
510 const struct transit * transit2 = p2;
923de654 511
ffe11cfb
SH
512 return (transit1->length == transit2->length &&
513 memcmp (transit1->val, transit2->val, transit1->length) == 0);
718e3744 514}
515
94f2b392 516static void
66e5cd87 517transit_init (void)
718e3744 518{
519 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
520}
228da428
CC
521
522static void
523transit_finish (void)
524{
289d2501 525 hash_clean (transit_hash, (void (*)(void *))transit_free);
228da428
CC
526 hash_free (transit_hash);
527 transit_hash = NULL;
528}
6b0655a2 529
718e3744 530/* Attribute hash routines. */
9bddac4b 531static struct hash *attrhash;
718e3744 532
fb982c25
PJ
533static struct attr_extra *
534bgp_attr_extra_new (void)
535{
c5a543b4
DW
536 struct attr_extra *extra;
537 extra = XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
538 extra->label_index = BGP_INVALID_LABEL_INDEX;
539 return extra;
fb982c25
PJ
540}
541
542void
543bgp_attr_extra_free (struct attr *attr)
544{
545 if (attr->extra)
546 {
547 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
548 attr->extra = NULL;
549 }
550}
551
552struct attr_extra *
553bgp_attr_extra_get (struct attr *attr)
554{
555 if (!attr->extra)
556 attr->extra = bgp_attr_extra_new();
557 return attr->extra;
558}
559
560/* Shallow copy of an attribute
561 * Though, not so shallow that it doesn't copy the contents
562 * of the attr_extra pointed to by 'extra'
563 */
564void
565bgp_attr_dup (struct attr *new, struct attr *orig)
566{
558d1fec
JBD
567 struct attr_extra *extra = new->extra;
568
fb982c25 569 *new = *orig;
a0de1d16
CF
570 /* if caller provided attr_extra space, use it in any case.
571 *
572 * This is neccesary even if orig->extra equals NULL, because otherwise
573 * memory may be later allocated on the heap by bgp_attr_extra_get.
574 *
575 * That memory would eventually be leaked, because the caller must not
576 * call bgp_attr_extra_free if he provided attr_extra on the stack.
577 */
578 if (extra)
579 {
580 new->extra = extra;
581 memset(new->extra, 0, sizeof(struct attr_extra));
f4c89855 582 if (orig->extra) {
a0de1d16 583 *new->extra = *orig->extra;
f4c89855 584 }
a0de1d16
CF
585 }
586 else if (orig->extra)
fb982c25 587 {
a0de1d16 588 new->extra = bgp_attr_extra_new();
fb982c25
PJ
589 *new->extra = *orig->extra;
590 }
591}
592
73ac8160
DS
593void
594bgp_attr_deep_dup (struct attr *new, struct attr *orig)
595{
596 if (orig->aspath)
597 new->aspath = aspath_dup(orig->aspath);
598
599 if (orig->community)
600 new->community = community_dup(orig->community);
601
602 if (orig->extra)
603 {
604 if (orig->extra->ecommunity)
605 new->extra->ecommunity = ecommunity_dup(orig->extra->ecommunity);
606 if (orig->extra->cluster)
607 new->extra->cluster = cluster_dup(orig->extra->cluster);
608 if (orig->extra->transit)
609 new->extra->transit = transit_dup(orig->extra->transit);
bede7744
LB
610 if (orig->extra->encap_subtlvs)
611 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
612#if ENABLE_BGP_VNC
613 if (orig->extra->vnc_subtlvs)
614 new->extra->vnc_subtlvs = encap_tlv_dup(orig->extra->vnc_subtlvs);
615#endif
73ac8160
DS
616 }
617}
618
619void
620bgp_attr_deep_free (struct attr *attr)
621{
622 if (attr->aspath)
623 aspath_free(attr->aspath);
624
625 if (attr->community)
626 community_free(attr->community);
627
628 if (attr->extra)
629 {
630 if (attr->extra->ecommunity)
631 ecommunity_free(&attr->extra->ecommunity);
632 if (attr->extra->cluster)
633 cluster_free(attr->extra->cluster);
634 if (attr->extra->transit)
635 transit_free(attr->extra->transit);
bede7744
LB
636 if (attr->extra->encap_subtlvs)
637 encap_free(attr->extra->encap_subtlvs);
638#if ENABLE_BGP_VNC
639 if (attr->extra->vnc_subtlvs)
640 encap_free(attr->extra->vnc_subtlvs);
641#endif
73ac8160
DS
642 }
643}
644
cbdfbaa5
PJ
645unsigned long int
646attr_count (void)
647{
648 return attrhash->count;
649}
650
651unsigned long int
652attr_unknown_count (void)
653{
654 return transit_hash->count;
655}
656
718e3744 657unsigned int
923de654 658attrhash_key_make (void *p)
718e3744 659{
7fb0cd82
JBD
660 const struct attr *attr = (struct attr *) p;
661 const struct attr_extra *extra = attr->extra;
c8e7b895
SH
662 uint32_t key = 0;
663#define MIX(val) key = jhash_1word(val, key)
664
665 MIX(attr->origin);
666 MIX(attr->nexthop.s_addr);
667 MIX(attr->med);
668 MIX(attr->local_pref);
718e3744 669
c8f3fe30
PJ
670 key += attr->origin;
671 key += attr->nexthop.s_addr;
672 key += attr->med;
673 key += attr->local_pref;
fb982c25 674
7fb0cd82 675 if (extra)
fb982c25 676 {
7fb0cd82
JBD
677 MIX(extra->aggregator_as);
678 MIX(extra->aggregator_addr.s_addr);
679 MIX(extra->weight);
680 MIX(extra->mp_nexthop_global_in.s_addr);
689bb66c 681 MIX(extra->originator_id.s_addr);
0d9551dc 682 MIX(extra->tag);
6cf48acc 683 MIX(extra->label_index);
fb982c25
PJ
684 }
685
718e3744 686 if (attr->aspath)
c8e7b895 687 MIX(aspath_key_make (attr->aspath));
718e3744 688 if (attr->community)
c8e7b895 689 MIX(community_hash_make (attr->community));
fb982c25 690
7fb0cd82 691 if (extra)
fb982c25 692 {
57d187bc 693 if (extra->lcommunity)
2acb4ac2 694 MIX(lcommunity_hash_make (extra->lcommunity));
7fb0cd82
JBD
695 if (extra->ecommunity)
696 MIX(ecommunity_hash_make (extra->ecommunity));
697 if (extra->cluster)
698 MIX(cluster_hash_key_make (extra->cluster));
699 if (extra->transit)
700 MIX(transit_hash_key_make (extra->transit));
bede7744
LB
701 if (extra->encap_subtlvs)
702 MIX(encap_hash_key_make (extra->encap_subtlvs));
703#if ENABLE_BGP_VNC
704 if (extra->vnc_subtlvs)
705 MIX(encap_hash_key_make (extra->vnc_subtlvs));
706#endif
7fb0cd82 707 MIX(extra->mp_nexthop_len);
801a9bcc
DS
708 key = jhash(extra->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key);
709 key = jhash(extra->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key);
fb982c25 710 }
718e3744 711
712 return key;
713}
714
715int
ffe11cfb 716attrhash_cmp (const void *p1, const void *p2)
718e3744 717{
ffe11cfb
SH
718 const struct attr * attr1 = p1;
719 const struct attr * attr2 = p2;
923de654 720
718e3744 721 if (attr1->flag == attr2->flag
722 && attr1->origin == attr2->origin
723 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
fb982c25
PJ
724 && attr1->aspath == attr2->aspath
725 && attr1->community == attr2->community
718e3744 726 && attr1->med == attr2->med
3f9c7369
DS
727 && attr1->local_pref == attr2->local_pref
728 && attr1->rmap_change_flags == attr2->rmap_change_flags)
fb982c25 729 {
ffe11cfb
SH
730 const struct attr_extra *ae1 = attr1->extra;
731 const struct attr_extra *ae2 = attr2->extra;
fb982c25
PJ
732
733 if (ae1 && ae2
734 && ae1->aggregator_as == ae2->aggregator_as
735 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
736 && ae1->weight == ae2->weight
0d9551dc 737 && ae1->tag == ae2->tag
6cf48acc 738 && ae1->label_index == ae2->label_index
fb982c25
PJ
739 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
740 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
741 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
fb982c25
PJ
742 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
743 && ae1->ecommunity == ae2->ecommunity
57d187bc 744 && ae1->lcommunity == ae2->lcommunity
fb982c25 745 && ae1->cluster == ae2->cluster
689bb66c 746 && ae1->transit == ae2->transit
f4c89855
LB
747 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
748 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
65efcfce
LB
749#if ENABLE_BGP_VNC
750 && encap_same(ae1->vnc_subtlvs, ae2->vnc_subtlvs)
751#endif
684a7227
PG
752 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id)
753 && overlay_index_same(ae1, ae2))
fb982c25
PJ
754 return 1;
755 else if (ae1 || ae2)
756 return 0;
757 /* neither attribute has extra attributes, so they're same */
758 return 1;
759 }
718e3744 760 else
761 return 0;
762}
763
94f2b392 764static void
ffe11cfb 765attrhash_init (void)
718e3744 766{
767 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
768}
769
289d2501
LB
770/*
771 * special for hash_clean below
772 */
773static void
774attr_vfree (void *attr)
775{
776 bgp_attr_extra_free ((struct attr *)attr);
777 XFREE (MTYPE_ATTR, attr);
778}
779
228da428
CC
780static void
781attrhash_finish (void)
782{
289d2501 783 hash_clean(attrhash, attr_vfree);
228da428
CC
784 hash_free (attrhash);
785 attrhash = NULL;
786}
787
94f2b392 788static void
718e3744 789attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
790{
791 struct attr *attr = backet->data;
792
793 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
794 inet_ntoa (attr->nexthop), VTY_NEWLINE);
795}
796
797void
798attr_show_all (struct vty *vty)
799{
800 hash_iterate (attrhash,
801 (void (*)(struct hash_backet *, void *))
802 attr_show_all_iterator,
803 vty);
804}
805
94f2b392 806static void *
923de654 807bgp_attr_hash_alloc (void *p)
718e3744 808{
ffd0c037 809 const struct attr * val = (const struct attr *) p;
718e3744 810 struct attr *attr;
811
812 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
813 *attr = *val;
fb982c25
PJ
814 if (val->extra)
815 {
816 attr->extra = bgp_attr_extra_new ();
817 *attr->extra = *val->extra;
bede7744
LB
818 if (val->extra->encap_subtlvs) {
819 val->extra->encap_subtlvs = NULL;
f4c89855 820 }
65efcfce 821#if ENABLE_BGP_VNC
bede7744
LB
822 if (val->extra->vnc_subtlvs) {
823 val->extra->vnc_subtlvs = NULL;
65efcfce
LB
824 }
825#endif
fb982c25 826 }
718e3744 827 attr->refcnt = 0;
828 return attr;
829}
830
831/* Internet argument attribute. */
832struct attr *
833bgp_attr_intern (struct attr *attr)
834{
835 struct attr *find;
836
837 /* Intern referenced strucutre. */
838 if (attr->aspath)
839 {
840 if (! attr->aspath->refcnt)
841 attr->aspath = aspath_intern (attr->aspath);
842 else
843 attr->aspath->refcnt++;
844 }
845 if (attr->community)
846 {
847 if (! attr->community->refcnt)
848 attr->community = community_intern (attr->community);
849 else
850 attr->community->refcnt++;
851 }
fb982c25 852 if (attr->extra)
718e3744 853 {
fb982c25
PJ
854 struct attr_extra *attre = attr->extra;
855
856 if (attre->ecommunity)
857 {
858 if (! attre->ecommunity->refcnt)
859 attre->ecommunity = ecommunity_intern (attre->ecommunity);
860 else
861 attre->ecommunity->refcnt++;
f6f434b2 862
fb982c25 863 }
57d187bc
JS
864 if (attre->lcommunity)
865 {
866 if (! attre->lcommunity->refcnt)
867 attre->lcommunity = lcommunity_intern (attre->lcommunity);
868 else
869 attre->lcommunity->refcnt++;
870 }
fb982c25
PJ
871 if (attre->cluster)
872 {
873 if (! attre->cluster->refcnt)
874 attre->cluster = cluster_intern (attre->cluster);
875 else
876 attre->cluster->refcnt++;
877 }
878 if (attre->transit)
879 {
880 if (! attre->transit->refcnt)
881 attre->transit = transit_intern (attre->transit);
882 else
883 attre->transit->refcnt++;
884 }
bede7744
LB
885 if (attre->encap_subtlvs)
886 {
887 if (! attre->encap_subtlvs->refcnt)
888 attre->encap_subtlvs = encap_intern (attre->encap_subtlvs, ENCAP_SUBTLV_TYPE);
889 else
890 attre->encap_subtlvs->refcnt++;
891 }
892#if ENABLE_BGP_VNC
893 if (attre->vnc_subtlvs)
894 {
895 if (! attre->vnc_subtlvs->refcnt)
896 attre->vnc_subtlvs = encap_intern (attre->vnc_subtlvs, VNC_SUBTLV_TYPE);
897 else
898 attre->vnc_subtlvs->refcnt++;
899 }
900#endif
718e3744 901 }
f6f434b2 902
718e3744 903 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
904 find->refcnt++;
bede7744 905
718e3744 906 return find;
907}
908
3f9c7369
DS
909/**
910 * Increment the refcount on various structures that attr holds.
911 * Note on usage: call _only_ when the 'attr' object has already
912 * been 'intern'ed and exists in 'attrhash' table. The function
913 * serves to hold a reference to that (real) object.
914 * Note also that the caller can safely call bgp_attr_unintern()
915 * after calling bgp_attr_refcount(). That would release the
916 * reference and could result in a free() of the attr object.
917 */
918struct attr *
919bgp_attr_refcount (struct attr *attr)
920{
921 /* Intern referenced strucutre. */
922 if (attr->aspath)
923 attr->aspath->refcnt++;
924
925 if (attr->community)
926 attr->community->refcnt++;
927
928 if (attr->extra)
929 {
930 struct attr_extra *attre = attr->extra;
931 if (attre->ecommunity)
932 attre->ecommunity->refcnt++;
933
934 if (attre->cluster)
935 attre->cluster->refcnt++;
936
937 if (attre->transit)
938 attre->transit->refcnt++;
bede7744
LB
939
940 if (attre->encap_subtlvs)
941 attre->encap_subtlvs->refcnt++;
942
943#if ENABLE_BGP_VNC
944 if (attre->vnc_subtlvs)
945 attre->vnc_subtlvs->refcnt++;
946#endif
3f9c7369
DS
947 }
948 attr->refcnt++;
949 return attr;
950}
03e214c8 951
718e3744 952/* Make network statement's attribute. */
953struct attr *
954bgp_attr_default_set (struct attr *attr, u_char origin)
955{
956 memset (attr, 0, sizeof (struct attr));
fb982c25
PJ
957 bgp_attr_extra_get (attr);
958
718e3744 959 attr->origin = origin;
960 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
961 attr->aspath = aspath_empty ();
962 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
fb982c25 963 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
0d9551dc 964 attr->extra->tag = 0;
718e3744 965 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
fb982c25 966 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
03e214c8 967
718e3744 968 return attr;
969}
970
b5d58c32 971/* Create the attributes for an aggregate */
718e3744 972struct attr *
973bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
974 struct aspath *aspath,
42f7e184
DS
975 struct community *community, int as_set,
976 u_char atomic_aggregate)
718e3744 977{
978 struct attr attr;
979 struct attr *new;
938ef3a2 980 struct attr_extra attre;
718e3744 981
982 memset (&attr, 0, sizeof (struct attr));
938ef3a2
JBD
983 memset (&attre, 0, sizeof (struct attr_extra));
984 attr.extra = &attre;
985
718e3744 986 /* Origin attribute. */
987 attr.origin = origin;
988 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
989
990 /* AS path attribute. */
991 if (aspath)
992 attr.aspath = aspath_intern (aspath);
993 else
994 attr.aspath = aspath_empty ();
995 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
996
997 /* Next hop attribute. */
998 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
999
1000 if (community)
1001 {
1002 attr.community = community;
1003 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1004 }
1005
938ef3a2 1006 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
938ef3a2 1007 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
42f7e184 1008 if (! as_set || atomic_aggregate)
718e3744 1009 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1010 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1011 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
938ef3a2 1012 attre.aggregator_as = bgp->confed_id;
718e3744 1013 else
938ef3a2
JBD
1014 attre.aggregator_as = bgp->as;
1015 attre.aggregator_addr = bgp->router_id;
718e3744 1016
1017 new = bgp_attr_intern (&attr);
938ef3a2 1018
f6f434b2 1019 aspath_unintern (&new->aspath);
718e3744 1020 return new;
1021}
1022
b881c707
PJ
1023/* Unintern just the sub-components of the attr, but not the attr */
1024void
1025bgp_attr_unintern_sub (struct attr *attr)
1026{
1027 /* aspath refcount shoud be decrement. */
1028 if (attr->aspath)
1029 aspath_unintern (&attr->aspath);
d92a2f39 1030 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
b881c707
PJ
1031
1032 if (attr->community)
1033 community_unintern (&attr->community);
d92a2f39 1034 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
b881c707
PJ
1035
1036 if (attr->extra)
1037 {
1038 if (attr->extra->ecommunity)
1039 ecommunity_unintern (&attr->extra->ecommunity);
d92a2f39 1040 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
57d187bc
JS
1041
1042 if (attr->extra->lcommunity)
1043 lcommunity_unintern (&attr->extra->lcommunity);
1044 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
2acb4ac2 1045
b881c707
PJ
1046 if (attr->extra->cluster)
1047 cluster_unintern (attr->extra->cluster);
d92a2f39 1048 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
b881c707
PJ
1049
1050 if (attr->extra->transit)
1051 transit_unintern (attr->extra->transit);
bede7744
LB
1052
1053 if (attr->extra->encap_subtlvs)
1054 encap_unintern (&attr->extra->encap_subtlvs, ENCAP_SUBTLV_TYPE);
1055
1056#if ENABLE_BGP_VNC
1057 if (attr->extra->vnc_subtlvs)
1058 encap_unintern (&attr->extra->vnc_subtlvs, VNC_SUBTLV_TYPE);
1059#endif
b881c707
PJ
1060 }
1061}
1062
718e3744 1063/* Free bgp attribute and aspath. */
1064void
1a2fd707 1065bgp_attr_unintern (struct attr **pattr)
718e3744 1066{
1a2fd707 1067 struct attr *attr = *pattr;
718e3744 1068 struct attr *ret;
b881c707 1069 struct attr tmp;
b9f1dca1 1070 struct attr_extra tmp_extra;
f6f434b2 1071
718e3744 1072 /* Decrement attribute reference. */
1a2fd707 1073 attr->refcnt--;
b881c707 1074
1a2fd707 1075 tmp = *attr;
b881c707 1076
1a2fd707 1077 if (attr->extra)
fb982c25 1078 {
b9f1dca1 1079 tmp.extra = &tmp_extra;
1a2fd707 1080 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
fb982c25 1081 }
f6f434b2 1082
718e3744 1083 /* If reference becomes zero then free attribute object. */
1a2fd707
JBD
1084 if (attr->refcnt == 0)
1085 {
1086 ret = hash_release (attrhash, attr);
718e3744 1087 assert (ret != NULL);
1a2fd707
JBD
1088 bgp_attr_extra_free (attr);
1089 XFREE (MTYPE_ATTR, attr);
1090 *pattr = NULL;
718e3744 1091 }
1092
b881c707 1093 bgp_attr_unintern_sub (&tmp);
718e3744 1094}
1095
1096void
1097bgp_attr_flush (struct attr *attr)
1098{
1099 if (attr->aspath && ! attr->aspath->refcnt)
f9a3a260
LB
1100 {
1101 aspath_free (attr->aspath);
1102 attr->aspath = NULL;
1103 }
718e3744 1104 if (attr->community && ! attr->community->refcnt)
f9a3a260
LB
1105 {
1106 community_free (attr->community);
1107 attr->community = NULL;
1108 }
fb982c25
PJ
1109 if (attr->extra)
1110 {
1111 struct attr_extra *attre = attr->extra;
f6f434b2 1112
fb982c25 1113 if (attre->ecommunity && ! attre->ecommunity->refcnt)
f6f434b2 1114 ecommunity_free (&attre->ecommunity);
57d187bc 1115 if (attre->lcommunity && ! attre->lcommunity->refcnt)
2acb4ac2 1116 lcommunity_free (&attre->lcommunity);
fb982c25 1117 if (attre->cluster && ! attre->cluster->refcnt)
f9a3a260
LB
1118 {
1119 cluster_free (attre->cluster);
1120 attre->cluster = NULL;
1121 }
fb982c25 1122 if (attre->transit && ! attre->transit->refcnt)
f9a3a260
LB
1123 {
1124 transit_free (attre->transit);
1125 attre->transit = NULL;
1126 }
bede7744
LB
1127 if (attre->encap_subtlvs && ! attre->encap_subtlvs->refcnt)
1128 {
1129 encap_free(attre->encap_subtlvs);
1130 attre->encap_subtlvs = NULL;
1131 }
65efcfce 1132#if ENABLE_BGP_VNC
bede7744
LB
1133 if (attre->vnc_subtlvs && ! attre->vnc_subtlvs->refcnt)
1134 {
1135 encap_free(attre->vnc_subtlvs);
1136 attre->vnc_subtlvs = NULL;
1137 }
65efcfce 1138#endif
fb982c25 1139 }
718e3744 1140}
1141
b881c707
PJ
1142/* Implement draft-scudder-idr-optional-transitive behaviour and
1143 * avoid resetting sessions for malformed attributes which are
1144 * are partial/optional and hence where the error likely was not
1145 * introduced by the sending neighbour.
1146 */
1147static bgp_attr_parse_ret_t
835315bf
PJ
1148bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
1149 bgp_size_t length)
b881c707 1150{
835315bf
PJ
1151 struct peer *const peer = args->peer;
1152 const u_int8_t flags = args->flags;
1153 /* startp and length must be special-cased, as whether or not to
1154 * send the attribute data with the NOTIFY depends on the error,
1155 * the caller therefore signals this with the seperate length argument
1156 */
bd471fea 1157 u_char *notify_datap = (length > 0 ? args->startp : NULL);
835315bf 1158
b881c707 1159 /* Only relax error handling for eBGP peers */
6d85b15b 1160 if (peer->sort != BGP_PEER_EBGP)
b881c707
PJ
1161 {
1162 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
bd471fea 1163 notify_datap, length);
b881c707
PJ
1164 return BGP_ATTR_PARSE_ERROR;
1165
1166 }
1167
bd471fea
PJ
1168 /* Adjust the stream getp to the end of the attribute, in case we can
1169 * still proceed but the caller hasn't read all the attribute.
1170 */
1171 stream_set_getp (BGP_INPUT (peer),
1172 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
1173 + args->total);
1174
835315bf 1175 switch (args->type) {
fa61e16d
PJ
1176 /* where an attribute is relatively inconsequential, e.g. it does not
1177 * affect route selection, and can be safely ignored, then any such
1178 * attributes which are malformed should just be ignored and the route
1179 * processed as normal.
b881c707
PJ
1180 */
1181 case BGP_ATTR_AS4_AGGREGATOR:
1182 case BGP_ATTR_AGGREGATOR:
1183 case BGP_ATTR_ATOMIC_AGGREGATE:
1184 return BGP_ATTR_PARSE_PROCEED;
1185
1186 /* Core attributes, particularly ones which may influence route
fa61e16d 1187 * selection, should always cause session resets
b881c707
PJ
1188 */
1189 case BGP_ATTR_ORIGIN:
1190 case BGP_ATTR_AS_PATH:
1191 case BGP_ATTR_NEXT_HOP:
1192 case BGP_ATTR_MULTI_EXIT_DISC:
1193 case BGP_ATTR_LOCAL_PREF:
1194 case BGP_ATTR_COMMUNITIES:
1195 case BGP_ATTR_ORIGINATOR_ID:
1196 case BGP_ATTR_CLUSTER_LIST:
1197 case BGP_ATTR_MP_REACH_NLRI:
1198 case BGP_ATTR_MP_UNREACH_NLRI:
1199 case BGP_ATTR_EXT_COMMUNITIES:
1200 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
bd471fea 1201 notify_datap, length);
b881c707
PJ
1202 return BGP_ATTR_PARSE_ERROR;
1203 }
1204
1205 /* Partial optional attributes that are malformed should not cause
1206 * the whole session to be reset. Instead treat it as a withdrawal
1207 * of the routes, if possible.
1208 */
835315bf
PJ
1209 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
1210 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1211 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
b881c707
PJ
1212 return BGP_ATTR_PARSE_WITHDRAW;
1213
1214 /* default to reset */
f57000c0 1215 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
b881c707
PJ
1216}
1217
afcb7679
DO
1218/* Find out what is wrong with the path attribute flag bits and log the error.
1219 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1220 Extended Length. Checking O/T/P bits at once implies, that the attribute
1221 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1222 non-transitive" attribute. */
1223static void
835315bf
PJ
1224bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
1225 u_int8_t desired_flags /* how RFC says it must be */
afcb7679
DO
1226)
1227{
1228 u_char seen = 0, i;
835315bf
PJ
1229 u_char real_flags = args->flags;
1230 const u_int8_t attr_code = args->type;
1231
afcb7679
DO
1232 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1233 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1234 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
1235 if
1236 (
1237 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
1238 CHECK_FLAG (real_flags, attr_flag_str[i].key)
1239 )
1240 {
16286195
DS
1241 zlog_err ("%s attribute must%s be flagged as \"%s\"",
1242 LOOKUP (attr_str, attr_code),
1243 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
1244 attr_flag_str[i].str);
afcb7679
DO
1245 seen = 1;
1246 }
fa5831e8
PJ
1247 if (!seen)
1248 {
16286195
DS
1249 zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
1250 " (real flags 0x%x, desired 0x%x)",
1251 __func__, LOOKUP (attr_str, attr_code),
1252 real_flags, desired_flags);
fa5831e8 1253 }
afcb7679
DO
1254}
1255
3ecab4c8
PJ
1256/* Required flags for attributes. EXTLEN will be masked off when testing,
1257 * as will PARTIAL for optional+transitive attributes.
1258 */
1259const u_int8_t attr_flags_values [] = {
1260 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
1261 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
1262 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
1263 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
1264 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
1265 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
1266 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1267 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1268 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
1269 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1270 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1271 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1272 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1273 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1274 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
2acb4ac2 1275 [BGP_ATTR_LARGE_COMMUNITIES]= BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
c5a543b4 1276 [BGP_ATTR_PREFIX_SID] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
3ecab4c8 1277};
099111ef 1278static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
3ecab4c8
PJ
1279
1280static int
835315bf 1281bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
3ecab4c8
PJ
1282{
1283 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
835315bf
PJ
1284 const u_int8_t flags = args->flags;
1285 const u_int8_t attr_code = args->type;
3ecab4c8
PJ
1286
1287 /* there may be attributes we don't know about */
1288 if (attr_code > attr_flags_values_max)
1289 return 0;
1290 if (attr_flags_values[attr_code] == 0)
1291 return 0;
1292
1293 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1294 * 1."
1295 */
1296 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1297 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1298 {
16286195
DS
1299 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
1300 LOOKUP (attr_str, attr_code), flags);
3ecab4c8
PJ
1301 return 1;
1302 }
1303
1304 /* "For well-known attributes and for optional non-transitive attributes,
1305 * the Partial bit MUST be set to 0."
1306 */
1307 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1308 {
1309 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1310 {
16286195
DS
1311 zlog_err ("%s well-known attribute "
1312 "must NOT have the partial flag set (%x)",
1313 LOOKUP (attr_str, attr_code), flags);
3ecab4c8
PJ
1314 return 1;
1315 }
1316 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1317 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1318 {
16286195
DS
1319 zlog_err ("%s optional + transitive attribute "
1320 "must NOT have the partial flag set (%x)",
1321 LOOKUP (attr_str, attr_code), flags);
3ecab4c8
PJ
1322 return 1;
1323 }
1324 }
1325
1326 /* Optional transitive attributes may go through speakers that don't
1327 * reocgnise them and set the Partial bit.
1328 */
1329 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1330 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1331 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1332
683f2b86 1333 if ((flags & ~mask)
3ecab4c8
PJ
1334 == attr_flags_values[attr_code])
1335 return 0;
1336
835315bf 1337 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
3ecab4c8
PJ
1338 return 1;
1339}
1340
718e3744 1341/* Get origin attribute of the update message. */
b881c707 1342static bgp_attr_parse_ret_t
835315bf 1343bgp_attr_origin (struct bgp_attr_parser_args *args)
718e3744 1344{
835315bf
PJ
1345 struct peer *const peer = args->peer;
1346 struct attr *const attr = args->attr;
1347 const bgp_size_t length = args->length;
1348
718e3744 1349 /* If any recognized attribute has Attribute Length that conflicts
1350 with the expected length (based on the attribute type code), then
1351 the Error Subcode is set to Attribute Length Error. The Data
1352 field contains the erroneous attribute (type, length and
1353 value). */
1354 if (length != 1)
1355 {
16286195 1356 zlog_err ("Origin attribute length is not one %d", length);
835315bf 1357 return bgp_attr_malformed (args,
b881c707 1358 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1359 args->total);
718e3744 1360 }
1361
1362 /* Fetch origin attribute. */
1363 attr->origin = stream_getc (BGP_INPUT (peer));
1364
1365 /* If the ORIGIN attribute has an undefined value, then the Error
1366 Subcode is set to Invalid Origin Attribute. The Data field
1367 contains the unrecognized attribute (type, length and value). */
1368 if ((attr->origin != BGP_ORIGIN_IGP)
1369 && (attr->origin != BGP_ORIGIN_EGP)
1370 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1371 {
16286195 1372 zlog_err ("Origin attribute value is invalid %d", attr->origin);
835315bf 1373 return bgp_attr_malformed (args,
b881c707 1374 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
835315bf 1375 args->total);
718e3744 1376 }
1377
1378 /* Set oring attribute flag. */
1379 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1380
1381 return 0;
1382}
ab005298
PJ
1383
1384/* Parse AS path information. This function is wrapper of
1385 aspath_parse. */
1386static int
835315bf 1387bgp_attr_aspath (struct bgp_attr_parser_args *args)
718e3744 1388{
835315bf
PJ
1389 struct attr *const attr = args->attr;
1390 struct peer *const peer = args->peer;
1391 const bgp_size_t length = args->length;
3ecab4c8 1392
ab005298
PJ
1393 /*
1394 * peer with AS4 => will get 4Byte ASnums
1395 * otherwise, will get 16 Bit
0b2aa3a0 1396 */
ab005298
PJ
1397 attr->aspath = aspath_parse (peer->ibuf, length,
1398 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
0b2aa3a0 1399
ab005298
PJ
1400 /* In case of IBGP, length will be zero. */
1401 if (! attr->aspath)
cddb8112 1402 {
16286195 1403 zlog_err ("Malformed AS path from %s, length is %d", peer->host, length);
835315bf 1404 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
cddb8112 1405 }
cddb8112 1406
ab005298
PJ
1407 /* Set aspath attribute flag. */
1408 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
0b2aa3a0 1409
b881c707 1410 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1411}
1412
b881c707 1413static bgp_attr_parse_ret_t
835315bf 1414bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
0b2aa3a0
PJ
1415{
1416 /* These checks were part of bgp_attr_aspath, but with
1417 * as4 we should to check aspath things when
1418 * aspath synthesizing with as4_path has already taken place.
1419 * Otherwise we check ASPATH and use the synthesized thing, and that is
1420 * not right.
1421 * So do the checks later, i.e. here
1422 */
1423 struct bgp *bgp = peer->bgp;
1424 struct aspath *aspath;
1425
ca87e1d3 1426 /* Confederation sanity check. */
6d85b15b
JBD
1427 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1428 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
ca87e1d3 1429 {
16286195 1430 zlog_err ("Malformed AS path from %s", peer->host);
835315bf
PJ
1431 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1432 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1433 return BGP_ATTR_PARSE_ERROR;
ca87e1d3
VT
1434 }
1435
718e3744 1436 /* First AS check for EBGP. */
1437 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1438 {
6d85b15b 1439 if (peer->sort == BGP_PEER_EBGP
718e3744 1440 && ! aspath_firstas_check (attr->aspath, peer->as))
1441 {
16286195 1442 zlog_err ("%s incorrect first AS (must be %u)", peer->host, peer->as);
835315bf
PJ
1443 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1444 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1445 return BGP_ATTR_PARSE_ERROR;
718e3744 1446 }
1447 }
1448
1449 /* local-as prepend */
1450 if (peer->change_local_as &&
1451 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1452 {
1453 aspath = aspath_dup (attr->aspath);
1454 aspath = aspath_add_seq (aspath, peer->change_local_as);
f6f434b2 1455 aspath_unintern (&attr->aspath);
718e3744 1456 attr->aspath = aspath_intern (aspath);
1457 }
1458
b881c707 1459 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1460}
1461
ab005298
PJ
1462/* Parse AS4 path information. This function is another wrapper of
1463 aspath_parse. */
1464static int
835315bf 1465bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
ab005298 1466{
835315bf
PJ
1467 struct peer *const peer = args->peer;
1468 struct attr *const attr = args->attr;
1469 const bgp_size_t length = args->length;
3ecab4c8 1470
ab005298
PJ
1471 *as4_path = aspath_parse (peer->ibuf, length, 1);
1472
b881c707
PJ
1473 /* In case of IBGP, length will be zero. */
1474 if (!*as4_path)
1475 {
16286195 1476 zlog_err ("Malformed AS4 path from %s, length is %d", peer->host, length);
835315bf 1477 return bgp_attr_malformed (args,
b881c707 1478 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
835315bf 1479 0);
b881c707
PJ
1480 }
1481
ab005298 1482 /* Set aspath attribute flag. */
46c3ce83 1483 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
ab005298 1484
b881c707 1485 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1486}
1487
718e3744 1488/* Nexthop attribute. */
b881c707 1489static bgp_attr_parse_ret_t
835315bf 1490bgp_attr_nexthop (struct bgp_attr_parser_args *args)
718e3744 1491{
835315bf
PJ
1492 struct peer *const peer = args->peer;
1493 struct attr *const attr = args->attr;
1494 const bgp_size_t length = args->length;
1495
bc3443eb 1496 in_addr_t nexthop_h, nexthop_n;
718e3744 1497
718e3744 1498 /* Check nexthop attribute length. */
1499 if (length != 4)
1500 {
16286195 1501 zlog_err ("Nexthop attribute length isn't four [%d]", length);
718e3744 1502
835315bf 1503 return bgp_attr_malformed (args,
b881c707 1504 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1505 args->total);
718e3744 1506 }
1507
58298ccd
DS
1508 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1509 attribute must result in a NOTIFICATION message (this is implemented below).
1510 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1511 logged locally (this is implemented somewhere else). The UPDATE message
1512 gets ignored in any of these cases. */
bc3443eb
DO
1513 nexthop_n = stream_get_ipv4 (peer->ibuf);
1514 nexthop_h = ntohl (nexthop_n);
cebb7440
LB
1515 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1516 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
bc3443eb
DO
1517 {
1518 char buf[INET_ADDRSTRLEN];
bb02b823 1519 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
16286195 1520 zlog_err ("Martian nexthop %s", buf);
835315bf 1521 return bgp_attr_malformed (args,
bc3443eb 1522 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
835315bf 1523 args->total);
bc3443eb
DO
1524 }
1525
1526 attr->nexthop.s_addr = nexthop_n;
718e3744 1527 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1528
b881c707 1529 return BGP_ATTR_PARSE_PROCEED;
718e3744 1530}
1531
1532/* MED atrribute. */
b881c707 1533static bgp_attr_parse_ret_t
835315bf 1534bgp_attr_med (struct bgp_attr_parser_args *args)
718e3744 1535{
835315bf
PJ
1536 struct peer *const peer = args->peer;
1537 struct attr *const attr = args->attr;
1538 const bgp_size_t length = args->length;
1539
718e3744 1540 /* Length check. */
1541 if (length != 4)
1542 {
16286195 1543 zlog_err ("MED attribute length isn't four [%d]", length);
b881c707 1544
835315bf 1545 return bgp_attr_malformed (args,
b881c707 1546 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1547 args->total);
718e3744 1548 }
1549
1550 attr->med = stream_getl (peer->ibuf);
1551
1552 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1553
b881c707 1554 return BGP_ATTR_PARSE_PROCEED;
718e3744 1555}
1556
1557/* Local preference attribute. */
b881c707 1558static bgp_attr_parse_ret_t
835315bf 1559bgp_attr_local_pref (struct bgp_attr_parser_args *args)
718e3744 1560{
835315bf
PJ
1561 struct peer *const peer = args->peer;
1562 struct attr *const attr = args->attr;
1563 const bgp_size_t length = args->length;
3ecab4c8 1564
a624cae2
DO
1565 /* Length check. */
1566 if (length != 4)
1567 {
16286195 1568 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length);
835315bf 1569 return bgp_attr_malformed (args,
a624cae2 1570 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1571 args->total);
a624cae2 1572 }
0ea968d2 1573
718e3744 1574 /* If it is contained in an UPDATE message that is received from an
1575 external peer, then this attribute MUST be ignored by the
1576 receiving speaker. */
6d85b15b 1577 if (peer->sort == BGP_PEER_EBGP)
718e3744 1578 {
9985f83c 1579 stream_forward_getp (peer->ibuf, length);
b881c707 1580 return BGP_ATTR_PARSE_PROCEED;
718e3744 1581 }
1582
a624cae2 1583 attr->local_pref = stream_getl (peer->ibuf);
718e3744 1584
1585 /* Set atomic aggregate flag. */
1586 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1587
b881c707 1588 return BGP_ATTR_PARSE_PROCEED;
718e3744 1589}
1590
1591/* Atomic aggregate. */
94f2b392 1592static int
835315bf 1593bgp_attr_atomic (struct bgp_attr_parser_args *args)
718e3744 1594{
835315bf
PJ
1595 struct attr *const attr = args->attr;
1596 const bgp_size_t length = args->length;
3ecab4c8 1597
9eba2ada 1598 /* Length check. */
718e3744 1599 if (length != 0)
1600 {
16286195 1601 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length);
835315bf 1602 return bgp_attr_malformed (args,
b881c707 1603 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1604 args->total);
718e3744 1605 }
1606
1607 /* Set atomic aggregate flag. */
1608 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1609
b881c707 1610 return BGP_ATTR_PARSE_PROCEED;
718e3744 1611}
1612
1613/* Aggregator attribute */
94f2b392 1614static int
835315bf 1615bgp_attr_aggregator (struct bgp_attr_parser_args *args)
718e3744 1616{
835315bf
PJ
1617 struct peer *const peer = args->peer;
1618 struct attr *const attr = args->attr;
1619 const bgp_size_t length = args->length;
1620
0b2aa3a0 1621 int wantedlen = 6;
fb982c25 1622 struct attr_extra *attre = bgp_attr_extra_get (attr);
3ecab4c8 1623
0b2aa3a0 1624 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
b881c707 1625 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
0b2aa3a0
PJ
1626 wantedlen = 8;
1627
1628 if (length != wantedlen)
718e3744 1629 {
16286195 1630 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen, length);
835315bf 1631 return bgp_attr_malformed (args,
b881c707 1632 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1633 args->total);
718e3744 1634 }
0b2aa3a0
PJ
1635
1636 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1637 attre->aggregator_as = stream_getl (peer->ibuf);
1638 else
1639 attre->aggregator_as = stream_getw (peer->ibuf);
fb982c25 1640 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
718e3744 1641
1642 /* Set atomic aggregate flag. */
1643 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1644
b881c707 1645 return BGP_ATTR_PARSE_PROCEED;
718e3744 1646}
1647
0b2aa3a0 1648/* New Aggregator attribute */
b881c707 1649static bgp_attr_parse_ret_t
835315bf
PJ
1650bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1651 as_t *as4_aggregator_as,
1652 struct in_addr *as4_aggregator_addr)
0b2aa3a0 1653{
835315bf
PJ
1654 struct peer *const peer = args->peer;
1655 struct attr *const attr = args->attr;
1656 const bgp_size_t length = args->length;
1657
0b2aa3a0
PJ
1658 if (length != 8)
1659 {
16286195 1660 zlog_err ("New Aggregator length is not 8 [%d]", length);
835315bf 1661 return bgp_attr_malformed (args,
b881c707 1662 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1663 0);
0b2aa3a0 1664 }
3ecab4c8 1665
0b2aa3a0
PJ
1666 *as4_aggregator_as = stream_getl (peer->ibuf);
1667 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1668
1669 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1670
b881c707 1671 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1672}
1673
1674/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1675 */
b881c707 1676static bgp_attr_parse_ret_t
835315bf
PJ
1677bgp_attr_munge_as4_attrs (struct peer *const peer,
1678 struct attr *const attr,
0b2aa3a0
PJ
1679 struct aspath *as4_path, as_t as4_aggregator,
1680 struct in_addr *as4_aggregator_addr)
1681{
1682 int ignore_as4_path = 0;
1683 struct aspath *newpath;
1684 struct attr_extra *attre = attr->extra;
bb7bef14
PJ
1685
1686 if (!attr->aspath)
1687 {
1688 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1689 * checked that all well-known, mandatory attributes were present.
1690 *
1691 * Can only be a problem with peer itself - hard error
1692 */
1693 return BGP_ATTR_PARSE_ERROR;
1694 }
1695
b881c707 1696 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
0b2aa3a0
PJ
1697 {
1698 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1699 * if given.
1700 * It is worth a warning though, because the peer really
1701 * should not send them
1702 */
1703 if (BGP_DEBUG(as4, AS4))
1704 {
1705 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1706 zlog_debug ("[AS4] %s %s AS4_PATH",
1707 peer->host, "AS4 capable peer, yet it sent");
1708
1709 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1710 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1711 peer->host, "AS4 capable peer, yet it sent");
1712 }
1713
b881c707 1714 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1715 }
1716
0b2aa3a0
PJ
1717 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1718 * because that may override AS4_PATH
1719 */
1720 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1721 {
b881c707 1722 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
0b2aa3a0 1723 {
370b64a2
PJ
1724 assert (attre);
1725
0b2aa3a0
PJ
1726 /* received both.
1727 * if the as_number in aggregator is not AS_TRANS,
1728 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1729 * and the Aggregator shall be taken as
1730 * info on the aggregating node, and the AS_PATH
1731 * shall be taken as the AS_PATH
1732 * otherwise
1733 * the Aggregator shall be ignored and the
1734 * AS4_AGGREGATOR shall be taken as the
1735 * Aggregating node and the AS_PATH is to be
1736 * constructed "as in all other cases"
1737 */
b881c707 1738 if (attre->aggregator_as != BGP_AS_TRANS)
0b2aa3a0
PJ
1739 {
1740 /* ignore */
1741 if ( BGP_DEBUG(as4, AS4))
1742 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1743 " send AGGREGATOR != AS_TRANS and"
1744 " AS4_AGGREGATOR, so ignore"
1745 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1746 ignore_as4_path = 1;
1747 }
1748 else
1749 {
1750 /* "New_aggregator shall be taken as aggregator" */
1751 attre->aggregator_as = as4_aggregator;
1752 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1753 }
1754 }
1755 else
1756 {
1757 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1758 * That is bogus - but reading the conditions
1759 * we have to handle AS4_AGGREGATOR as if it were
1760 * AGGREGATOR in that case
1761 */
1762 if ( BGP_DEBUG(as4, AS4))
1763 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1764 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1765 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
370b64a2 1766 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
0b2aa3a0
PJ
1767 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1768 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1769 }
1770 }
1771
1772 /* need to reconcile NEW_AS_PATH and AS_PATH */
b881c707 1773 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
0b2aa3a0 1774 {
bb7bef14
PJ
1775 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1776 aspath_unintern (&attr->aspath);
1777 attr->aspath = aspath_intern (newpath);
0b2aa3a0 1778 }
b881c707 1779 return BGP_ATTR_PARSE_PROCEED;
0b2aa3a0
PJ
1780}
1781
718e3744 1782/* Community attribute. */
b881c707 1783static bgp_attr_parse_ret_t
835315bf 1784bgp_attr_community (struct bgp_attr_parser_args *args)
718e3744 1785{
835315bf
PJ
1786 struct peer *const peer = args->peer;
1787 struct attr *const attr = args->attr;
1788 const bgp_size_t length = args->length;
b881c707 1789
718e3744 1790 if (length == 0)
b2ceea18
PJ
1791 {
1792 attr->community = NULL;
b881c707 1793 return BGP_ATTR_PARSE_PROCEED;
b2ceea18 1794 }
0c466381
PJ
1795
1796 attr->community =
1797 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1798
1799 /* XXX: fix community_parse to use stream API and remove this */
1800 stream_forward_getp (peer->ibuf, length);
718e3744 1801
0c466381 1802 if (!attr->community)
835315bf 1803 return bgp_attr_malformed (args,
b881c707 1804 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
835315bf 1805 args->total);
0c466381 1806
718e3744 1807 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1808
b881c707 1809 return BGP_ATTR_PARSE_PROCEED;
718e3744 1810}
1811
1812/* Originator ID attribute. */
b881c707 1813static bgp_attr_parse_ret_t
835315bf 1814bgp_attr_originator_id (struct bgp_attr_parser_args *args)
718e3744 1815{
835315bf
PJ
1816 struct peer *const peer = args->peer;
1817 struct attr *const attr = args->attr;
1818 const bgp_size_t length = args->length;
1819
d595b566 1820 /* Length check. */
718e3744 1821 if (length != 4)
1822 {
16286195 1823 zlog_err ("Bad originator ID length %d", length);
718e3744 1824
835315bf 1825 return bgp_attr_malformed (args,
b881c707 1826 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
835315bf 1827 args->total);
718e3744 1828 }
1829
fb982c25
PJ
1830 (bgp_attr_extra_get (attr))->originator_id.s_addr
1831 = stream_get_ipv4 (peer->ibuf);
718e3744 1832
1833 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1834
b881c707 1835 return BGP_ATTR_PARSE_PROCEED;
718e3744 1836}
1837
1838/* Cluster list attribute. */
b881c707 1839static bgp_attr_parse_ret_t
835315bf 1840bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
718e3744 1841{
835315bf
PJ
1842 struct peer *const peer = args->peer;
1843 struct attr *const attr = args->attr;
1844 const bgp_size_t length = args->length;
1845
718e3744 1846 /* Check length. */
1847 if (length % 4)
1848 {
16286195 1849 zlog_err ("Bad cluster list length %d", length);
718e3744 1850
835315bf
PJ
1851 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1852 args->total);
718e3744 1853 }
1854
fb982c25
PJ
1855 (bgp_attr_extra_get (attr))->cluster
1856 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
b881c707
PJ
1857
1858 /* XXX: Fix cluster_parse to use stream API and then remove this */
1859 stream_forward_getp (peer->ibuf, length);
718e3744 1860
1861 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1862
b881c707 1863 return BGP_ATTR_PARSE_PROCEED;
718e3744 1864}
1865
1866/* Multiprotocol reachability information parse. */
03292809 1867int
835315bf
PJ
1868bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1869 struct bgp_nlri *mp_update)
718e3744 1870{
b58ed1f8
DS
1871 iana_afi_t pkt_afi;
1872 afi_t afi;
9cabb64b 1873 safi_t pkt_safi, safi;
718e3744 1874 bgp_size_t nlri_len;
6e4ab12f 1875 size_t start;
718e3744 1876 struct stream *s;
835315bf
PJ
1877 struct peer *const peer = args->peer;
1878 struct attr *const attr = args->attr;
1879 const bgp_size_t length = args->length;
fb982c25 1880 struct attr_extra *attre = bgp_attr_extra_get(attr);
835315bf 1881
718e3744 1882 /* Set end of packet. */
6e4ab12f
PJ
1883 s = BGP_INPUT(peer);
1884 start = stream_get_getp(s);
1885
1886 /* safe to read statically sized header? */
1887#define BGP_MP_REACH_MIN_SIZE 5
03292809 1888#define LEN_LEFT (length - (stream_get_getp(s) - start))
6e4ab12f 1889 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
03292809
PJ
1890 {
1891 zlog_info ("%s: %s sent invalid length, %lu",
1892 __func__, peer->host, (unsigned long)length);
f57000c0 1893 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 1894 }
6e4ab12f 1895
718e3744 1896 /* Load AFI, SAFI. */
9cabb64b 1897 pkt_afi = stream_getw (s);
1898 pkt_safi = stream_getc (s);
1899
1900 /* Convert AFI, SAFI to internal values, check. */
1901 if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
1902 {
1903 /* Log if AFI or SAFI is unrecognized. This is not an error unless
1904 * the attribute is otherwise malformed.
1905 */
1906 if (bgp_debug_update(peer, NULL, NULL, 0))
1907 zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
1908 peer->host, pkt_afi, pkt_safi);
1909 return BGP_ATTR_PARSE_ERROR;
1910 }
718e3744 1911
1912 /* Get nexthop length. */
fb982c25 1913 attre->mp_nexthop_len = stream_getc (s);
6e4ab12f 1914
03292809
PJ
1915 if (LEN_LEFT < attre->mp_nexthop_len)
1916 {
1917 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1918 __func__, peer->host, attre->mp_nexthop_len);
f57000c0 1919 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 1920 }
6e4ab12f 1921
718e3744 1922 /* Nexthop length check. */
fb982c25 1923 switch (attre->mp_nexthop_len)
718e3744 1924 {
801a9bcc
DS
1925 case BGP_ATTR_NHLEN_IPV4:
1926 stream_get (&attre->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
66bed4f4
ML
1927 /* Probably needed for RFC 2283 */
1928 if (attr->nexthop.s_addr == 0)
801a9bcc 1929 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
718e3744 1930 break;
801a9bcc 1931 case BGP_ATTR_NHLEN_VPNV4:
9206f9ec
SH
1932 stream_getl (s); /* RD high */
1933 stream_getl (s); /* RD low */
801a9bcc 1934 stream_get (&attre->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
718e3744 1935 break;
801a9bcc 1936 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
945c8fe9
LB
1937 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
1938 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL)
1939 {
1940 stream_getl (s); /* RD high */
1941 stream_getl (s); /* RD low */
1942 }
801a9bcc 1943 stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
718e3744 1944 break;
801a9bcc 1945 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
945c8fe9
LB
1946 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
1947 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
1948 {
1949 stream_getl (s); /* RD high */
1950 stream_getl (s); /* RD low */
1951 }
801a9bcc 1952 stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
945c8fe9
LB
1953 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
1954 {
1955 stream_getl (s); /* RD high */
1956 stream_getl (s); /* RD low */
1957 }
801a9bcc 1958 stream_get (&attre->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
fb982c25 1959 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
718e3744 1960 {
1961 char buf1[INET6_ADDRSTRLEN];
1962 char buf2[INET6_ADDRSTRLEN];
1963
3f9c7369 1964 if (bgp_debug_update(peer, NULL, NULL, 1))
3dd32081
DS
1965 zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value",
1966 peer->host,
fb982c25 1967 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
718e3744 1968 buf1, INET6_ADDRSTRLEN),
fb982c25 1969 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
718e3744 1970 buf2, INET6_ADDRSTRLEN));
1971
801a9bcc 1972 attre->mp_nexthop_len = IPV6_MAX_BYTELEN;
718e3744 1973 }
1974 break;
718e3744 1975 default:
03292809
PJ
1976 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1977 __func__, peer->host, attre->mp_nexthop_len);
f57000c0 1978 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
718e3744 1979 }
1980
03292809
PJ
1981 if (!LEN_LEFT)
1982 {
1983 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1984 __func__, peer->host);
f57000c0 1985 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 1986 }
718e3744 1987
6e4ab12f
PJ
1988 {
1989 u_char val;
1990 if ((val = stream_getc (s)))
1991 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1992 peer->host, val);
1993 }
1994
1995 /* must have nrli_len, what is left of the attribute */
03292809 1996 nlri_len = LEN_LEFT;
6e4ab12f 1997 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
03292809
PJ
1998 {
1999 zlog_info ("%s: (%s) Failed to read NLRI",
2000 __func__, peer->host);
f57000c0 2001 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
03292809 2002 }
718e3744 2003
2004 mp_update->afi = afi;
2005 mp_update->safi = safi;
2006 mp_update->nlri = stream_pnt (s);
2007 mp_update->length = nlri_len;
2008
9985f83c 2009 stream_forward_getp (s, nlri_len);
718e3744 2010
37da8fa9
DL
2011 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
2012
b881c707 2013 return BGP_ATTR_PARSE_PROCEED;
03292809 2014#undef LEN_LEFT
718e3744 2015}
2016
2017/* Multiprotocol unreachable parse */
03292809 2018int
835315bf 2019bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
718e3744 2020 struct bgp_nlri *mp_withdraw)
2021{
2022 struct stream *s;
b58ed1f8 2023 iana_afi_t pkt_afi;
4c9641ba 2024 afi_t afi;
9cabb64b 2025 safi_t pkt_safi, safi;
718e3744 2026 u_int16_t withdraw_len;
835315bf 2027 struct peer *const peer = args->peer;
37da8fa9 2028 struct attr *const attr = args->attr;
835315bf 2029 const bgp_size_t length = args->length;
718e3744 2030
2031 s = peer->ibuf;
6e4ab12f
PJ
2032
2033#define BGP_MP_UNREACH_MIN_SIZE 3
2034 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
f57000c0 2035 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
6e4ab12f 2036
9cabb64b 2037 pkt_afi = stream_getw (s);
2038 pkt_safi = stream_getc (s);
2039
2040 /* Convert AFI, SAFI to internal values, check. */
2041 if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
2042 {
2043 /* Log if AFI or SAFI is unrecognized. This is not an error unless
2044 * the attribute is otherwise malformed.
2045 */
2046 if (bgp_debug_update(peer, NULL, NULL, 0))
2047 zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
2048 peer->host, pkt_afi, pkt_safi);
2049 return BGP_ATTR_PARSE_ERROR;
2050 }
2051
6e4ab12f 2052 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
718e3744 2053
718e3744 2054 mp_withdraw->afi = afi;
2055 mp_withdraw->safi = safi;
2056 mp_withdraw->nlri = stream_pnt (s);
2057 mp_withdraw->length = withdraw_len;
2058
9985f83c 2059 stream_forward_getp (s, withdraw_len);
718e3744 2060
37da8fa9
DL
2061 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
2062
b881c707 2063 return BGP_ATTR_PARSE_PROCEED;
718e3744 2064}
2065
57d187bc
JS
2066/* Large Community attribute. */
2067static bgp_attr_parse_ret_t
2068bgp_attr_large_community (struct bgp_attr_parser_args *args)
2069{
2070 struct peer *const peer = args->peer;
2071 struct attr *const attr = args->attr;
2072 const bgp_size_t length = args->length;
2073
2074 /*
2075 * Large community follows new attribute format.
2076 */
2077 if (length == 0)
2078 {
2079 if (attr->extra)
2080 attr->extra->lcommunity = NULL;
2081 /* Empty extcomm doesn't seem to be invalid per se */
2082 return BGP_ATTR_PARSE_PROCEED;
2083 }
2084
2085 (bgp_attr_extra_get (attr))->lcommunity =
2086 lcommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
2087 /* XXX: fix ecommunity_parse to use stream API */
2088 stream_forward_getp (peer->ibuf, length);
2089
2090 if (attr->extra && !attr->extra->lcommunity)
2091 return bgp_attr_malformed (args,
2092 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2093 args->total);
2094
2095 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
2096
2097 return BGP_ATTR_PARSE_PROCEED;
2098}
2099
718e3744 2100/* Extended Community attribute. */
b881c707 2101static bgp_attr_parse_ret_t
835315bf 2102bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
718e3744 2103{
835315bf
PJ
2104 struct peer *const peer = args->peer;
2105 struct attr *const attr = args->attr;
2106 const bgp_size_t length = args->length;
b881c707 2107
718e3744 2108 if (length == 0)
fb982c25
PJ
2109 {
2110 if (attr->extra)
2111 attr->extra->ecommunity = NULL;
0c466381 2112 /* Empty extcomm doesn't seem to be invalid per se */
b881c707 2113 return BGP_ATTR_PARSE_PROCEED;
fb982c25 2114 }
0c466381
PJ
2115
2116 (bgp_attr_extra_get (attr))->ecommunity =
2117 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
2118 /* XXX: fix ecommunity_parse to use stream API */
2119 stream_forward_getp (peer->ibuf, length);
2120
57d187bc 2121 if (attr->extra && !attr->extra->ecommunity)
835315bf
PJ
2122 return bgp_attr_malformed (args,
2123 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2124 args->total);
0c466381 2125
718e3744 2126 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
2127
b881c707 2128 return BGP_ATTR_PARSE_PROCEED;
718e3744 2129}
2130
f4c89855
LB
2131/* Parse Tunnel Encap attribute in an UPDATE */
2132static int
2133bgp_attr_encap(
2134 uint8_t type,
2135 struct peer *peer, /* IN */
2136 bgp_size_t length, /* IN: attr's length field */
2137 struct attr *attr, /* IN: caller already allocated */
2138 u_char flag, /* IN: attr's flags field */
2139 u_char *startp)
2140{
2141 bgp_size_t total;
2142 struct attr_extra *attre = NULL;
2143 struct bgp_attr_encap_subtlv *stlv_last = NULL;
2de1475f 2144 uint16_t tunneltype = 0;
f4c89855
LB
2145
2146 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
2147
2148 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
2149 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
2150 {
2151 zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag);
2152 bgp_notify_send_with_data (peer,
2153 BGP_NOTIFY_UPDATE_ERR,
2154 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2155 startp, total);
2156 return -1;
2157 }
2158
2159 if (BGP_ATTR_ENCAP == type) {
2160 /* read outer TLV type and length */
2161 uint16_t tlv_length;
2162
2163 if (length < 4) {
2164 zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L");
2165 bgp_notify_send_with_data(peer,
2166 BGP_NOTIFY_UPDATE_ERR,
2167 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2168 startp, total);
2169 return -1;
2170 }
2171 tunneltype = stream_getw (BGP_INPUT (peer));
2172 tlv_length = stream_getw (BGP_INPUT (peer));
2173 length -= 4;
2174
2175 if (tlv_length != length) {
2176 zlog_info ("%s: tlv_length(%d) != length(%d)",
2177 __func__, tlv_length, length);
2178 }
2179 }
2180
2181 while (length >= 4) {
0f2b4f4d 2182 uint16_t subtype = 0;
f4cafc65 2183 uint16_t sublength = 0;
f4c89855
LB
2184 struct bgp_attr_encap_subtlv *tlv;
2185
587ff0fd
LB
2186 if (BGP_ATTR_ENCAP == type) {
2187 subtype = stream_getc (BGP_INPUT (peer));
2188 sublength = stream_getc (BGP_INPUT (peer));
2189 length -= 2;
65efcfce
LB
2190#if ENABLE_BGP_VNC
2191 } else {
2192 subtype = stream_getw (BGP_INPUT (peer));
2193 sublength = stream_getw (BGP_INPUT (peer));
2194 length -= 4;
2195#endif
587ff0fd 2196 }
f4c89855
LB
2197
2198 if (sublength > length) {
2199 zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2200 sublength, length);
2201 bgp_notify_send_with_data (peer,
2202 BGP_NOTIFY_UPDATE_ERR,
2203 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2204 startp, total);
2205 return -1;
2206 }
2207
2208 /* alloc and copy sub-tlv */
2209 /* TBD make sure these are freed when attributes are released */
2210 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
2211 tlv->type = subtype;
2212 tlv->length = sublength;
2213 stream_get(tlv->value, peer->ibuf, sublength);
2214 length -= sublength;
2215
2216 /* attach tlv to encap chain */
2217 if (!attre) {
2218 attre = bgp_attr_extra_get(attr);
2219 if (BGP_ATTR_ENCAP == type) {
2220 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
2221 stlv_last = stlv_last->next);
2222 if (stlv_last) {
2223 stlv_last->next = tlv;
2224 } else {
2225 attre->encap_subtlvs = tlv;
2226 }
65efcfce
LB
2227#if ENABLE_BGP_VNC
2228 } else {
2229 for (stlv_last = attre->vnc_subtlvs; stlv_last && stlv_last->next;
2230 stlv_last = stlv_last->next);
2231 if (stlv_last) {
2232 stlv_last->next = tlv;
2233 } else {
2234 attre->vnc_subtlvs = tlv;
2235 }
2236#endif
f4c89855
LB
2237 }
2238 } else {
2239 stlv_last->next = tlv;
2240 }
2241 stlv_last = tlv;
2242 }
2243
ac73d8fb
LB
2244 if (BGP_ATTR_ENCAP == type) {
2245 if (!attre)
2246 attre = bgp_attr_extra_get(attr);
2247 attre->encap_tunneltype = tunneltype;
f4c89855
LB
2248 }
2249
2250 if (length) {
2251 /* spurious leftover data */
2252 zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length);
2253 bgp_notify_send_with_data (peer,
2254 BGP_NOTIFY_UPDATE_ERR,
2255 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2256 startp, total);
2257 return -1;
2258 }
2259
2260 return 0;
2261}
2262
c5a543b4
DW
2263/* Prefix SID attribute
2264 * draft-ietf-idr-bgp-prefix-sid-05
2265 */
6cf48acc 2266static bgp_attr_parse_ret_t
c5a543b4 2267bgp_attr_prefix_sid (struct bgp_attr_parser_args *args, struct bgp_nlri *mp_update)
6cf48acc
VV
2268{
2269 struct peer *const peer = args->peer;
2270 struct attr *const attr = args->attr;
c5a543b4
DW
2271 int type;
2272 int length;
6cf48acc 2273 u_int32_t label_index;
c5a543b4
DW
2274 struct in6_addr ipv6_sid;
2275 u_int32_t srgb_base;
2276 u_int32_t srgb_range;
2277 int srgb_count;
6cf48acc 2278
c5a543b4
DW
2279 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID);
2280
2281 type = stream_getc (peer->ibuf);
2282 length = stream_getw (peer->ibuf);
2283
2284 if (type == BGP_PREFIX_SID_LABEL_INDEX)
6cf48acc 2285 {
c5a543b4
DW
2286 if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH)
2287 {
2288 zlog_err ("Prefix SID label index length is %d instead of %d", length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
2289 return bgp_attr_malformed (args,
2290 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2291 args->total);
2292 }
6cf48acc 2293
c5a543b4
DW
2294 /* Ignore flags and reserved */
2295 stream_getc (peer->ibuf);
2296 stream_getw (peer->ibuf);
6cf48acc 2297
c5a543b4
DW
2298 /* Fetch the label index and see if it is valid. */
2299 label_index = stream_getl (peer->ibuf);
2300 if (label_index == BGP_INVALID_LABEL_INDEX)
2301 return bgp_attr_malformed (args,
2302 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2303 args->total);
6cf48acc 2304
c5a543b4
DW
2305 /* Store label index; subsequently, we'll check on address-family */
2306 (bgp_attr_extra_get (attr))->label_index = label_index;
2307
2308 /*
2309 * Ignore the Label index attribute unless received for labeled-unicast
2310 * SAFI.
2311 */
2312 if (!mp_update->length || mp_update->safi != SAFI_LABELED_UNICAST)
2313 attr->extra->label_index = BGP_INVALID_LABEL_INDEX;
2314 }
6cf48acc 2315
c5a543b4
DW
2316 /* Placeholder code for the IPv6 SID type */
2317 else if (type == BGP_PREFIX_SID_IPV6)
2318 {
2319 if (length != BGP_PREFIX_SID_IPV6_LENGTH)
2320 {
2321 zlog_err ("Prefix SID IPv6 length is %d instead of %d", length, BGP_PREFIX_SID_IPV6_LENGTH);
2322 return bgp_attr_malformed (args,
2323 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2324 args->total);
2325 }
6cf48acc 2326
c5a543b4
DW
2327 /* Ignore reserved */
2328 stream_getc (peer->ibuf);
2329 stream_getw (peer->ibuf);
6cf48acc 2330
c5a543b4
DW
2331 stream_get (&ipv6_sid, peer->ibuf, 16);
2332 }
2333
2334 /* Placeholder code for the Originator SRGB type */
2335 else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB)
6cf48acc 2336 {
c5a543b4
DW
2337 /* Ignore flags */
2338 stream_getw (peer->ibuf);
2339
2340 length -= 2;
2341
2342 if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH)
2343 {
2344 zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2345 length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
2346 return bgp_attr_malformed (args,
2347 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2348 args->total);
2349 }
2350
2351 srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH;
2352
2353 for (int i = 0; i < srgb_count; i++)
2354 {
2355 stream_get (&srgb_base, peer->ibuf, 3);
2356 stream_get (&srgb_range, peer->ibuf, 3);
2357 }
6cf48acc 2358 }
c5a543b4 2359
6cf48acc
VV
2360 return BGP_ATTR_PARSE_PROCEED;
2361}
2362
718e3744 2363/* BGP unknown attribute treatment. */
b881c707 2364static bgp_attr_parse_ret_t
835315bf 2365bgp_attr_unknown (struct bgp_attr_parser_args *args)
718e3744 2366{
8794e8d2 2367 bgp_size_t total = args->total;
718e3744 2368 struct transit *transit;
fb982c25 2369 struct attr_extra *attre;
835315bf
PJ
2370 struct peer *const peer = args->peer;
2371 struct attr *const attr = args->attr;
2372 u_char *const startp = args->startp;
2373 const u_char type = args->type;
2374 const u_char flag = args->flags;
2375 const bgp_size_t length = args->length;
2376
3f9c7369 2377 if (bgp_debug_update(peer, NULL, NULL, 1))
16286195
DS
2378 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2379 peer->host, type, length);
f418446b 2380
718e3744 2381 /* Forward read pointer of input stream. */
9985f83c 2382 stream_forward_getp (peer->ibuf, length);
718e3744 2383
718e3744 2384 /* If any of the mandatory well-known attributes are not recognized,
2385 then the Error Subcode is set to Unrecognized Well-known
2386 Attribute. The Data field contains the unrecognized attribute
2387 (type, length and value). */
b881c707 2388 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
718e3744 2389 {
835315bf 2390 return bgp_attr_malformed (args,
b881c707 2391 BGP_NOTIFY_UPDATE_UNREC_ATTR,
835315bf 2392 args->total);
718e3744 2393 }
2394
2395 /* Unrecognized non-transitive optional attributes must be quietly
2396 ignored and not passed along to other BGP peers. */
2397 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
b881c707 2398 return BGP_ATTR_PARSE_PROCEED;
718e3744 2399
2400 /* If a path with recognized transitive optional attribute is
2401 accepted and passed along to other BGP peers and the Partial bit
2402 in the Attribute Flags octet is set to 1 by some previous AS, it
2403 is not set back to 0 by the current AS. */
2404 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
2405
2406 /* Store transitive attribute to the end of attr->transit. */
fb982c25 2407 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
393deb9b 2408 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
718e3744 2409
fb982c25 2410 transit = attre->transit;
718e3744 2411
2412 if (transit->val)
2413 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
2414 transit->length + total);
2415 else
2416 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2417
2418 memcpy (transit->val + transit->length, startp, total);
2419 transit->length += total;
2420
b881c707 2421 return BGP_ATTR_PARSE_PROCEED;
718e3744 2422}
2423
bb7bef14
PJ
2424/* Well-known attribute check. */
2425static int
52a51fd3 2426bgp_attr_check (struct peer *peer, struct attr *attr)
bb7bef14
PJ
2427{
2428 u_char type = 0;
2429
67495ddb
PJ
2430 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2431 * empty UPDATE. */
2432 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2433 return BGP_ATTR_PARSE_PROCEED;
2434
2435 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2436 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2437 are present, it should. Check for any other attribute being present
2438 instead.
2439 */
2440 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2441 return BGP_ATTR_PARSE_PROCEED;
2442
bb7bef14
PJ
2443 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2444 type = BGP_ATTR_ORIGIN;
2445
2446 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2447 type = BGP_ATTR_AS_PATH;
2448
52a51fd3
DW
2449 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2450 * NLRI is empty. We can't easily check NLRI empty here though.
bb7bef14 2451 */
52a51fd3
DW
2452 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2453 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
2454 type = BGP_ATTR_NEXT_HOP;
bb7bef14
PJ
2455
2456 if (peer->sort == BGP_PEER_IBGP
2457 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2458 type = BGP_ATTR_LOCAL_PREF;
2459
2460 if (type)
2461 {
52a51fd3
DW
2462 zlog_warn ("%s Missing well-known attribute %s.", peer->host,
2463 LOOKUP (attr_str, type));
bb7bef14
PJ
2464 bgp_notify_send_with_data (peer,
2465 BGP_NOTIFY_UPDATE_ERR,
2466 BGP_NOTIFY_UPDATE_MISS_ATTR,
2467 &type, 1);
2468 return BGP_ATTR_PARSE_ERROR;
2469 }
2470 return BGP_ATTR_PARSE_PROCEED;
2471}
2472
718e3744 2473/* Read attribute of update packet. This function is called from
8b366b9c 2474 bgp_update_receive() in bgp_packet.c. */
b881c707 2475bgp_attr_parse_ret_t
718e3744 2476bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
52a51fd3 2477 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
718e3744 2478{
2479 int ret;
b881c707 2480 u_char flag = 0;
0b2aa3a0 2481 u_char type = 0;
718e3744 2482 bgp_size_t length;
2483 u_char *startp, *endp;
2484 u_char *attr_endp;
2485 u_char seen[BGP_ATTR_BITMAP_SIZE];
0b2aa3a0
PJ
2486 /* we need the as4_path only until we have synthesized the as_path with it */
2487 /* same goes for as4_aggregator */
2488 struct aspath *as4_path = NULL;
2489 as_t as4_aggregator = 0;
19c3598b 2490 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
718e3744 2491
2492 /* Initialize bitmap. */
2493 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2494
2495 /* End pointer of BGP attribute. */
2496 endp = BGP_INPUT_PNT (peer) + size;
b881c707 2497
718e3744 2498 /* Get attributes to the end of attribute length. */
2499 while (BGP_INPUT_PNT (peer) < endp)
2500 {
2501 /* Check remaining length check.*/
2502 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2503 {
c29fdba7 2504 /* XXX warning: long int format, int arg (arg 5) */
16286195
DS
2505 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
2506 peer->host,
2507 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
718e3744 2508
2509 bgp_notify_send (peer,
2510 BGP_NOTIFY_UPDATE_ERR,
2511 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707 2512 return BGP_ATTR_PARSE_ERROR;
718e3744 2513 }
2514
2515 /* Fetch attribute flag and type. */
2516 startp = BGP_INPUT_PNT (peer);
2d42e68a
DO
2517 /* "The lower-order four bits of the Attribute Flags octet are
2518 unused. They MUST be zero when sent and MUST be ignored when
2519 received." */
2520 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
718e3744 2521 type = stream_getc (BGP_INPUT (peer));
2522
370b64a2
PJ
2523 /* Check whether Extended-Length applies and is in bounds */
2524 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2525 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2526 {
16286195
DS
2527 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
2528 peer->host,
2529 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
370b64a2
PJ
2530
2531 bgp_notify_send (peer,
2532 BGP_NOTIFY_UPDATE_ERR,
2533 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707 2534 return BGP_ATTR_PARSE_ERROR;
370b64a2 2535 }
835315bf 2536
718e3744 2537 /* Check extended attribue length bit. */
2538 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2539 length = stream_getw (BGP_INPUT (peer));
2540 else
2541 length = stream_getc (BGP_INPUT (peer));
2542
2543 /* If any attribute appears more than once in the UPDATE
2544 message, then the Error Subcode is set to Malformed Attribute
2545 List. */
2546
2547 if (CHECK_BITMAP (seen, type))
2548 {
16286195
DS
2549 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
2550 peer->host, type);
718e3744 2551
2552 bgp_notify_send (peer,
2553 BGP_NOTIFY_UPDATE_ERR,
2554 BGP_NOTIFY_UPDATE_MAL_ATTR);
b881c707 2555 return BGP_ATTR_PARSE_ERROR;
718e3744 2556 }
2557
2558 /* Set type to bitmap to check duplicate attribute. `type' is
2559 unsigned char so it never overflow bitmap range. */
2560
2561 SET_BITMAP (seen, type);
2562
2563 /* Overflow check. */
2564 attr_endp = BGP_INPUT_PNT (peer) + length;
2565
2566 if (attr_endp > endp)
2567 {
16286195 2568 zlog_warn ("%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp);
b184ccd8
DS
2569 bgp_notify_send_with_data (peer,
2570 BGP_NOTIFY_UPDATE_ERR,
2571 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2572 startp, attr_endp - startp);
b881c707 2573 return BGP_ATTR_PARSE_ERROR;
718e3744 2574 }
835315bf
PJ
2575
2576 struct bgp_attr_parser_args attr_args = {
2577 .peer = peer,
2578 .length = length,
2579 .attr = attr,
2580 .type = type,
2581 .flags = flag,
2582 .startp = startp,
2583 .total = attr_endp - startp,
2584 };
2585
2586
2587 /* If any recognized attribute has Attribute Flags that conflict
2588 with the Attribute Type Code, then the Error Subcode is set to
2589 Attribute Flags Error. The Data field contains the erroneous
2590 attribute (type, length and value). */
2591 if (bgp_attr_flag_invalid (&attr_args))
fa61e16d
PJ
2592 {
2593 bgp_attr_parse_ret_t ret;
2594 ret = bgp_attr_malformed (&attr_args,
2595 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2596 attr_args.total);
2597 if (ret == BGP_ATTR_PARSE_PROCEED)
2598 continue;
2599 return ret;
2600 }
718e3744 2601
2602 /* OK check attribute and store it's value. */
2603 switch (type)
2604 {
2605 case BGP_ATTR_ORIGIN:
835315bf 2606 ret = bgp_attr_origin (&attr_args);
718e3744 2607 break;
2608 case BGP_ATTR_AS_PATH:
835315bf 2609 ret = bgp_attr_aspath (&attr_args);
718e3744 2610 break;
0b2aa3a0 2611 case BGP_ATTR_AS4_PATH:
835315bf 2612 ret = bgp_attr_as4_path (&attr_args, &as4_path);
0b2aa3a0 2613 break;
718e3744 2614 case BGP_ATTR_NEXT_HOP:
835315bf 2615 ret = bgp_attr_nexthop (&attr_args);
718e3744 2616 break;
2617 case BGP_ATTR_MULTI_EXIT_DISC:
835315bf 2618 ret = bgp_attr_med (&attr_args);
718e3744 2619 break;
2620 case BGP_ATTR_LOCAL_PREF:
835315bf 2621 ret = bgp_attr_local_pref (&attr_args);
718e3744 2622 break;
2623 case BGP_ATTR_ATOMIC_AGGREGATE:
835315bf 2624 ret = bgp_attr_atomic (&attr_args);
718e3744 2625 break;
2626 case BGP_ATTR_AGGREGATOR:
835315bf 2627 ret = bgp_attr_aggregator (&attr_args);
718e3744 2628 break;
0b2aa3a0 2629 case BGP_ATTR_AS4_AGGREGATOR:
835315bf
PJ
2630 ret = bgp_attr_as4_aggregator (&attr_args,
2631 &as4_aggregator,
2632 &as4_aggregator_addr);
0b2aa3a0 2633 break;
718e3744 2634 case BGP_ATTR_COMMUNITIES:
835315bf 2635 ret = bgp_attr_community (&attr_args);
718e3744 2636 break;
57d187bc
JS
2637 case BGP_ATTR_LARGE_COMMUNITIES:
2638 ret = bgp_attr_large_community (&attr_args);
2639 break;
718e3744 2640 case BGP_ATTR_ORIGINATOR_ID:
835315bf 2641 ret = bgp_attr_originator_id (&attr_args);
718e3744 2642 break;
2643 case BGP_ATTR_CLUSTER_LIST:
835315bf 2644 ret = bgp_attr_cluster_list (&attr_args);
718e3744 2645 break;
2646 case BGP_ATTR_MP_REACH_NLRI:
835315bf 2647 ret = bgp_mp_reach_parse (&attr_args, mp_update);
718e3744 2648 break;
2649 case BGP_ATTR_MP_UNREACH_NLRI:
835315bf 2650 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
718e3744 2651 break;
2652 case BGP_ATTR_EXT_COMMUNITIES:
835315bf 2653 ret = bgp_attr_ext_communities (&attr_args);
718e3744 2654 break;
65efcfce
LB
2655#if ENABLE_BGP_VNC
2656 case BGP_ATTR_VNC:
2657#endif
f4c89855
LB
2658 case BGP_ATTR_ENCAP:
2659 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2660 break;
c5a543b4
DW
2661 case BGP_ATTR_PREFIX_SID:
2662 ret = bgp_attr_prefix_sid (&attr_args, mp_update);
6cf48acc 2663 break;
718e3744 2664 default:
835315bf 2665 ret = bgp_attr_unknown (&attr_args);
718e3744 2666 break;
2667 }
b881c707 2668
f57000c0
DL
2669 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2670 {
2671 bgp_notify_send (peer,
2672 BGP_NOTIFY_UPDATE_ERR,
2673 BGP_NOTIFY_UPDATE_MAL_ATTR);
2674 ret = BGP_ATTR_PARSE_ERROR;
2675 }
2676
b881c707
PJ
2677 /* If hard error occured immediately return to the caller. */
2678 if (ret == BGP_ATTR_PARSE_ERROR)
6e4ab12f 2679 {
16286195
DS
2680 zlog_warn ("%s: Attribute %s, parse error",
2681 peer->host,
2682 LOOKUP (attr_str, type));
b881c707
PJ
2683 if (as4_path)
2684 aspath_unintern (&as4_path);
2685 return ret;
6e4ab12f 2686 }
b881c707
PJ
2687 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2688 {
2689
16286195
DS
2690 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
2691 peer->host,
2692 LOOKUP (attr_str, type));
b881c707
PJ
2693 if (as4_path)
2694 aspath_unintern (&as4_path);
2695 return ret;
2696 }
2697
718e3744 2698 /* Check the fetched length. */
2699 if (BGP_INPUT_PNT (peer) != attr_endp)
2700 {
16286195
DS
2701 zlog_warn ("%s: BGP attribute %s, fetch error",
2702 peer->host, LOOKUP (attr_str, type));
718e3744 2703 bgp_notify_send (peer,
2704 BGP_NOTIFY_UPDATE_ERR,
2705 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707
PJ
2706 if (as4_path)
2707 aspath_unintern (&as4_path);
2708 return BGP_ATTR_PARSE_ERROR;
718e3744 2709 }
2710 }
2711
2712 /* Check final read pointer is same as end pointer. */
2713 if (BGP_INPUT_PNT (peer) != endp)
2714 {
16286195
DS
2715 zlog_warn ("%s: BGP attribute %s, length mismatch",
2716 peer->host, LOOKUP (attr_str, type));
718e3744 2717 bgp_notify_send (peer,
2718 BGP_NOTIFY_UPDATE_ERR,
2719 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
b881c707
PJ
2720 if (as4_path)
2721 aspath_unintern (&as4_path);
2722 return BGP_ATTR_PARSE_ERROR;
718e3744 2723 }
2724
bb7bef14
PJ
2725 /* Check all mandatory well-known attributes are present */
2726 {
2727 bgp_attr_parse_ret_t ret;
52a51fd3 2728 if ((ret = bgp_attr_check (peer, attr)) < 0)
bb7bef14
PJ
2729 {
2730 if (as4_path)
2731 aspath_unintern (&as4_path);
2732 return ret;
2733 }
2734 }
2735
0b2aa3a0
PJ
2736 /*
2737 * At this place we can see whether we got AS4_PATH and/or
2738 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2739 * We can not do this before we've read all attributes because
2740 * the as4 handling does not say whether AS4_PATH has to be sent
2741 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2742 * in relationship to AGGREGATOR.
2743 * So, to be defensive, we are not relying on any order and read
2744 * all attributes first, including these 32bit ones, and now,
2745 * afterwards, we look what and if something is to be done for as4.
67495ddb
PJ
2746 *
2747 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2748 * MP_UNREACH_NLRI.
0b2aa3a0 2749 */
f57000c0
DL
2750 /* actually... this doesn't ever return failure currently, but
2751 * better safe than sorry */
67495ddb
PJ
2752 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2753 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
0b2aa3a0 2754 as4_aggregator, &as4_aggregator_addr))
b881c707 2755 {
f57000c0
DL
2756 bgp_notify_send (peer,
2757 BGP_NOTIFY_UPDATE_ERR,
2758 BGP_NOTIFY_UPDATE_MAL_ATTR);
b881c707
PJ
2759 if (as4_path)
2760 aspath_unintern (&as4_path);
2761 return BGP_ATTR_PARSE_ERROR;
2762 }
0b2aa3a0
PJ
2763
2764 /* At this stage, we have done all fiddling with as4, and the
2765 * resulting info is in attr->aggregator resp. attr->aspath
2766 * so we can chuck as4_aggregator and as4_path alltogether in
2767 * order to save memory
2768 */
b881c707 2769 if (as4_path)
0b2aa3a0 2770 {
f6f434b2 2771 aspath_unintern (&as4_path); /* unintern - it is in the hash */
0b2aa3a0
PJ
2772 /* The flag that we got this is still there, but that does not
2773 * do any trouble
2774 */
2775 }
2776 /*
2777 * The "rest" of the code does nothing with as4_aggregator.
2778 * there is no memory attached specifically which is not part
2779 * of the attr.
2780 * so ignoring just means do nothing.
2781 */
2782 /*
2783 * Finally do the checks on the aspath we did not do yet
2784 * because we waited for a potentially synthesized aspath.
2785 */
b881c707 2786 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
0b2aa3a0 2787 {
835315bf 2788 ret = bgp_attr_aspath_check (peer, attr);
b881c707 2789 if (ret != BGP_ATTR_PARSE_PROCEED)
0b2aa3a0
PJ
2790 return ret;
2791 }
bede7744
LB
2792 if (attr->extra)
2793 {
2794 /* Finally intern unknown attribute. */
2795 if (attr->extra->transit)
2796 attr->extra->transit = transit_intern (attr->extra->transit);
2797 if (attr->extra->encap_subtlvs)
2798 attr->extra->encap_subtlvs = encap_intern (attr->extra->encap_subtlvs, ENCAP_SUBTLV_TYPE);
2799#if ENABLE_BGP_VNC
2800 if (attr->extra->vnc_subtlvs)
2801 attr->extra->vnc_subtlvs = encap_intern (attr->extra->vnc_subtlvs, VNC_SUBTLV_TYPE);
2802#endif
2803 }
718e3744 2804
b881c707 2805 return BGP_ATTR_PARSE_PROCEED;
718e3744 2806}
2807
8c71e481 2808size_t
2b26882d
DW
2809bgp_packet_mpattr_start (struct stream *s, struct peer *peer,
2810 afi_t afi, safi_t safi,
3f9c7369 2811 struct bpacket_attr_vec_arr *vecarr,
8c71e481
PM
2812 struct attr *attr)
2813{
2814 size_t sizep;
b58ed1f8 2815 iana_afi_t pkt_afi;
9cabb64b 2816 safi_t pkt_safi;
2b26882d 2817 afi_t nh_afi;
8c71e481
PM
2818
2819 /* Set extended bit always to encode the attribute length as 2 bytes */
2820 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2821 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2822 sizep = stream_get_endp (s);
2823 stream_putw (s, 0); /* Marker: Attribute length. */
93b73dfa 2824
9cabb64b 2825
2826 /* Convert AFI, SAFI to values for packet. */
2827 bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
2828
2829 stream_putw (s, pkt_afi); /* AFI */
2830 stream_putc (s, pkt_safi); /* SAFI */
aab1814c 2831
a080e8fb
DW
2832 /* Nexthop AFI */
2833 if (peer_cap_enhe(peer, afi, safi)) {
2834 nh_afi = AFI_IP6;
2835 } else {
2836 if (afi == AFI_L2VPN)
2837 nh_afi = AFI_L2VPN;
2838 else if (safi == SAFI_LABELED_UNICAST)
2839 nh_afi = afi;
2840 else
2841 nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->extra->mp_nexthop_len);
2842 }
aab1814c 2843
8c71e481 2844 /* Nexthop */
3800c7b0 2845 bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
8a92a8a0 2846 switch (nh_afi)
8c71e481
PM
2847 {
2848 case AFI_IP:
2849 switch (safi)
2850 {
6407da5a 2851 case SAFI_UNICAST:
8c71e481 2852 case SAFI_MULTICAST:
cd1964ff 2853 case SAFI_LABELED_UNICAST:
8c71e481
PM
2854 stream_putc (s, 4);
2855 stream_put_ipv4 (s, attr->nexthop.s_addr);
2856 break;
2857 case SAFI_MPLS_VPN:
2858 stream_putc (s, 12);
93b73dfa 2859 stream_putl (s, 0); /* RD = 0, per RFC */
8c71e481
PM
2860 stream_putl (s, 0);
2861 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2862 break;
587ff0fd
LB
2863 case SAFI_ENCAP:
2864 stream_putc (s, 4);
2865 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2866 break;
8c71e481
PM
2867 default:
2868 break;
2869 }
2870 break;
8c71e481
PM
2871 case AFI_IP6:
2872 switch (safi)
2873 {
2874 case SAFI_UNICAST:
2875 case SAFI_MULTICAST:
cd1964ff 2876 case SAFI_LABELED_UNICAST:
8c71e481 2877 {
8c71e481
PM
2878 struct attr_extra *attre = attr->extra;
2879
2880 assert (attr->extra);
343e90c3
DW
2881
2882 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
2883 stream_putc (s, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
2884 stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
801a9bcc 2885 stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
343e90c3
DW
2886 } else {
2887 stream_putc (s, IPV6_MAX_BYTELEN);
2888 stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
2889 }
8c71e481 2890 }
93b73dfa
LB
2891 break;
2892 case SAFI_MPLS_VPN:
2893 {
2894 struct attr_extra *attre = attr->extra;
2895
2896 assert (attr->extra);
6407da5a 2897 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
93b73dfa
LB
2898 stream_putc (s, 24);
2899 stream_putl (s, 0); /* RD = 0, per RFC */
2900 stream_putl (s, 0);
6407da5a 2901 stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
2902 } else if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
93b73dfa
LB
2903 stream_putc (s, 48);
2904 stream_putl (s, 0); /* RD = 0, per RFC */
2905 stream_putl (s, 0);
6407da5a 2906 stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
93b73dfa
LB
2907 stream_putl (s, 0); /* RD = 0, per RFC */
2908 stream_putl (s, 0);
6407da5a 2909 stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
93b73dfa
LB
2910 }
2911 }
2912 break;
587ff0fd
LB
2913 case SAFI_ENCAP:
2914 assert (attr->extra);
2915 stream_putc (s, IPV6_MAX_BYTELEN);
2916 stream_put (s, &attr->extra->mp_nexthop_global, IPV6_MAX_BYTELEN);
2917 break;
8c71e481
PM
2918 default:
2919 break;
2920 }
2921 break;
e9cf8c8e
PG
2922 case AFI_L2VPN:
2923 switch (safi)
2924 {
2925 case SAFI_EVPN:
2926 if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV4)
2927 {
2928 stream_putc (s, 12);
2929 stream_putl (s, 0); /* RD = 0, per RFC */
2930 stream_putl (s, 0);
2931 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2932 }
2933 else if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL)
2934 {
2935 stream_putc (s, 24);
2936 stream_putl (s, 0); /* RD = 0, per RFC */
2937 stream_putl (s, 0);
2938 stream_put (s, &attr->extra->mp_nexthop_global, IPV6_MAX_BYTELEN);
2939 }
2940 else if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
2941 {
2942 stream_putc (s, 48);
2943 stream_putl (s, 0); /* RD = 0, per RFC */
2944 stream_putl (s, 0);
2945 stream_put (s, &attr->extra->mp_nexthop_global, IPV6_MAX_BYTELEN);
2946 stream_putl (s, 0); /* RD = 0, per RFC */
2947 stream_putl (s, 0);
2948 stream_put (s, &attr->extra->mp_nexthop_local, IPV6_MAX_BYTELEN);
2949 }
2950 break;
2951 break;
2952 default:
2953 break;
2954 }
8c71e481
PM
2955 default:
2956 break;
2957 }
2958
2959 /* SNPA */
2960 stream_putc (s, 0);
2961 return sizep;
2962}
2963
2964void
2965bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2966 struct prefix *p, struct prefix_rd *prd,
adbac85e 2967 u_char *tag, int addpath_encode,
b18825eb 2968 u_int32_t addpath_tx_id, struct attr *attr)
8c71e481 2969{
93b73dfa 2970 if (safi == SAFI_MPLS_VPN)
8c71e481 2971 {
adbac85e
DW
2972 if (addpath_encode)
2973 stream_putl(s, addpath_tx_id);
8c71e481
PM
2974 /* Tag, RD, Prefix write. */
2975 stream_putc (s, p->prefixlen + 88);
2976 stream_put (s, tag, 3);
2977 stream_put (s, prd->val, 8);
2978 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
8c71e481 2979 }
b00383ea 2980 else if (safi == SAFI_EVPN)
b18825eb
PG
2981 {
2982 bgp_packet_mpattr_route_type_5(s, p, prd, tag, attr);
2983 }
cd1964ff
DS
2984 else if (safi == SAFI_LABELED_UNICAST)
2985 {
2986 /* Prefix write with label. */
2987 stream_put_labeled_prefix(s, p, tag);
2988 }
93b73dfa
LB
2989 else
2990 stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
2991}
2992
2993size_t
2994bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2995{
2996 int size = PSIZE (p->prefixlen);
2997 if (safi == SAFI_MPLS_VPN)
2998 size += 88;
2999 return size;
8c71e481
PM
3000}
3001
f4c89855 3002/*
65efcfce
LB
3003 * Encodes the tunnel encapsulation attribute,
3004 * and with ENABLE_BGP_VNC the VNC attribute which uses
3005 * almost the same TLV format
f4c89855
LB
3006 */
3007static void
3008bgp_packet_mpattr_tea(
3009 struct bgp *bgp,
3010 struct peer *peer,
3011 struct stream *s,
3012 struct attr *attr,
3013 uint8_t attrtype)
3014{
3015 unsigned int attrlenfield = 0;
587ff0fd 3016 unsigned int attrhdrlen = 0;
f4c89855
LB
3017 struct bgp_attr_encap_subtlv *subtlvs;
3018 struct bgp_attr_encap_subtlv *st;
3019 const char *attrname;
3020
ac73d8fb
LB
3021 if (!attr || !attr->extra ||
3022 (attrtype == BGP_ATTR_ENCAP &&
3023 (!attr->extra->encap_tunneltype ||
3024 attr->extra->encap_tunneltype == BGP_ENCAP_TYPE_MPLS)))
f4c89855
LB
3025 return;
3026
3027 switch (attrtype) {
3028 case BGP_ATTR_ENCAP:
3029 attrname = "Tunnel Encap";
3030 subtlvs = attr->extra->encap_subtlvs;
f4c6f62d
LB
3031 if (subtlvs == NULL) /* nothing to do */
3032 return;
f4c89855
LB
3033 /*
3034 * The tunnel encap attr has an "outer" tlv.
3035 * T = tunneltype,
3036 * L = total length of subtlvs,
3037 * V = concatenated subtlvs.
3038 */
3039 attrlenfield = 2 + 2; /* T + L */
587ff0fd 3040 attrhdrlen = 1 + 1; /* subTLV T + L */
f4c89855
LB
3041 break;
3042
65efcfce
LB
3043#if ENABLE_BGP_VNC
3044 case BGP_ATTR_VNC:
3045 attrname = "VNC";
3046 subtlvs = attr->extra->vnc_subtlvs;
f4c6f62d
LB
3047 if (subtlvs == NULL) /* nothing to do */
3048 return;
65efcfce
LB
3049 attrlenfield = 0; /* no outer T + L */
3050 attrhdrlen = 2 + 2; /* subTLV T + L */
3051 break;
3052#endif
3053
f4c89855
LB
3054 default:
3055 assert(0);
3056 }
3057
f4c89855
LB
3058 /* compute attr length */
3059 for (st = subtlvs; st; st = st->next) {
587ff0fd 3060 attrlenfield += (attrhdrlen + st->length);
f4c89855
LB
3061 }
3062
f4c89855
LB
3063 if (attrlenfield > 0xffff) {
3064 zlog_info ("%s attribute is too long (length=%d), can't send it",
3065 attrname,
3066 attrlenfield);
3067 return;
3068 }
3069
3070 if (attrlenfield > 0xff) {
3071 /* 2-octet length field */
3072 stream_putc (s,
3073 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
3074 stream_putc (s, attrtype);
3075 stream_putw (s, attrlenfield & 0xffff);
3076 } else {
3077 /* 1-octet length field */
3078 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
3079 stream_putc (s, attrtype);
3080 stream_putc (s, attrlenfield & 0xff);
3081 }
3082
3083 if (attrtype == BGP_ATTR_ENCAP) {
3084 /* write outer T+L */
3085 stream_putw(s, attr->extra->encap_tunneltype);
3086 stream_putw(s, attrlenfield - 4);
3087 }
3088
3089 /* write each sub-tlv */
3090 for (st = subtlvs; st; st = st->next) {
587ff0fd
LB
3091 if (attrtype == BGP_ATTR_ENCAP) {
3092 stream_putc (s, st->type);
3093 stream_putc (s, st->length);
65efcfce
LB
3094#if ENABLE_BGP_VNC
3095 } else {
3096 stream_putw (s, st->type);
3097 stream_putw (s, st->length);
3098#endif
587ff0fd 3099 }
f4c89855
LB
3100 stream_put (s, st->value, st->length);
3101 }
3102}
f4c89855 3103
8c71e481
PM
3104void
3105bgp_packet_mpattr_end (struct stream *s, size_t sizep)
3106{
3107 /* Set MP attribute length. Don't count the (2) bytes used to encode
3108 the attr length */
3109 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
3110}
3111
718e3744 3112/* Make attribute packet. */
3113bgp_size_t
3114bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
8c71e481 3115 struct stream *s, struct attr *attr,
3f9c7369 3116 struct bpacket_attr_vec_arr *vecarr,
8c71e481 3117 struct prefix *p, afi_t afi, safi_t safi,
adbac85e
DW
3118 struct peer *from, struct prefix_rd *prd, u_char *tag,
3119 int addpath_encode,
3120 u_int32_t addpath_tx_id)
718e3744 3121{
fe69a505 3122 size_t cp;
0b2aa3a0 3123 size_t aspath_sizep;
718e3744 3124 struct aspath *aspath;
0b2aa3a0
PJ
3125 int send_as4_path = 0;
3126 int send_as4_aggregator = 0;
3127 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
718e3744 3128
3129 if (! bgp)
75aead62 3130 bgp = peer->bgp;
718e3744 3131
3132 /* Remember current pointer. */
9985f83c 3133 cp = stream_get_endp (s);
718e3744 3134
8a92a8a0 3135 if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) &&
343e90c3 3136 !peer_cap_enhe(peer, afi, safi)))
8c71e481 3137 {
93b73dfa
LB
3138 size_t mpattrlen_pos = 0;
3139
2b26882d 3140 mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi, vecarr, attr);
adbac85e 3141 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag,
b18825eb 3142 addpath_encode, addpath_tx_id, attr);
8c71e481
PM
3143 bgp_packet_mpattr_end(s, mpattrlen_pos);
3144 }
3145
718e3744 3146 /* Origin attribute. */
3147 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3148 stream_putc (s, BGP_ATTR_ORIGIN);
3149 stream_putc (s, 1);
3150 stream_putc (s, attr->origin);
3151
3152 /* AS path attribute. */
3153
3154 /* If remote-peer is EBGP */
6d85b15b 3155 if (peer->sort == BGP_PEER_EBGP
718e3744 3156 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
fe69a505 3157 || attr->aspath->segments == NULL)
fee0f4c6 3158 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
718e3744 3159 {
3160 aspath = aspath_dup (attr->aspath);
3161
66b199b2
DS
3162 /* Even though we may not be configured for confederations we may have
3163 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3164 aspath = aspath_delete_confed_seq (aspath);
3165
718e3744 3166 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
3167 {
66b199b2 3168 /* Stuff our path CONFED_ID on the front */
718e3744 3169 aspath = aspath_add_seq (aspath, bgp->confed_id);
3170 }
3171 else
3172 {
9d3f9705
AC
3173 if (peer->change_local_as) {
3174 /* If replace-as is specified, we only use the change_local_as when
3175 advertising routes. */
3176 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
3177 aspath = aspath_add_seq (aspath, peer->local_as);
3178 }
718e3744 3179 aspath = aspath_add_seq (aspath, peer->change_local_as);
9d3f9705
AC
3180 } else {
3181 aspath = aspath_add_seq (aspath, peer->local_as);
3182 }
718e3744 3183 }
3184 }
6d85b15b 3185 else if (peer->sort == BGP_PEER_CONFED)
718e3744 3186 {
3187 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
3188 aspath = aspath_dup (attr->aspath);
3189 aspath = aspath_add_confed_seq (aspath, peer->local_as);
3190 }
3191 else
3192 aspath = attr->aspath;
3193
0b2aa3a0
PJ
3194 /* If peer is not AS4 capable, then:
3195 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3196 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
3197 * types are in it (i.e. exclude them if they are there)
3198 * AND do this only if there is at least one asnum > 65535 in the path!
3199 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
3200 * all ASnums > 65535 to BGP_AS_TRANS
3201 */
3202
3203 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3204 stream_putc (s, BGP_ATTR_AS_PATH);
3205 aspath_sizep = stream_get_endp (s);
3206 stream_putw (s, 0);
3207 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
3208
3209 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3210 * in the path
3211 */
3212 if (!use32bit && aspath_has_as4 (aspath))
3213 send_as4_path = 1; /* we'll do this later, at the correct place */
3214
718e3744 3215 /* Nexthop attribute. */
343e90c3 3216 if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer, afi, safi))
718e3744 3217 {
8a92a8a0
DS
3218 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
3219 {
3220 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3221 stream_putc (s, BGP_ATTR_NEXT_HOP);
3222 bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
3223 stream_putc (s, 4);
3224 stream_put_ipv4 (s, attr->nexthop.s_addr);
3225 }
343e90c3 3226 else if (peer_cap_enhe(from, afi, safi))
8a92a8a0
DS
3227 {
3228 /*
3229 * Likely this is the case when an IPv4 prefix was received with
3230 * Extended Next-hop capability and now being advertised to
3231 * non-ENHE peers.
3232 * Setting the mandatory (ipv4) next-hop attribute here to enable
3233 * implicit next-hop self with correct (ipv4 address family).
3234 */
3235 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3236 stream_putc (s, BGP_ATTR_NEXT_HOP);
3237 bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, NULL);
3238 stream_putc (s, 4);
3239 stream_put_ipv4 (s, 0);
3240 }
718e3744 3241 }
3242
3243 /* MED attribute. */
abc920f8
DS
3244 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) ||
3245 bgp->maxmed_active)
718e3744 3246 {
3247 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3248 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3249 stream_putc (s, 4);
abc920f8 3250 stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med));
718e3744 3251 }
3252
3253 /* Local preference. */
6d85b15b
JBD
3254 if (peer->sort == BGP_PEER_IBGP ||
3255 peer->sort == BGP_PEER_CONFED)
718e3744 3256 {
3257 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3258 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3259 stream_putc (s, 4);
3260 stream_putl (s, attr->local_pref);
3261 }
3262
3263 /* Atomic aggregate. */
3264 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3265 {
3266 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3267 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3268 stream_putc (s, 0);
3269 }
3270
3271 /* Aggregator. */
3272 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3273 {
fb982c25 3274 assert (attr->extra);
0b2aa3a0
PJ
3275
3276 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
718e3744 3277 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3278 stream_putc (s, BGP_ATTR_AGGREGATOR);
0b2aa3a0
PJ
3279
3280 if (use32bit)
3281 {
3282 /* AS4 capable peer */
3283 stream_putc (s, 8);
3284 stream_putl (s, attr->extra->aggregator_as);
3285 }
3286 else
3287 {
3288 /* 2-byte AS peer */
3289 stream_putc (s, 6);
3290
3291 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
3292 if ( attr->extra->aggregator_as > 65535 )
3293 {
3294 stream_putw (s, BGP_AS_TRANS);
3295
3296 /* we have to send AS4_AGGREGATOR, too.
3297 * we'll do that later in order to send attributes in ascending
3298 * order.
3299 */
3300 send_as4_aggregator = 1;
3301 }
3302 else
3303 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
3304 }
fb982c25 3305 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
718e3744 3306 }
3307
3308 /* Community attribute. */
3309 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
3310 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
3311 {
3312 if (attr->community->size * 4 > 255)
3313 {
3314 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3315 stream_putc (s, BGP_ATTR_COMMUNITIES);
3316 stream_putw (s, attr->community->size * 4);
3317 }
3318 else
3319 {
3320 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3321 stream_putc (s, BGP_ATTR_COMMUNITIES);
3322 stream_putc (s, attr->community->size * 4);
3323 }
3324 stream_put (s, attr->community->val, attr->community->size * 4);
3325 }
3326
57d187bc
JS
3327 /*
3328 * Large Community attribute.
3329 */
3330 if (attr->extra &&
3331 CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)
3332 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)))
3333 {
3334 if (attr->extra->lcommunity->size * 12 > 255)
2acb4ac2
DL
3335 {
3336 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3337 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
3338 stream_putw (s, attr->extra->lcommunity->size * 12);
3339 }
57d187bc 3340 else
2acb4ac2
DL
3341 {
3342 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3343 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
3344 stream_putc (s, attr->extra->lcommunity->size * 12);
3345 }
57d187bc
JS
3346 stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
3347 }
3348
718e3744 3349 /* Route Reflector. */
6d85b15b 3350 if (peer->sort == BGP_PEER_IBGP
718e3744 3351 && from
6d85b15b 3352 && from->sort == BGP_PEER_IBGP)
718e3744 3353 {
3354 /* Originator ID. */
3355 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3356 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
3357 stream_putc (s, 4);
3358
3359 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
fb982c25 3360 stream_put_in_addr (s, &attr->extra->originator_id);
34c3f81b
PJ
3361 else
3362 stream_put_in_addr (s, &from->remote_id);
718e3744 3363
3364 /* Cluster list. */
3365 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3366 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
3367
9eda90ce 3368 if (attr->extra && attr->extra->cluster)
718e3744 3369 {
fb982c25 3370 stream_putc (s, attr->extra->cluster->length + 4);
718e3744 3371 /* If this peer configuration's parent BGP has cluster_id. */
3372 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
3373 stream_put_in_addr (s, &bgp->cluster_id);
3374 else
3375 stream_put_in_addr (s, &bgp->router_id);
fb982c25
PJ
3376 stream_put (s, attr->extra->cluster->list,
3377 attr->extra->cluster->length);
718e3744 3378 }
3379 else
3380 {
3381 stream_putc (s, 4);
3382 /* If this peer configuration's parent BGP has cluster_id. */
3383 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
3384 stream_put_in_addr (s, &bgp->cluster_id);
3385 else
3386 stream_put_in_addr (s, &bgp->router_id);
3387 }
3388 }
3389
718e3744 3390 /* Extended Communities attribute. */
3391 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
3392 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
3393 {
fb982c25
PJ
3394 struct attr_extra *attre = attr->extra;
3395
3396 assert (attre);
3397
6d85b15b
JBD
3398 if (peer->sort == BGP_PEER_IBGP
3399 || peer->sort == BGP_PEER_CONFED)
718e3744 3400 {
fb982c25 3401 if (attre->ecommunity->size * 8 > 255)
4372df71 3402 {
3403 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3404 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
fb982c25 3405 stream_putw (s, attre->ecommunity->size * 8);
4372df71 3406 }
3407 else
3408 {
3409 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3410 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
fb982c25 3411 stream_putc (s, attre->ecommunity->size * 8);
4372df71 3412 }
fb982c25 3413 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
718e3744 3414 }
3415 else
3416 {
5228ad27 3417 u_int8_t *pnt;
4372df71 3418 int tbit;
3419 int ecom_tr_size = 0;
3420 int i;
3421
fb982c25 3422 for (i = 0; i < attre->ecommunity->size; i++)
4372df71 3423 {
fb982c25 3424 pnt = attre->ecommunity->val + (i * 8);
4372df71 3425 tbit = *pnt;
3426
3427 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
3428 continue;
3429
3430 ecom_tr_size++;
3431 }
3432
3433 if (ecom_tr_size)
3434 {
3435 if (ecom_tr_size * 8 > 255)
3436 {
3437 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3438 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
3439 stream_putw (s, ecom_tr_size * 8);
3440 }
3441 else
3442 {
3443 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3444 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
3445 stream_putc (s, ecom_tr_size * 8);
3446 }
3447
fb982c25 3448 for (i = 0; i < attre->ecommunity->size; i++)
4372df71 3449 {
fb982c25 3450 pnt = attre->ecommunity->val + (i * 8);
4372df71 3451 tbit = *pnt;
3452
3453 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
3454 continue;
3455
3456 stream_put (s, pnt, 8);
3457 }
3458 }
718e3744 3459 }
718e3744 3460 }
0b2aa3a0 3461
6cf48acc
VV
3462 /* Label index attribute. */
3463 if (safi == SAFI_LABELED_UNICAST)
3464 {
c5a543b4 3465 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))
6cf48acc
VV
3466 {
3467 u_int32_t label_index;
3468
3469 assert (attr->extra);
3470 label_index = attr->extra->label_index;
c5a543b4
DW
3471
3472 if (label_index != BGP_INVALID_LABEL_INDEX)
3473 {
3474 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3475 stream_putc (s, BGP_ATTR_PREFIX_SID);
3476 stream_putc (s, 10);
3477 stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX);
3478 stream_putw (s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
3479 stream_putc (s, 0); // reserved
3480 stream_putw (s, 0); // flags
3481 stream_putl (s, label_index);
3482 }
6cf48acc
VV
3483 }
3484 }
3485
0b2aa3a0
PJ
3486 if ( send_as4_path )
3487 {
3488 /* If the peer is NOT As4 capable, AND */
3489 /* there are ASnums > 65535 in path THEN
3490 * give out AS4_PATH */
3491
3492 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3493 * path segments!
3494 * Hm, I wonder... confederation things *should* only be at
3495 * the beginning of an aspath, right? Then we should use
3496 * aspath_delete_confed_seq for this, because it is already
3497 * there! (JK)
3498 * Folks, talk to me: what is reasonable here!?
3499 */
3500 aspath = aspath_delete_confed_seq (aspath);
3501
3502 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
3503 stream_putc (s, BGP_ATTR_AS4_PATH);
3504 aspath_sizep = stream_get_endp (s);
3505 stream_putw (s, 0);
3506 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
3507 }
3508
3509 if (aspath != attr->aspath)
3510 aspath_free (aspath);
3511
3512 if ( send_as4_aggregator )
3513 {
3514 assert (attr->extra);
3515
3516 /* send AS4_AGGREGATOR, at this place */
3517 /* this section of code moved here in order to ensure the correct
3518 * *ascending* order of attributes
3519 */
3520 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3521 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
3522 stream_putc (s, 8);
3523 stream_putl (s, attr->extra->aggregator_as);
3524 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
3525 }
587ff0fd 3526
aee875b5
PG
3527 if (((afi == AFI_IP || afi == AFI_IP6) &&
3528 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)) ||
3529 (afi == AFI_L2VPN && safi == SAFI_EVPN))
587ff0fd
LB
3530 {
3531 /* Tunnel Encap attribute */
3532 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
65efcfce
LB
3533
3534#if ENABLE_BGP_VNC
3535 /* VNC attribute */
3536 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC);
3537#endif
587ff0fd
LB
3538 }
3539
718e3744 3540 /* Unknown transit attribute. */
fb982c25
PJ
3541 if (attr->extra && attr->extra->transit)
3542 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
718e3744 3543
3544 /* Return total size of attribute. */
9985f83c 3545 return stream_get_endp (s) - cp;
718e3744 3546}
3547
8c71e481
PM
3548size_t
3549bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
718e3744 3550{
718e3744 3551 unsigned long attrlen_pnt;
b58ed1f8 3552 iana_afi_t pkt_afi;
9cabb64b 3553 safi_t pkt_safi;
718e3744 3554
8c71e481
PM
3555 /* Set extended bit always to encode the attribute length as 2 bytes */
3556 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
718e3744 3557 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
3558
9985f83c 3559 attrlen_pnt = stream_get_endp (s);
8c71e481 3560 stream_putw (s, 0); /* Length of this attribute. */
718e3744 3561
9cabb64b 3562 /* Convert AFI, SAFI to values for packet. */
3563 bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
3564
3565 stream_putw (s, pkt_afi);
3566 stream_putc (s, pkt_safi);
3567
8c71e481
PM
3568 return attrlen_pnt;
3569}
718e3744 3570
8c71e481
PM
3571void
3572bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
3573 afi_t afi, safi_t safi, struct prefix_rd *prd,
adbac85e 3574 u_char *tag, int addpath_encode,
b18825eb 3575 u_int32_t addpath_tx_id, struct attr *attr)
8c71e481 3576{
cd1964ff
DS
3577 u_char wlabel[3] = {0x80, 0x00, 0x00};
3578
3579 if (safi == SAFI_LABELED_UNICAST)
3580 tag = wlabel;
3581
b18825eb
PG
3582 return bgp_packet_mpattr_prefix (s, afi, safi, p, prd,
3583 tag, addpath_encode, addpath_tx_id, attr);
8c71e481 3584}
718e3744 3585
8c71e481
PM
3586void
3587bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
3588{
93b73dfa 3589 bgp_packet_mpattr_end (s, attrlen_pnt);
718e3744 3590}
3591
3592/* Initialization of attribute. */
3593void
fe69a505 3594bgp_attr_init (void)
718e3744 3595{
718e3744 3596 aspath_init ();
3597 attrhash_init ();
3598 community_init ();
3599 ecommunity_init ();
57d187bc 3600 lcommunity_init ();
718e3744 3601 cluster_init ();
3602 transit_init ();
bede7744 3603 encap_init ();
718e3744 3604}
3605
228da428
CC
3606void
3607bgp_attr_finish (void)
3608{
3609 aspath_finish ();
3610 attrhash_finish ();
3611 community_finish ();
3612 ecommunity_finish ();
57d187bc 3613 lcommunity_finish ();
228da428
CC
3614 cluster_finish ();
3615 transit_finish ();
bede7744 3616 encap_finish ();
228da428
CC
3617}
3618
718e3744 3619/* Make attribute packet. */
3620void
a384592f 3621bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3622 struct prefix *prefix)
718e3744 3623{
3624 unsigned long cp;
3625 unsigned long len;
0b2aa3a0 3626 size_t aspath_lenp;
718e3744 3627 struct aspath *aspath;
adbac85e
DW
3628 int addpath_encode = 0;
3629 u_int32_t addpath_tx_id = 0;
718e3744 3630
3631 /* Remember current pointer. */
9985f83c 3632 cp = stream_get_endp (s);
718e3744 3633
3634 /* Place holder of length. */
3635 stream_putw (s, 0);
3636
3637 /* Origin attribute. */
3638 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3639 stream_putc (s, BGP_ATTR_ORIGIN);
3640 stream_putc (s, 1);
3641 stream_putc (s, attr->origin);
3642
3643 aspath = attr->aspath;
0b2aa3a0
PJ
3644
3645 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3646 stream_putc (s, BGP_ATTR_AS_PATH);
3647 aspath_lenp = stream_get_endp (s);
3648 stream_putw (s, 0);
3649
3650 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
718e3744 3651
3652 /* Nexthop attribute. */
a384592f 3653 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
56c1f7d8 3654 if(prefix != NULL && prefix->family != AF_INET6)
a384592f 3655 {
3656 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3657 stream_putc (s, BGP_ATTR_NEXT_HOP);
3658 stream_putc (s, 4);
3659 stream_put_ipv4 (s, attr->nexthop.s_addr);
3660 }
718e3744 3661
3662 /* MED attribute. */
3663 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3664 {
3665 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3666 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3667 stream_putc (s, 4);
3668 stream_putl (s, attr->med);
3669 }
3670
3671 /* Local preference. */
3672 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3673 {
3674 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3675 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3676 stream_putc (s, 4);
3677 stream_putl (s, attr->local_pref);
3678 }
3679
3680 /* Atomic aggregate. */
3681 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3682 {
3683 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3684 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3685 stream_putc (s, 0);
3686 }
3687
3688 /* Aggregator. */
3689 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3690 {
fb982c25 3691 assert (attr->extra);
718e3744 3692 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3693 stream_putc (s, BGP_ATTR_AGGREGATOR);
0b2aa3a0
PJ
3694 stream_putc (s, 8);
3695 stream_putl (s, attr->extra->aggregator_as);
fb982c25 3696 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
718e3744 3697 }
3698
3699 /* Community attribute. */
3700 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3701 {
3702 if (attr->community->size * 4 > 255)
3703 {
3704 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3705 stream_putc (s, BGP_ATTR_COMMUNITIES);
3706 stream_putw (s, attr->community->size * 4);
3707 }
3708 else
3709 {
3710 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3711 stream_putc (s, BGP_ATTR_COMMUNITIES);
3712 stream_putc (s, attr->community->size * 4);
3713 }
3714 stream_put (s, attr->community->val, attr->community->size * 4);
3715 }
3716
57d187bc
JS
3717 /* Large Community attribute. */
3718 if (attr->extra && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES))
3719 {
3720 if (attr->extra->lcommunity->size * 12 > 255)
2acb4ac2
DL
3721 {
3722 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3723 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
3724 stream_putw (s, attr->extra->lcommunity->size * 12);
3725 }
57d187bc 3726 else
2acb4ac2
DL
3727 {
3728 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3729 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
3730 stream_putc (s, attr->extra->lcommunity->size * 12);
3731 }
57d187bc
JS
3732
3733 stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
3734 }
3735
a384592f 3736 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
fb982c25 3737 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
801a9bcc
DS
3738 (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL ||
3739 attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) )
a384592f 3740 {
3741 int sizep;
fb982c25
PJ
3742 struct attr_extra *attre = attr->extra;
3743
a384592f 3744 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3745 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
9985f83c 3746 sizep = stream_get_endp (s);
a384592f 3747
3748 /* MP header */
fb982c25 3749 stream_putc (s, 0); /* Marker: Attribute length. */
a384592f 3750 stream_putw(s, AFI_IP6); /* AFI */
3751 stream_putc(s, SAFI_UNICAST); /* SAFI */
3752
3753 /* Next hop */
fb982c25 3754 stream_putc(s, attre->mp_nexthop_len);
801a9bcc
DS
3755 stream_put(s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
3756 if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3757 stream_put(s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
a384592f 3758
3759 /* SNPA */
3760 stream_putc(s, 0);
3761
3762 /* Prefix */
adbac85e 3763 stream_put_prefix_addpath (s, prefix, addpath_encode, addpath_tx_id);
a384592f 3764
3765 /* Set MP attribute length. */
9985f83c 3766 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
a384592f 3767 }
a384592f 3768
c5a543b4
DW
3769 /* Prefix SID */
3770 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))
6cf48acc
VV
3771 {
3772 assert (attr->extra);
c5a543b4
DW
3773
3774 if (attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
3775 {
3776 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3777 stream_putc (s, BGP_ATTR_PREFIX_SID);
3778 stream_putc (s, 10);
3779 stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX);
3780 stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
3781 stream_putc (s, 0); // reserved
3782 stream_putw (s, 0); // flags
3783 stream_putl (s, attr->extra->label_index);
3784 }
6cf48acc
VV
3785 }
3786
718e3744 3787 /* Return total size of attribute. */
9985f83c 3788 len = stream_get_endp (s) - cp - 2;
718e3744 3789 stream_putw_at (s, cp, len);
3790}