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