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