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