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