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