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