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