]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_attr.c
Changes to improve BGP convergence time:
[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
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include <zebra.h>
22
23 #include "linklist.h"
24 #include "prefix.h"
25 #include "memory.h"
26 #include "vector.h"
27 #include "vty.h"
28 #include "stream.h"
29 #include "log.h"
30 #include "hash.h"
31 #include "jhash.h"
32
33 #include "bgpd/bgpd.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_route.h"
36 #include "bgpd/bgp_aspath.h"
37 #include "bgpd/bgp_community.h"
38 #include "bgpd/bgp_debug.h"
39 #include "bgpd/bgp_packet.h"
40 #include "bgpd/bgp_ecommunity.h"
41
42 /* Attribute strings for logging. */
43 static const struct message attr_str [] =
44 {
45 { BGP_ATTR_ORIGIN, "ORIGIN" },
46 { BGP_ATTR_AS_PATH, "AS_PATH" },
47 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
48 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
49 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
50 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
51 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
52 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
53 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
54 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
55 { BGP_ATTR_DPA, "DPA" },
56 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
57 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
58 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
59 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
60 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
61 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
62 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
63 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
64 };
65 static const int attr_str_max = array_size(attr_str);
66
67 static const struct message attr_flag_str[] =
68 {
69 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
70 { BGP_ATTR_FLAG_TRANS, "Transitive" },
71 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
72 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
73 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
74 };
75 static const size_t attr_flag_str_max = array_size(attr_flag_str);
76
77 static struct hash *cluster_hash;
78
79 static void *
80 cluster_hash_alloc (void *p)
81 {
82 struct cluster_list * val = (struct cluster_list *) p;
83 struct cluster_list *cluster;
84
85 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
86 cluster->length = val->length;
87
88 if (cluster->length)
89 {
90 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
91 memcpy (cluster->list, val->list, val->length);
92 }
93 else
94 cluster->list = NULL;
95
96 cluster->refcnt = 0;
97
98 return cluster;
99 }
100
101 /* Cluster list related functions. */
102 static struct cluster_list *
103 cluster_parse (struct in_addr * pnt, int length)
104 {
105 struct cluster_list tmp;
106 struct cluster_list *cluster;
107
108 tmp.length = length;
109 tmp.list = pnt;
110
111 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
112 cluster->refcnt++;
113 return cluster;
114 }
115
116 int
117 cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
118 {
119 int i;
120
121 for (i = 0; i < cluster->length / 4; i++)
122 if (cluster->list[i].s_addr == originator.s_addr)
123 return 1;
124 return 0;
125 }
126
127 static unsigned int
128 cluster_hash_key_make (void *p)
129 {
130 const struct cluster_list *cluster = p;
131
132 return jhash(cluster->list, cluster->length, 0);
133 }
134
135 static int
136 cluster_hash_cmp (const void *p1, const void *p2)
137 {
138 const struct cluster_list * cluster1 = p1;
139 const struct cluster_list * cluster2 = p2;
140
141 return (cluster1->length == cluster2->length &&
142 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
143 }
144
145 static void
146 cluster_free (struct cluster_list *cluster)
147 {
148 if (cluster->list)
149 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
150 XFREE (MTYPE_CLUSTER, cluster);
151 }
152
153 static struct cluster_list *
154 cluster_dup (struct cluster_list *cluster)
155 {
156 struct cluster_list *new;
157
158 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
159 new->length = cluster->length;
160
161 if (cluster->length)
162 {
163 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
164 memcpy (new->list, cluster->list, cluster->length);
165 }
166 else
167 new->list = NULL;
168
169 return new;
170 }
171
172 static struct cluster_list *
173 cluster_intern (struct cluster_list *cluster)
174 {
175 struct cluster_list *find;
176
177 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
178 find->refcnt++;
179
180 return find;
181 }
182
183 void
184 cluster_unintern (struct cluster_list *cluster)
185 {
186 if (cluster->refcnt)
187 cluster->refcnt--;
188
189 if (cluster->refcnt == 0)
190 {
191 hash_release (cluster_hash, cluster);
192 cluster_free (cluster);
193 }
194 }
195
196 static void
197 cluster_init (void)
198 {
199 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
200 }
201
202 static void
203 cluster_finish (void)
204 {
205 hash_free (cluster_hash);
206 cluster_hash = NULL;
207 }
208
209 /* Unknown transit attribute. */
210 static struct hash *transit_hash;
211
212 static void
213 transit_free (struct transit *transit)
214 {
215 if (transit->val)
216 XFREE (MTYPE_TRANSIT_VAL, transit->val);
217 XFREE (MTYPE_TRANSIT, transit);
218 }
219
220 static struct transit *
221 transit_dup (struct transit *transit)
222 {
223 struct transit *new;
224
225 new = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
226 new->length = transit->length;
227 if (new->length)
228 {
229 new->val = XMALLOC (MTYPE_TRANSIT_VAL, transit->length);
230 memcpy (new->val, transit->val, transit->length);
231 }
232 else
233 new->val = NULL;
234
235 return new;
236 }
237
238 static void *
239 transit_hash_alloc (void *p)
240 {
241 /* Transit structure is already allocated. */
242 return p;
243 }
244
245 static struct transit *
246 transit_intern (struct transit *transit)
247 {
248 struct transit *find;
249
250 find = hash_get (transit_hash, transit, transit_hash_alloc);
251 if (find != transit)
252 transit_free (transit);
253 find->refcnt++;
254
255 return find;
256 }
257
258 void
259 transit_unintern (struct transit *transit)
260 {
261 if (transit->refcnt)
262 transit->refcnt--;
263
264 if (transit->refcnt == 0)
265 {
266 hash_release (transit_hash, transit);
267 transit_free (transit);
268 }
269 }
270
271 static unsigned int
272 transit_hash_key_make (void *p)
273 {
274 const struct transit * transit = p;
275
276 return jhash(transit->val, transit->length, 0);
277 }
278
279 static int
280 transit_hash_cmp (const void *p1, const void *p2)
281 {
282 const struct transit * transit1 = p1;
283 const struct transit * transit2 = p2;
284
285 return (transit1->length == transit2->length &&
286 memcmp (transit1->val, transit2->val, transit1->length) == 0);
287 }
288
289 static void
290 transit_init (void)
291 {
292 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
293 }
294
295 static void
296 transit_finish (void)
297 {
298 hash_free (transit_hash);
299 transit_hash = NULL;
300 }
301
302 /* Attribute hash routines. */
303 static struct hash *attrhash;
304
305 static struct attr_extra *
306 bgp_attr_extra_new (void)
307 {
308 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
309 }
310
311 void
312 bgp_attr_extra_free (struct attr *attr)
313 {
314 if (attr->extra)
315 {
316 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
317 attr->extra = NULL;
318 }
319 }
320
321 struct attr_extra *
322 bgp_attr_extra_get (struct attr *attr)
323 {
324 if (!attr->extra)
325 attr->extra = bgp_attr_extra_new();
326 return attr->extra;
327 }
328
329 /* Shallow copy of an attribute
330 * Though, not so shallow that it doesn't copy the contents
331 * of the attr_extra pointed to by 'extra'
332 */
333 void
334 bgp_attr_dup (struct attr *new, struct attr *orig)
335 {
336 struct attr_extra *extra = new->extra;
337
338 *new = *orig;
339 /* if caller provided attr_extra space, use it in any case.
340 *
341 * This is neccesary even if orig->extra equals NULL, because otherwise
342 * memory may be later allocated on the heap by bgp_attr_extra_get.
343 *
344 * That memory would eventually be leaked, because the caller must not
345 * call bgp_attr_extra_free if he provided attr_extra on the stack.
346 */
347 if (extra)
348 {
349 new->extra = extra;
350 memset(new->extra, 0, sizeof(struct attr_extra));
351 if (orig->extra)
352 *new->extra = *orig->extra;
353 }
354 else if (orig->extra)
355 {
356 new->extra = bgp_attr_extra_new();
357 *new->extra = *orig->extra;
358 }
359 }
360
361 void
362 bgp_attr_deep_dup (struct attr *new, struct attr *orig)
363 {
364 if (orig->aspath)
365 new->aspath = aspath_dup(orig->aspath);
366
367 if (orig->community)
368 new->community = community_dup(orig->community);
369
370 if (orig->extra)
371 {
372 if (orig->extra->ecommunity)
373 new->extra->ecommunity = ecommunity_dup(orig->extra->ecommunity);
374 if (orig->extra->cluster)
375 new->extra->cluster = cluster_dup(orig->extra->cluster);
376 if (orig->extra->transit)
377 new->extra->transit = transit_dup(orig->extra->transit);
378 }
379 }
380
381 void
382 bgp_attr_deep_free (struct attr *attr)
383 {
384 if (attr->aspath)
385 aspath_free(attr->aspath);
386
387 if (attr->community)
388 community_free(attr->community);
389
390 if (attr->extra)
391 {
392 if (attr->extra->ecommunity)
393 ecommunity_free(&attr->extra->ecommunity);
394 if (attr->extra->cluster)
395 cluster_free(attr->extra->cluster);
396 if (attr->extra->transit)
397 transit_free(attr->extra->transit);
398 }
399 }
400
401 unsigned long int
402 attr_count (void)
403 {
404 return attrhash->count;
405 }
406
407 unsigned long int
408 attr_unknown_count (void)
409 {
410 return transit_hash->count;
411 }
412
413 unsigned int
414 attrhash_key_make (void *p)
415 {
416 const struct attr *attr = (struct attr *) p;
417 const struct attr_extra *extra = attr->extra;
418 uint32_t key = 0;
419 #define MIX(val) key = jhash_1word(val, key)
420
421 MIX(attr->origin);
422 MIX(attr->nexthop.s_addr);
423 MIX(attr->med);
424 MIX(attr->local_pref);
425
426 key += attr->origin;
427 key += attr->nexthop.s_addr;
428 key += attr->med;
429 key += attr->local_pref;
430
431 if (extra)
432 {
433 MIX(extra->aggregator_as);
434 MIX(extra->aggregator_addr.s_addr);
435 MIX(extra->weight);
436 MIX(extra->mp_nexthop_global_in.s_addr);
437 MIX(extra->originator_id.s_addr);
438 MIX(extra->tag);
439 }
440
441 if (attr->aspath)
442 MIX(aspath_key_make (attr->aspath));
443 if (attr->community)
444 MIX(community_hash_make (attr->community));
445
446 if (extra)
447 {
448 if (extra->ecommunity)
449 MIX(ecommunity_hash_make (extra->ecommunity));
450 if (extra->cluster)
451 MIX(cluster_hash_key_make (extra->cluster));
452 if (extra->transit)
453 MIX(transit_hash_key_make (extra->transit));
454
455 #ifdef HAVE_IPV6
456 MIX(extra->mp_nexthop_len);
457 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
458 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
459 #endif /* HAVE_IPV6 */
460 }
461
462 return key;
463 }
464
465 int
466 attrhash_cmp (const void *p1, const void *p2)
467 {
468 const struct attr * attr1 = p1;
469 const struct attr * attr2 = p2;
470
471 if (attr1->flag == attr2->flag
472 && attr1->origin == attr2->origin
473 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
474 && attr1->aspath == attr2->aspath
475 && attr1->community == attr2->community
476 && attr1->med == attr2->med
477 && attr1->local_pref == attr2->local_pref)
478 {
479 const struct attr_extra *ae1 = attr1->extra;
480 const struct attr_extra *ae2 = attr2->extra;
481
482 if (ae1 && ae2
483 && ae1->aggregator_as == ae2->aggregator_as
484 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
485 && ae1->weight == ae2->weight
486 && ae1->tag == ae2->tag
487 #ifdef HAVE_IPV6
488 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
489 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
490 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
491 #endif /* HAVE_IPV6 */
492 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
493 && ae1->ecommunity == ae2->ecommunity
494 && ae1->cluster == ae2->cluster
495 && ae1->transit == ae2->transit
496 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
497 return 1;
498 else if (ae1 || ae2)
499 return 0;
500 /* neither attribute has extra attributes, so they're same */
501 return 1;
502 }
503 else
504 return 0;
505 }
506
507 static void
508 attrhash_init (void)
509 {
510 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
511 }
512
513 static void
514 attrhash_finish (void)
515 {
516 hash_free (attrhash);
517 attrhash = NULL;
518 }
519
520 static void
521 attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
522 {
523 struct attr *attr = backet->data;
524
525 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
526 inet_ntoa (attr->nexthop), VTY_NEWLINE);
527 }
528
529 void
530 attr_show_all (struct vty *vty)
531 {
532 hash_iterate (attrhash,
533 (void (*)(struct hash_backet *, void *))
534 attr_show_all_iterator,
535 vty);
536 }
537
538 static void *
539 bgp_attr_hash_alloc (void *p)
540 {
541 struct attr * val = (struct attr *) p;
542 struct attr *attr;
543
544 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
545 *attr = *val;
546 if (val->extra)
547 {
548 attr->extra = bgp_attr_extra_new ();
549 *attr->extra = *val->extra;
550 }
551 attr->refcnt = 0;
552 return attr;
553 }
554
555 /* Internet argument attribute. */
556 struct attr *
557 bgp_attr_intern (struct attr *attr)
558 {
559 struct attr *find;
560
561 /* Intern referenced strucutre. */
562 if (attr->aspath)
563 {
564 if (! attr->aspath->refcnt)
565 attr->aspath = aspath_intern (attr->aspath);
566 else
567 attr->aspath->refcnt++;
568 }
569 if (attr->community)
570 {
571 if (! attr->community->refcnt)
572 attr->community = community_intern (attr->community);
573 else
574 attr->community->refcnt++;
575 }
576 if (attr->extra)
577 {
578 struct attr_extra *attre = attr->extra;
579
580 if (attre->ecommunity)
581 {
582 if (! attre->ecommunity->refcnt)
583 attre->ecommunity = ecommunity_intern (attre->ecommunity);
584 else
585 attre->ecommunity->refcnt++;
586
587 }
588 if (attre->cluster)
589 {
590 if (! attre->cluster->refcnt)
591 attre->cluster = cluster_intern (attre->cluster);
592 else
593 attre->cluster->refcnt++;
594 }
595 if (attre->transit)
596 {
597 if (! attre->transit->refcnt)
598 attre->transit = transit_intern (attre->transit);
599 else
600 attre->transit->refcnt++;
601 }
602 }
603
604 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
605 find->refcnt++;
606
607 return find;
608 }
609
610
611 /* Make network statement's attribute. */
612 struct attr *
613 bgp_attr_default_set (struct attr *attr, u_char origin)
614 {
615 memset (attr, 0, sizeof (struct attr));
616 bgp_attr_extra_get (attr);
617
618 attr->origin = origin;
619 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
620 attr->aspath = aspath_empty ();
621 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
622 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
623 attr->extra->tag = 0;
624 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
625 #ifdef HAVE_IPV6
626 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
627 #endif
628
629 return attr;
630 }
631
632
633 /* Make network statement's attribute. */
634 struct attr *
635 bgp_attr_default_intern (u_char origin)
636 {
637 struct attr attr;
638 struct attr *new;
639
640 bgp_attr_default_set(&attr, origin);
641
642 new = bgp_attr_intern (&attr);
643 bgp_attr_extra_free (&attr);
644
645 aspath_unintern (&new->aspath);
646 return new;
647 }
648
649 /* Create the attributes for an aggregate */
650 struct attr *
651 bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
652 struct aspath *aspath,
653 struct community *community, int as_set,
654 u_char atomic_aggregate)
655 {
656 struct attr attr;
657 struct attr *new;
658 struct attr_extra attre;
659
660 memset (&attr, 0, sizeof (struct attr));
661 memset (&attre, 0, sizeof (struct attr_extra));
662 attr.extra = &attre;
663
664 /* Origin attribute. */
665 attr.origin = origin;
666 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
667
668 /* AS path attribute. */
669 if (aspath)
670 attr.aspath = aspath_intern (aspath);
671 else
672 attr.aspath = aspath_empty ();
673 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
674
675 /* Next hop attribute. */
676 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
677
678 if (community)
679 {
680 attr.community = community;
681 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
682 }
683
684 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
685 #ifdef HAVE_IPV6
686 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
687 #endif
688 if (! as_set || atomic_aggregate)
689 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
690 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
691 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
692 attre.aggregator_as = bgp->confed_id;
693 else
694 attre.aggregator_as = bgp->as;
695 attre.aggregator_addr = bgp->router_id;
696
697 new = bgp_attr_intern (&attr);
698
699 aspath_unintern (&new->aspath);
700 return new;
701 }
702
703 /* Unintern just the sub-components of the attr, but not the attr */
704 void
705 bgp_attr_unintern_sub (struct attr *attr)
706 {
707 /* aspath refcount shoud be decrement. */
708 if (attr->aspath)
709 aspath_unintern (&attr->aspath);
710 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
711
712 if (attr->community)
713 community_unintern (&attr->community);
714 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
715
716 if (attr->extra)
717 {
718 if (attr->extra->ecommunity)
719 ecommunity_unintern (&attr->extra->ecommunity);
720 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
721
722 if (attr->extra->cluster)
723 cluster_unintern (attr->extra->cluster);
724 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
725
726 if (attr->extra->transit)
727 transit_unintern (attr->extra->transit);
728 }
729 }
730
731 /* Free bgp attribute and aspath. */
732 void
733 bgp_attr_unintern (struct attr **pattr)
734 {
735 struct attr *attr = *pattr;
736 struct attr *ret;
737 struct attr tmp;
738 struct attr_extra tmp_extra;
739
740 /* Decrement attribute reference. */
741 attr->refcnt--;
742
743 tmp = *attr;
744
745 if (attr->extra)
746 {
747 tmp.extra = &tmp_extra;
748 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
749 }
750
751 /* If reference becomes zero then free attribute object. */
752 if (attr->refcnt == 0)
753 {
754 ret = hash_release (attrhash, attr);
755 assert (ret != NULL);
756 bgp_attr_extra_free (attr);
757 XFREE (MTYPE_ATTR, attr);
758 *pattr = NULL;
759 }
760
761 bgp_attr_unintern_sub (&tmp);
762 }
763
764 void
765 bgp_attr_flush (struct attr *attr)
766 {
767 if (attr->aspath && ! attr->aspath->refcnt)
768 aspath_free (attr->aspath);
769 if (attr->community && ! attr->community->refcnt)
770 community_free (attr->community);
771 if (attr->extra)
772 {
773 struct attr_extra *attre = attr->extra;
774
775 if (attre->ecommunity && ! attre->ecommunity->refcnt)
776 ecommunity_free (&attre->ecommunity);
777 if (attre->cluster && ! attre->cluster->refcnt)
778 cluster_free (attre->cluster);
779 if (attre->transit && ! attre->transit->refcnt)
780 transit_free (attre->transit);
781 }
782 }
783
784 /* Implement draft-scudder-idr-optional-transitive behaviour and
785 * avoid resetting sessions for malformed attributes which are
786 * are partial/optional and hence where the error likely was not
787 * introduced by the sending neighbour.
788 */
789 static bgp_attr_parse_ret_t
790 bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
791 bgp_size_t length)
792 {
793 struct peer *const peer = args->peer;
794 const u_int8_t flags = args->flags;
795 /* startp and length must be special-cased, as whether or not to
796 * send the attribute data with the NOTIFY depends on the error,
797 * the caller therefore signals this with the seperate length argument
798 */
799 u_char *notify_datap = (length > 0 ? args->startp : NULL);
800
801 /* Only relax error handling for eBGP peers */
802 if (peer->sort != BGP_PEER_EBGP)
803 {
804 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
805 notify_datap, length);
806 return BGP_ATTR_PARSE_ERROR;
807
808 }
809
810 /* Adjust the stream getp to the end of the attribute, in case we can
811 * still proceed but the caller hasn't read all the attribute.
812 */
813 stream_set_getp (BGP_INPUT (peer),
814 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
815 + args->total);
816
817 switch (args->type) {
818 /* where an attribute is relatively inconsequential, e.g. it does not
819 * affect route selection, and can be safely ignored, then any such
820 * attributes which are malformed should just be ignored and the route
821 * processed as normal.
822 */
823 case BGP_ATTR_AS4_AGGREGATOR:
824 case BGP_ATTR_AGGREGATOR:
825 case BGP_ATTR_ATOMIC_AGGREGATE:
826 return BGP_ATTR_PARSE_PROCEED;
827
828 /* Core attributes, particularly ones which may influence route
829 * selection, should always cause session resets
830 */
831 case BGP_ATTR_ORIGIN:
832 case BGP_ATTR_AS_PATH:
833 case BGP_ATTR_NEXT_HOP:
834 case BGP_ATTR_MULTI_EXIT_DISC:
835 case BGP_ATTR_LOCAL_PREF:
836 case BGP_ATTR_COMMUNITIES:
837 case BGP_ATTR_ORIGINATOR_ID:
838 case BGP_ATTR_CLUSTER_LIST:
839 case BGP_ATTR_MP_REACH_NLRI:
840 case BGP_ATTR_MP_UNREACH_NLRI:
841 case BGP_ATTR_EXT_COMMUNITIES:
842 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
843 notify_datap, length);
844 return BGP_ATTR_PARSE_ERROR;
845 }
846
847 /* Partial optional attributes that are malformed should not cause
848 * the whole session to be reset. Instead treat it as a withdrawal
849 * of the routes, if possible.
850 */
851 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
852 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
853 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
854 return BGP_ATTR_PARSE_WITHDRAW;
855
856 /* default to reset */
857 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
858 }
859
860 /* Find out what is wrong with the path attribute flag bits and log the error.
861 "Flag bits" here stand for Optional, Transitive and Partial, but not for
862 Extended Length. Checking O/T/P bits at once implies, that the attribute
863 being diagnosed is defined by RFC as either a "well-known" or an "optional,
864 non-transitive" attribute. */
865 static void
866 bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
867 u_int8_t desired_flags /* how RFC says it must be */
868 )
869 {
870 u_char seen = 0, i;
871 u_char real_flags = args->flags;
872 const u_int8_t attr_code = args->type;
873
874 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
875 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
876 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
877 if
878 (
879 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
880 CHECK_FLAG (real_flags, attr_flag_str[i].key)
881 )
882 {
883 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
884 LOOKUP (attr_str, attr_code),
885 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
886 attr_flag_str[i].str);
887 seen = 1;
888 }
889 if (!seen)
890 {
891 zlog (args->peer->log, LOG_DEBUG,
892 "Strange, %s called for attr %s, but no problem found with flags"
893 " (real flags 0x%x, desired 0x%x)",
894 __func__, LOOKUP (attr_str, attr_code),
895 real_flags, desired_flags);
896 }
897 }
898
899 /* Required flags for attributes. EXTLEN will be masked off when testing,
900 * as will PARTIAL for optional+transitive attributes.
901 */
902 const u_int8_t attr_flags_values [] = {
903 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
904 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
905 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
906 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
907 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
908 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
909 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
910 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
911 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
912 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
913 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
914 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
915 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
916 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
917 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
918 };
919 static const size_t attr_flags_values_max =
920 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
921
922 static int
923 bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
924 {
925 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
926 const u_int8_t flags = args->flags;
927 const u_int8_t attr_code = args->type;
928 struct peer *const peer = args->peer;
929
930 /* there may be attributes we don't know about */
931 if (attr_code > attr_flags_values_max)
932 return 0;
933 if (attr_flags_values[attr_code] == 0)
934 return 0;
935
936 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
937 * 1."
938 */
939 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
940 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
941 {
942 zlog (peer->log, LOG_ERR,
943 "%s well-known attributes must have transitive flag set (%x)",
944 LOOKUP (attr_str, attr_code), flags);
945 return 1;
946 }
947
948 /* "For well-known attributes and for optional non-transitive attributes,
949 * the Partial bit MUST be set to 0."
950 */
951 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
952 {
953 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
954 {
955 zlog (peer->log, LOG_ERR,
956 "%s well-known attribute "
957 "must NOT have the partial flag set (%x)",
958 LOOKUP (attr_str, attr_code), flags);
959 return 1;
960 }
961 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
962 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
963 {
964 zlog (peer->log, LOG_ERR,
965 "%s optional + transitive attribute "
966 "must NOT have the partial flag set (%x)",
967 LOOKUP (attr_str, attr_code), flags);
968 return 1;
969 }
970 }
971
972 /* Optional transitive attributes may go through speakers that don't
973 * reocgnise them and set the Partial bit.
974 */
975 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
976 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
977 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
978
979 if ((flags & ~mask)
980 == attr_flags_values[attr_code])
981 return 0;
982
983 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
984 return 1;
985 }
986
987 /* Get origin attribute of the update message. */
988 static bgp_attr_parse_ret_t
989 bgp_attr_origin (struct bgp_attr_parser_args *args)
990 {
991 struct peer *const peer = args->peer;
992 struct attr *const attr = args->attr;
993 const bgp_size_t length = args->length;
994
995 /* If any recognized attribute has Attribute Length that conflicts
996 with the expected length (based on the attribute type code), then
997 the Error Subcode is set to Attribute Length Error. The Data
998 field contains the erroneous attribute (type, length and
999 value). */
1000 if (length != 1)
1001 {
1002 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1003 length);
1004 return bgp_attr_malformed (args,
1005 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1006 args->total);
1007 }
1008
1009 /* Fetch origin attribute. */
1010 attr->origin = stream_getc (BGP_INPUT (peer));
1011
1012 /* If the ORIGIN attribute has an undefined value, then the Error
1013 Subcode is set to Invalid Origin Attribute. The Data field
1014 contains the unrecognized attribute (type, length and value). */
1015 if ((attr->origin != BGP_ORIGIN_IGP)
1016 && (attr->origin != BGP_ORIGIN_EGP)
1017 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1018 {
1019 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1020 attr->origin);
1021 return bgp_attr_malformed (args,
1022 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1023 args->total);
1024 }
1025
1026 /* Set oring attribute flag. */
1027 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1028
1029 return 0;
1030 }
1031
1032 /* Parse AS path information. This function is wrapper of
1033 aspath_parse. */
1034 static int
1035 bgp_attr_aspath (struct bgp_attr_parser_args *args)
1036 {
1037 struct attr *const attr = args->attr;
1038 struct peer *const peer = args->peer;
1039 const bgp_size_t length = args->length;
1040
1041 /*
1042 * peer with AS4 => will get 4Byte ASnums
1043 * otherwise, will get 16 Bit
1044 */
1045 attr->aspath = aspath_parse (peer->ibuf, length,
1046 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1047
1048 /* In case of IBGP, length will be zero. */
1049 if (! attr->aspath)
1050 {
1051 zlog (peer->log, LOG_ERR,
1052 "Malformed AS path from %s, length is %d",
1053 peer->host, length);
1054 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
1055 }
1056
1057 /* Set aspath attribute flag. */
1058 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
1059
1060 return BGP_ATTR_PARSE_PROCEED;
1061 }
1062
1063 static bgp_attr_parse_ret_t
1064 bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
1065 {
1066 /* These checks were part of bgp_attr_aspath, but with
1067 * as4 we should to check aspath things when
1068 * aspath synthesizing with as4_path has already taken place.
1069 * Otherwise we check ASPATH and use the synthesized thing, and that is
1070 * not right.
1071 * So do the checks later, i.e. here
1072 */
1073 struct bgp *bgp = peer->bgp;
1074 struct aspath *aspath;
1075
1076 /* Confederation sanity check. */
1077 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1078 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
1079 {
1080 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
1081 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1082 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1083 return BGP_ATTR_PARSE_ERROR;
1084 }
1085
1086 /* First AS check for EBGP. */
1087 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1088 {
1089 if (peer->sort == BGP_PEER_EBGP
1090 && ! aspath_firstas_check (attr->aspath, peer->as))
1091 {
1092 zlog (peer->log, LOG_ERR,
1093 "%s incorrect first AS (must be %u)", peer->host, peer->as);
1094 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1095 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1096 return BGP_ATTR_PARSE_ERROR;
1097 }
1098 }
1099
1100 /* local-as prepend */
1101 if (peer->change_local_as &&
1102 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1103 {
1104 aspath = aspath_dup (attr->aspath);
1105 aspath = aspath_add_seq (aspath, peer->change_local_as);
1106 aspath_unintern (&attr->aspath);
1107 attr->aspath = aspath_intern (aspath);
1108 }
1109
1110 return BGP_ATTR_PARSE_PROCEED;
1111 }
1112
1113 /* Parse AS4 path information. This function is another wrapper of
1114 aspath_parse. */
1115 static int
1116 bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
1117 {
1118 struct peer *const peer = args->peer;
1119 struct attr *const attr = args->attr;
1120 const bgp_size_t length = args->length;
1121
1122 *as4_path = aspath_parse (peer->ibuf, length, 1);
1123
1124 /* In case of IBGP, length will be zero. */
1125 if (!*as4_path)
1126 {
1127 zlog (peer->log, LOG_ERR,
1128 "Malformed AS4 path from %s, length is %d",
1129 peer->host, length);
1130 return bgp_attr_malformed (args,
1131 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1132 0);
1133 }
1134
1135 /* Set aspath attribute flag. */
1136 if (as4_path)
1137 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1138
1139 return BGP_ATTR_PARSE_PROCEED;
1140 }
1141
1142 /* Nexthop attribute. */
1143 static bgp_attr_parse_ret_t
1144 bgp_attr_nexthop (struct bgp_attr_parser_args *args)
1145 {
1146 struct peer *const peer = args->peer;
1147 struct attr *const attr = args->attr;
1148 const bgp_size_t length = args->length;
1149
1150 in_addr_t nexthop_h, nexthop_n;
1151
1152 /* Check nexthop attribute length. */
1153 if (length != 4)
1154 {
1155 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1156 length);
1157
1158 return bgp_attr_malformed (args,
1159 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1160 args->total);
1161 }
1162
1163 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1164 attribute must result in a NOTIFICATION message (this is implemented below).
1165 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1166 logged locally (this is implemented somewhere else). The UPDATE message
1167 gets ignored in any of these cases. */
1168 nexthop_n = stream_get_ipv4 (peer->ibuf);
1169 nexthop_h = ntohl (nexthop_n);
1170 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1171 {
1172 char buf[INET_ADDRSTRLEN];
1173 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
1174 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
1175 return bgp_attr_malformed (args,
1176 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
1177 args->total);
1178 }
1179
1180 attr->nexthop.s_addr = nexthop_n;
1181 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1182
1183 return BGP_ATTR_PARSE_PROCEED;
1184 }
1185
1186 /* MED atrribute. */
1187 static bgp_attr_parse_ret_t
1188 bgp_attr_med (struct bgp_attr_parser_args *args)
1189 {
1190 struct peer *const peer = args->peer;
1191 struct attr *const attr = args->attr;
1192 const bgp_size_t length = args->length;
1193
1194 /* Length check. */
1195 if (length != 4)
1196 {
1197 zlog (peer->log, LOG_ERR,
1198 "MED attribute length isn't four [%d]", length);
1199
1200 return bgp_attr_malformed (args,
1201 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1202 args->total);
1203 }
1204
1205 attr->med = stream_getl (peer->ibuf);
1206
1207 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1208
1209 return BGP_ATTR_PARSE_PROCEED;
1210 }
1211
1212 /* Local preference attribute. */
1213 static bgp_attr_parse_ret_t
1214 bgp_attr_local_pref (struct bgp_attr_parser_args *args)
1215 {
1216 struct peer *const peer = args->peer;
1217 struct attr *const attr = args->attr;
1218 const bgp_size_t length = args->length;
1219
1220 /* Length check. */
1221 if (length != 4)
1222 {
1223 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1224 length);
1225 return bgp_attr_malformed (args,
1226 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1227 args->total);
1228 }
1229
1230 /* If it is contained in an UPDATE message that is received from an
1231 external peer, then this attribute MUST be ignored by the
1232 receiving speaker. */
1233 if (peer->sort == BGP_PEER_EBGP)
1234 {
1235 stream_forward_getp (peer->ibuf, length);
1236 return BGP_ATTR_PARSE_PROCEED;
1237 }
1238
1239 attr->local_pref = stream_getl (peer->ibuf);
1240
1241 /* Set atomic aggregate flag. */
1242 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1243
1244 return BGP_ATTR_PARSE_PROCEED;
1245 }
1246
1247 /* Atomic aggregate. */
1248 static int
1249 bgp_attr_atomic (struct bgp_attr_parser_args *args)
1250 {
1251 struct peer *const peer = args->peer;
1252 struct attr *const attr = args->attr;
1253 const bgp_size_t length = args->length;
1254
1255 /* Length check. */
1256 if (length != 0)
1257 {
1258 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1259 length);
1260 return bgp_attr_malformed (args,
1261 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1262 args->total);
1263 }
1264
1265 /* Set atomic aggregate flag. */
1266 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1267
1268 return BGP_ATTR_PARSE_PROCEED;
1269 }
1270
1271 /* Aggregator attribute */
1272 static int
1273 bgp_attr_aggregator (struct bgp_attr_parser_args *args)
1274 {
1275 struct peer *const peer = args->peer;
1276 struct attr *const attr = args->attr;
1277 const bgp_size_t length = args->length;
1278
1279 int wantedlen = 6;
1280 struct attr_extra *attre = bgp_attr_extra_get (attr);
1281
1282 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1283 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1284 wantedlen = 8;
1285
1286 if (length != wantedlen)
1287 {
1288 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1289 wantedlen, length);
1290 return bgp_attr_malformed (args,
1291 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1292 args->total);
1293 }
1294
1295 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1296 attre->aggregator_as = stream_getl (peer->ibuf);
1297 else
1298 attre->aggregator_as = stream_getw (peer->ibuf);
1299 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
1300
1301 /* Set atomic aggregate flag. */
1302 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1303
1304 return BGP_ATTR_PARSE_PROCEED;
1305 }
1306
1307 /* New Aggregator attribute */
1308 static bgp_attr_parse_ret_t
1309 bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1310 as_t *as4_aggregator_as,
1311 struct in_addr *as4_aggregator_addr)
1312 {
1313 struct peer *const peer = args->peer;
1314 struct attr *const attr = args->attr;
1315 const bgp_size_t length = args->length;
1316
1317 if (length != 8)
1318 {
1319 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1320 length);
1321 return bgp_attr_malformed (args,
1322 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1323 0);
1324 }
1325
1326 *as4_aggregator_as = stream_getl (peer->ibuf);
1327 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1328
1329 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1330
1331 return BGP_ATTR_PARSE_PROCEED;
1332 }
1333
1334 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1335 */
1336 static bgp_attr_parse_ret_t
1337 bgp_attr_munge_as4_attrs (struct peer *const peer,
1338 struct attr *const attr,
1339 struct aspath *as4_path, as_t as4_aggregator,
1340 struct in_addr *as4_aggregator_addr)
1341 {
1342 int ignore_as4_path = 0;
1343 struct aspath *newpath;
1344 struct attr_extra *attre = attr->extra;
1345
1346 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1347 {
1348 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1349 * if given.
1350 * It is worth a warning though, because the peer really
1351 * should not send them
1352 */
1353 if (BGP_DEBUG(as4, AS4))
1354 {
1355 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1356 zlog_debug ("[AS4] %s %s AS4_PATH",
1357 peer->host, "AS4 capable peer, yet it sent");
1358
1359 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1360 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1361 peer->host, "AS4 capable peer, yet it sent");
1362 }
1363
1364 return BGP_ATTR_PARSE_PROCEED;
1365 }
1366
1367 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1368 * because that may override AS4_PATH
1369 */
1370 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1371 {
1372 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
1373 {
1374 assert (attre);
1375
1376 /* received both.
1377 * if the as_number in aggregator is not AS_TRANS,
1378 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1379 * and the Aggregator shall be taken as
1380 * info on the aggregating node, and the AS_PATH
1381 * shall be taken as the AS_PATH
1382 * otherwise
1383 * the Aggregator shall be ignored and the
1384 * AS4_AGGREGATOR shall be taken as the
1385 * Aggregating node and the AS_PATH is to be
1386 * constructed "as in all other cases"
1387 */
1388 if (attre->aggregator_as != BGP_AS_TRANS)
1389 {
1390 /* ignore */
1391 if ( BGP_DEBUG(as4, AS4))
1392 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1393 " send AGGREGATOR != AS_TRANS and"
1394 " AS4_AGGREGATOR, so ignore"
1395 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1396 ignore_as4_path = 1;
1397 }
1398 else
1399 {
1400 /* "New_aggregator shall be taken as aggregator" */
1401 attre->aggregator_as = as4_aggregator;
1402 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1403 }
1404 }
1405 else
1406 {
1407 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1408 * That is bogus - but reading the conditions
1409 * we have to handle AS4_AGGREGATOR as if it were
1410 * AGGREGATOR in that case
1411 */
1412 if ( BGP_DEBUG(as4, AS4))
1413 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1414 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1415 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
1416 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
1417 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1418 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1419 }
1420 }
1421
1422 /* need to reconcile NEW_AS_PATH and AS_PATH */
1423 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
1424 {
1425 if (!attr->aspath)
1426 return BGP_ATTR_PARSE_PROCEED;
1427
1428 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1429 aspath_unintern (&attr->aspath);
1430 attr->aspath = aspath_intern (newpath);
1431 }
1432 return BGP_ATTR_PARSE_PROCEED;
1433 }
1434
1435 /* Community attribute. */
1436 static bgp_attr_parse_ret_t
1437 bgp_attr_community (struct bgp_attr_parser_args *args)
1438 {
1439 struct peer *const peer = args->peer;
1440 struct attr *const attr = args->attr;
1441 const bgp_size_t length = args->length;
1442
1443 if (length == 0)
1444 {
1445 attr->community = NULL;
1446 return BGP_ATTR_PARSE_PROCEED;
1447 }
1448
1449 attr->community =
1450 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1451
1452 /* XXX: fix community_parse to use stream API and remove this */
1453 stream_forward_getp (peer->ibuf, length);
1454
1455 if (!attr->community)
1456 return bgp_attr_malformed (args,
1457 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1458 args->total);
1459
1460 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1461
1462 return BGP_ATTR_PARSE_PROCEED;
1463 }
1464
1465 /* Originator ID attribute. */
1466 static bgp_attr_parse_ret_t
1467 bgp_attr_originator_id (struct bgp_attr_parser_args *args)
1468 {
1469 struct peer *const peer = args->peer;
1470 struct attr *const attr = args->attr;
1471 const bgp_size_t length = args->length;
1472
1473 /* Length check. */
1474 if (length != 4)
1475 {
1476 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1477
1478 return bgp_attr_malformed (args,
1479 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1480 args->total);
1481 }
1482
1483 (bgp_attr_extra_get (attr))->originator_id.s_addr
1484 = stream_get_ipv4 (peer->ibuf);
1485
1486 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1487
1488 return BGP_ATTR_PARSE_PROCEED;
1489 }
1490
1491 /* Cluster list attribute. */
1492 static bgp_attr_parse_ret_t
1493 bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
1494 {
1495 struct peer *const peer = args->peer;
1496 struct attr *const attr = args->attr;
1497 const bgp_size_t length = args->length;
1498
1499 /* Check length. */
1500 if (length % 4)
1501 {
1502 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1503
1504 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1505 args->total);
1506 }
1507
1508 (bgp_attr_extra_get (attr))->cluster
1509 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
1510
1511 /* XXX: Fix cluster_parse to use stream API and then remove this */
1512 stream_forward_getp (peer->ibuf, length);
1513
1514 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1515
1516 return BGP_ATTR_PARSE_PROCEED;
1517 }
1518
1519 /* Multiprotocol reachability information parse. */
1520 int
1521 bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1522 struct bgp_nlri *mp_update)
1523 {
1524 afi_t afi;
1525 safi_t safi;
1526 bgp_size_t nlri_len;
1527 size_t start;
1528 int ret;
1529 int num_mp_pfx = 0;
1530 struct stream *s;
1531 struct peer *const peer = args->peer;
1532 struct attr *const attr = args->attr;
1533 const bgp_size_t length = args->length;
1534 struct attr_extra *attre = bgp_attr_extra_get(attr);
1535
1536 /* Set end of packet. */
1537 s = BGP_INPUT(peer);
1538 start = stream_get_getp(s);
1539
1540 /* safe to read statically sized header? */
1541 #define BGP_MP_REACH_MIN_SIZE 5
1542 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1543 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
1544 {
1545 zlog_info ("%s: %s sent invalid length, %lu",
1546 __func__, peer->host, (unsigned long)length);
1547 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1548 }
1549
1550 /* Load AFI, SAFI. */
1551 afi = stream_getw (s);
1552 safi = stream_getc (s);
1553
1554 /* Get nexthop length. */
1555 attre->mp_nexthop_len = stream_getc (s);
1556
1557 if (LEN_LEFT < attre->mp_nexthop_len)
1558 {
1559 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1560 __func__, peer->host, attre->mp_nexthop_len);
1561 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1562 }
1563
1564 /* Nexthop length check. */
1565 switch (attre->mp_nexthop_len)
1566 {
1567 case 4:
1568 stream_get (&attre->mp_nexthop_global_in, s, 4);
1569 /* Probably needed for RFC 2283 */
1570 if (attr->nexthop.s_addr == 0)
1571 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
1572 break;
1573 case 12:
1574 stream_getl (s); /* RD high */
1575 stream_getl (s); /* RD low */
1576 stream_get (&attre->mp_nexthop_global_in, s, 4);
1577 break;
1578 #ifdef HAVE_IPV6
1579 case 16:
1580 stream_get (&attre->mp_nexthop_global, s, 16);
1581 break;
1582 case 32:
1583 stream_get (&attre->mp_nexthop_global, s, 16);
1584 stream_get (&attre->mp_nexthop_local, s, 16);
1585 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
1586 {
1587 char buf1[INET6_ADDRSTRLEN];
1588 char buf2[INET6_ADDRSTRLEN];
1589
1590 if (BGP_DEBUG (update, UPDATE_IN))
1591 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
1592 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
1593 buf1, INET6_ADDRSTRLEN),
1594 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
1595 buf2, INET6_ADDRSTRLEN));
1596
1597 attre->mp_nexthop_len = 16;
1598 }
1599 break;
1600 #endif /* HAVE_IPV6 */
1601 default:
1602 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1603 __func__, peer->host, attre->mp_nexthop_len);
1604 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1605 }
1606
1607 if (!LEN_LEFT)
1608 {
1609 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1610 __func__, peer->host);
1611 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1612 }
1613
1614 {
1615 u_char val;
1616 if ((val = stream_getc (s)))
1617 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1618 peer->host, val);
1619 }
1620
1621 /* must have nrli_len, what is left of the attribute */
1622 nlri_len = LEN_LEFT;
1623 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
1624 {
1625 zlog_info ("%s: (%s) Failed to read NLRI",
1626 __func__, peer->host);
1627 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1628 }
1629
1630 if (safi != SAFI_MPLS_LABELED_VPN)
1631 {
1632 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len,
1633 &num_mp_pfx);
1634 if (ret < 0)
1635 {
1636 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1637 __func__, peer->host);
1638 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1639 }
1640 }
1641
1642 mp_update->afi = afi;
1643 mp_update->safi = safi;
1644 mp_update->nlri = stream_pnt (s);
1645 mp_update->length = nlri_len;
1646
1647 stream_forward_getp (s, nlri_len);
1648
1649 return BGP_ATTR_PARSE_PROCEED;
1650 #undef LEN_LEFT
1651 }
1652
1653 /* Multiprotocol unreachable parse */
1654 int
1655 bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
1656 struct bgp_nlri *mp_withdraw)
1657 {
1658 struct stream *s;
1659 afi_t afi;
1660 safi_t safi;
1661 u_int16_t withdraw_len;
1662 int ret;
1663 int num_mp_pfx = 0;
1664 struct peer *const peer = args->peer;
1665 const bgp_size_t length = args->length;
1666
1667 s = peer->ibuf;
1668
1669 #define BGP_MP_UNREACH_MIN_SIZE 3
1670 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
1671 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1672
1673 afi = stream_getw (s);
1674 safi = stream_getc (s);
1675
1676 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
1677
1678 if (safi != SAFI_MPLS_LABELED_VPN)
1679 {
1680 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len,
1681 &num_mp_pfx);
1682 if (ret < 0)
1683 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1684 }
1685
1686 mp_withdraw->afi = afi;
1687 mp_withdraw->safi = safi;
1688 mp_withdraw->nlri = stream_pnt (s);
1689 mp_withdraw->length = withdraw_len;
1690
1691 stream_forward_getp (s, withdraw_len);
1692
1693 return BGP_ATTR_PARSE_PROCEED;
1694 }
1695
1696 /* Extended Community attribute. */
1697 static bgp_attr_parse_ret_t
1698 bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
1699 {
1700 struct peer *const peer = args->peer;
1701 struct attr *const attr = args->attr;
1702 const bgp_size_t length = args->length;
1703
1704 if (length == 0)
1705 {
1706 if (attr->extra)
1707 attr->extra->ecommunity = NULL;
1708 /* Empty extcomm doesn't seem to be invalid per se */
1709 return BGP_ATTR_PARSE_PROCEED;
1710 }
1711
1712 (bgp_attr_extra_get (attr))->ecommunity =
1713 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1714 /* XXX: fix ecommunity_parse to use stream API */
1715 stream_forward_getp (peer->ibuf, length);
1716
1717 if (!attr->extra->ecommunity)
1718 return bgp_attr_malformed (args,
1719 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1720 args->total);
1721
1722 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1723
1724 return BGP_ATTR_PARSE_PROCEED;
1725 }
1726
1727 /* BGP unknown attribute treatment. */
1728 static bgp_attr_parse_ret_t
1729 bgp_attr_unknown (struct bgp_attr_parser_args *args)
1730 {
1731 bgp_size_t total = args->total;
1732 struct transit *transit;
1733 struct attr_extra *attre;
1734 struct peer *const peer = args->peer;
1735 struct attr *const attr = args->attr;
1736 u_char *const startp = args->startp;
1737 const u_char type = args->type;
1738 const u_char flag = args->flags;
1739 const bgp_size_t length = args->length;
1740
1741
1742 if (BGP_DEBUG (normal, NORMAL))
1743 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1744 peer->host, type, length);
1745
1746 if (BGP_DEBUG (events, EVENTS))
1747 zlog (peer->log, LOG_DEBUG,
1748 "Unknown attribute type %d length %d is received", type, length);
1749
1750 /* Forward read pointer of input stream. */
1751 stream_forward_getp (peer->ibuf, length);
1752
1753 /* If any of the mandatory well-known attributes are not recognized,
1754 then the Error Subcode is set to Unrecognized Well-known
1755 Attribute. The Data field contains the unrecognized attribute
1756 (type, length and value). */
1757 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
1758 {
1759 return bgp_attr_malformed (args,
1760 BGP_NOTIFY_UPDATE_UNREC_ATTR,
1761 args->total);
1762 }
1763
1764 /* Unrecognized non-transitive optional attributes must be quietly
1765 ignored and not passed along to other BGP peers. */
1766 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
1767 return BGP_ATTR_PARSE_PROCEED;
1768
1769 /* If a path with recognized transitive optional attribute is
1770 accepted and passed along to other BGP peers and the Partial bit
1771 in the Attribute Flags octet is set to 1 by some previous AS, it
1772 is not set back to 0 by the current AS. */
1773 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1774
1775 /* Store transitive attribute to the end of attr->transit. */
1776 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
1777 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
1778
1779 transit = attre->transit;
1780
1781 if (transit->val)
1782 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1783 transit->length + total);
1784 else
1785 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1786
1787 memcpy (transit->val + transit->length, startp, total);
1788 transit->length += total;
1789
1790 return BGP_ATTR_PARSE_PROCEED;
1791 }
1792
1793 /* Read attribute of update packet. This function is called from
1794 bgp_update_receive() in bgp_packet.c. */
1795 bgp_attr_parse_ret_t
1796 bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1797 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1798 {
1799 int ret;
1800 u_char flag = 0;
1801 u_char type = 0;
1802 bgp_size_t length;
1803 u_char *startp, *endp;
1804 u_char *attr_endp;
1805 u_char seen[BGP_ATTR_BITMAP_SIZE];
1806 /* we need the as4_path only until we have synthesized the as_path with it */
1807 /* same goes for as4_aggregator */
1808 struct aspath *as4_path = NULL;
1809 as_t as4_aggregator = 0;
1810 struct in_addr as4_aggregator_addr = { 0 };
1811
1812 /* Initialize bitmap. */
1813 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1814
1815 /* End pointer of BGP attribute. */
1816 endp = BGP_INPUT_PNT (peer) + size;
1817
1818 /* Get attributes to the end of attribute length. */
1819 while (BGP_INPUT_PNT (peer) < endp)
1820 {
1821 /* Check remaining length check.*/
1822 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1823 {
1824 /* XXX warning: long int format, int arg (arg 5) */
1825 zlog (peer->log, LOG_WARNING,
1826 "%s: error BGP attribute length %lu is smaller than min len",
1827 peer->host,
1828 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1829
1830 bgp_notify_send (peer,
1831 BGP_NOTIFY_UPDATE_ERR,
1832 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1833 return BGP_ATTR_PARSE_ERROR;
1834 }
1835
1836 /* Fetch attribute flag and type. */
1837 startp = BGP_INPUT_PNT (peer);
1838 /* "The lower-order four bits of the Attribute Flags octet are
1839 unused. They MUST be zero when sent and MUST be ignored when
1840 received." */
1841 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
1842 type = stream_getc (BGP_INPUT (peer));
1843
1844 /* Check whether Extended-Length applies and is in bounds */
1845 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1846 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1847 {
1848 zlog (peer->log, LOG_WARNING,
1849 "%s: Extended length set, but just %lu bytes of attr header",
1850 peer->host,
1851 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1852
1853 bgp_notify_send (peer,
1854 BGP_NOTIFY_UPDATE_ERR,
1855 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1856 return BGP_ATTR_PARSE_ERROR;
1857 }
1858
1859 /* Check extended attribue length bit. */
1860 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1861 length = stream_getw (BGP_INPUT (peer));
1862 else
1863 length = stream_getc (BGP_INPUT (peer));
1864
1865 /* If any attribute appears more than once in the UPDATE
1866 message, then the Error Subcode is set to Malformed Attribute
1867 List. */
1868
1869 if (CHECK_BITMAP (seen, type))
1870 {
1871 zlog (peer->log, LOG_WARNING,
1872 "%s: error BGP attribute type %d appears twice in a message",
1873 peer->host, type);
1874
1875 bgp_notify_send (peer,
1876 BGP_NOTIFY_UPDATE_ERR,
1877 BGP_NOTIFY_UPDATE_MAL_ATTR);
1878 return BGP_ATTR_PARSE_ERROR;
1879 }
1880
1881 /* Set type to bitmap to check duplicate attribute. `type' is
1882 unsigned char so it never overflow bitmap range. */
1883
1884 SET_BITMAP (seen, type);
1885
1886 /* Overflow check. */
1887 attr_endp = BGP_INPUT_PNT (peer) + length;
1888
1889 if (attr_endp > endp)
1890 {
1891 zlog (peer->log, LOG_WARNING,
1892 "%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);
1893 bgp_notify_send (peer,
1894 BGP_NOTIFY_UPDATE_ERR,
1895 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1896 return BGP_ATTR_PARSE_ERROR;
1897 }
1898
1899 struct bgp_attr_parser_args attr_args = {
1900 .peer = peer,
1901 .length = length,
1902 .attr = attr,
1903 .type = type,
1904 .flags = flag,
1905 .startp = startp,
1906 .total = attr_endp - startp,
1907 };
1908
1909
1910 /* If any recognized attribute has Attribute Flags that conflict
1911 with the Attribute Type Code, then the Error Subcode is set to
1912 Attribute Flags Error. The Data field contains the erroneous
1913 attribute (type, length and value). */
1914 if (bgp_attr_flag_invalid (&attr_args))
1915 {
1916 bgp_attr_parse_ret_t ret;
1917 ret = bgp_attr_malformed (&attr_args,
1918 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1919 attr_args.total);
1920 if (ret == BGP_ATTR_PARSE_PROCEED)
1921 continue;
1922 return ret;
1923 }
1924
1925 /* OK check attribute and store it's value. */
1926 switch (type)
1927 {
1928 case BGP_ATTR_ORIGIN:
1929 ret = bgp_attr_origin (&attr_args);
1930 break;
1931 case BGP_ATTR_AS_PATH:
1932 ret = bgp_attr_aspath (&attr_args);
1933 break;
1934 case BGP_ATTR_AS4_PATH:
1935 ret = bgp_attr_as4_path (&attr_args, &as4_path);
1936 break;
1937 case BGP_ATTR_NEXT_HOP:
1938 ret = bgp_attr_nexthop (&attr_args);
1939 break;
1940 case BGP_ATTR_MULTI_EXIT_DISC:
1941 ret = bgp_attr_med (&attr_args);
1942 break;
1943 case BGP_ATTR_LOCAL_PREF:
1944 ret = bgp_attr_local_pref (&attr_args);
1945 break;
1946 case BGP_ATTR_ATOMIC_AGGREGATE:
1947 ret = bgp_attr_atomic (&attr_args);
1948 break;
1949 case BGP_ATTR_AGGREGATOR:
1950 ret = bgp_attr_aggregator (&attr_args);
1951 break;
1952 case BGP_ATTR_AS4_AGGREGATOR:
1953 ret = bgp_attr_as4_aggregator (&attr_args,
1954 &as4_aggregator,
1955 &as4_aggregator_addr);
1956 break;
1957 case BGP_ATTR_COMMUNITIES:
1958 ret = bgp_attr_community (&attr_args);
1959 break;
1960 case BGP_ATTR_ORIGINATOR_ID:
1961 ret = bgp_attr_originator_id (&attr_args);
1962 break;
1963 case BGP_ATTR_CLUSTER_LIST:
1964 ret = bgp_attr_cluster_list (&attr_args);
1965 break;
1966 case BGP_ATTR_MP_REACH_NLRI:
1967 ret = bgp_mp_reach_parse (&attr_args, mp_update);
1968 break;
1969 case BGP_ATTR_MP_UNREACH_NLRI:
1970 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
1971 break;
1972 case BGP_ATTR_EXT_COMMUNITIES:
1973 ret = bgp_attr_ext_communities (&attr_args);
1974 break;
1975 default:
1976 ret = bgp_attr_unknown (&attr_args);
1977 break;
1978 }
1979
1980 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
1981 {
1982 bgp_notify_send (peer,
1983 BGP_NOTIFY_UPDATE_ERR,
1984 BGP_NOTIFY_UPDATE_MAL_ATTR);
1985 ret = BGP_ATTR_PARSE_ERROR;
1986 }
1987
1988 /* If hard error occured immediately return to the caller. */
1989 if (ret == BGP_ATTR_PARSE_ERROR)
1990 {
1991 zlog (peer->log, LOG_WARNING,
1992 "%s: Attribute %s, parse error",
1993 peer->host,
1994 LOOKUP (attr_str, type));
1995 if (as4_path)
1996 aspath_unintern (&as4_path);
1997 return ret;
1998 }
1999 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2000 {
2001
2002 zlog (peer->log, LOG_WARNING,
2003 "%s: Attribute %s, parse error - treating as withdrawal",
2004 peer->host,
2005 LOOKUP (attr_str, type));
2006 if (as4_path)
2007 aspath_unintern (&as4_path);
2008 return ret;
2009 }
2010
2011 /* Check the fetched length. */
2012 if (BGP_INPUT_PNT (peer) != attr_endp)
2013 {
2014 zlog (peer->log, LOG_WARNING,
2015 "%s: BGP attribute %s, fetch error",
2016 peer->host, LOOKUP (attr_str, type));
2017 bgp_notify_send (peer,
2018 BGP_NOTIFY_UPDATE_ERR,
2019 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2020 if (as4_path)
2021 aspath_unintern (&as4_path);
2022 return BGP_ATTR_PARSE_ERROR;
2023 }
2024 }
2025
2026 /* Check final read pointer is same as end pointer. */
2027 if (BGP_INPUT_PNT (peer) != endp)
2028 {
2029 zlog (peer->log, LOG_WARNING,
2030 "%s: BGP attribute %s, length mismatch",
2031 peer->host, LOOKUP (attr_str, type));
2032 bgp_notify_send (peer,
2033 BGP_NOTIFY_UPDATE_ERR,
2034 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2035 if (as4_path)
2036 aspath_unintern (&as4_path);
2037 return BGP_ATTR_PARSE_ERROR;
2038 }
2039
2040 /*
2041 * At this place we can see whether we got AS4_PATH and/or
2042 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2043 * We can not do this before we've read all attributes because
2044 * the as4 handling does not say whether AS4_PATH has to be sent
2045 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2046 * in relationship to AGGREGATOR.
2047 * So, to be defensive, we are not relying on any order and read
2048 * all attributes first, including these 32bit ones, and now,
2049 * afterwards, we look what and if something is to be done for as4.
2050 */
2051 /* actually... this doesn't ever return failure currently, but
2052 * better safe than sorry */
2053 if (bgp_attr_munge_as4_attrs (peer, attr, as4_path,
2054 as4_aggregator, &as4_aggregator_addr))
2055 {
2056 bgp_notify_send (peer,
2057 BGP_NOTIFY_UPDATE_ERR,
2058 BGP_NOTIFY_UPDATE_MAL_ATTR);
2059 if (as4_path)
2060 aspath_unintern (&as4_path);
2061 return BGP_ATTR_PARSE_ERROR;
2062 }
2063
2064 /* At this stage, we have done all fiddling with as4, and the
2065 * resulting info is in attr->aggregator resp. attr->aspath
2066 * so we can chuck as4_aggregator and as4_path alltogether in
2067 * order to save memory
2068 */
2069 if (as4_path)
2070 {
2071 aspath_unintern (&as4_path); /* unintern - it is in the hash */
2072 /* The flag that we got this is still there, but that does not
2073 * do any trouble
2074 */
2075 }
2076 /*
2077 * The "rest" of the code does nothing with as4_aggregator.
2078 * there is no memory attached specifically which is not part
2079 * of the attr.
2080 * so ignoring just means do nothing.
2081 */
2082 /*
2083 * Finally do the checks on the aspath we did not do yet
2084 * because we waited for a potentially synthesized aspath.
2085 */
2086 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
2087 {
2088 ret = bgp_attr_aspath_check (peer, attr);
2089 if (ret != BGP_ATTR_PARSE_PROCEED)
2090 return ret;
2091 }
2092
2093 /* Finally intern unknown attribute. */
2094 if (attr->extra && attr->extra->transit)
2095 attr->extra->transit = transit_intern (attr->extra->transit);
2096
2097 return BGP_ATTR_PARSE_PROCEED;
2098 }
2099
2100 /* Well-known attribute check. */
2101 int
2102 bgp_attr_check (struct peer *peer, struct attr *attr)
2103 {
2104 u_char type = 0;
2105
2106 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2107 type = BGP_ATTR_ORIGIN;
2108
2109 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2110 type = BGP_ATTR_AS_PATH;
2111
2112 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
2113 type = BGP_ATTR_NEXT_HOP;
2114
2115 if (peer->sort == BGP_PEER_IBGP
2116 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2117 type = BGP_ATTR_LOCAL_PREF;
2118
2119 if (type)
2120 {
2121 zlog (peer->log, LOG_WARNING,
2122 "%s Missing well-known attribute %d.",
2123 peer->host, type);
2124 bgp_notify_send_with_data (peer,
2125 BGP_NOTIFY_UPDATE_ERR,
2126 BGP_NOTIFY_UPDATE_MISS_ATTR,
2127 &type, 1);
2128 return BGP_ATTR_PARSE_ERROR;
2129 }
2130 return BGP_ATTR_PARSE_PROCEED;
2131 }
2132
2133 int stream_put_prefix (struct stream *, struct prefix *);
2134
2135 size_t
2136 bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2137 struct attr *attr)
2138 {
2139 size_t sizep;
2140
2141 /* Set extended bit always to encode the attribute length as 2 bytes */
2142 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2143 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2144 sizep = stream_get_endp (s);
2145 stream_putw (s, 0); /* Marker: Attribute length. */
2146 stream_putw (s, afi); /* AFI */
2147 stream_putc (s, safi); /* SAFI */
2148
2149 /* Nexthop */
2150 switch (afi)
2151 {
2152 case AFI_IP:
2153 switch (safi)
2154 {
2155 case SAFI_UNICAST:
2156 case SAFI_MULTICAST:
2157 stream_putc (s, 4);
2158 stream_put_ipv4 (s, attr->nexthop.s_addr);
2159 break;
2160 case SAFI_MPLS_VPN:
2161 stream_putc (s, 12);
2162 stream_putl (s, 0);
2163 stream_putl (s, 0);
2164 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2165 break;
2166 default:
2167 break;
2168 }
2169 break;
2170 #ifdef HAVE_IPV6
2171 case AFI_IP6:
2172 switch (safi)
2173 {
2174 case SAFI_UNICAST:
2175 case SAFI_MULTICAST:
2176 {
2177 unsigned long sizep;
2178 struct attr_extra *attre = attr->extra;
2179
2180 assert (attr->extra);
2181 stream_putc (s, attre->mp_nexthop_len);
2182 stream_put (s, &attre->mp_nexthop_global, 16);
2183 if (attre->mp_nexthop_len == 32)
2184 stream_put (s, &attre->mp_nexthop_local, 16);
2185 }
2186 default:
2187 break;
2188 }
2189 break;
2190 #endif /*HAVE_IPV6*/
2191 default:
2192 break;
2193 }
2194
2195 /* SNPA */
2196 stream_putc (s, 0);
2197 return sizep;
2198 }
2199
2200 void
2201 bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2202 struct prefix *p, struct prefix_rd *prd,
2203 u_char *tag)
2204 {
2205 switch (safi)
2206 {
2207 case SAFI_MPLS_VPN:
2208 /* Tag, RD, Prefix write. */
2209 stream_putc (s, p->prefixlen + 88);
2210 stream_put (s, tag, 3);
2211 stream_put (s, prd->val, 8);
2212 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2213 break;
2214 default:
2215 /* Prefix write. */
2216 stream_put_prefix (s, p);
2217 break;
2218 }
2219 }
2220
2221 void
2222 bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2223 {
2224 /* Set MP attribute length. Don't count the (2) bytes used to encode
2225 the attr length */
2226 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2227 }
2228
2229 /* Make attribute packet. */
2230 bgp_size_t
2231 bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
2232 struct stream *s, struct attr *attr,
2233 struct prefix *p, afi_t afi, safi_t safi,
2234 struct peer *from, struct prefix_rd *prd, u_char *tag)
2235 {
2236 size_t cp;
2237 size_t aspath_sizep;
2238 struct aspath *aspath;
2239 int send_as4_path = 0;
2240 int send_as4_aggregator = 0;
2241 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
2242 size_t mpattrlen_pos = 0;
2243
2244 if (! bgp)
2245 bgp = bgp_get_default ();
2246
2247 /* Remember current pointer. */
2248 cp = stream_get_endp (s);
2249
2250 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2251 {
2252 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2253 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2254 bgp_packet_mpattr_end(s, mpattrlen_pos);
2255 }
2256
2257 /* Origin attribute. */
2258 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2259 stream_putc (s, BGP_ATTR_ORIGIN);
2260 stream_putc (s, 1);
2261 stream_putc (s, attr->origin);
2262
2263 /* AS path attribute. */
2264
2265 /* If remote-peer is EBGP */
2266 if (peer->sort == BGP_PEER_EBGP
2267 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
2268 || attr->aspath->segments == NULL)
2269 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
2270 {
2271 aspath = aspath_dup (attr->aspath);
2272
2273 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2274 {
2275 /* Strip the confed info, and then stuff our path CONFED_ID
2276 on the front */
2277 aspath = aspath_delete_confed_seq (aspath);
2278 aspath = aspath_add_seq (aspath, bgp->confed_id);
2279 }
2280 else
2281 {
2282 if (peer->change_local_as) {
2283 /* If replace-as is specified, we only use the change_local_as when
2284 advertising routes. */
2285 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2286 aspath = aspath_add_seq (aspath, peer->local_as);
2287 }
2288 aspath = aspath_add_seq (aspath, peer->change_local_as);
2289 } else {
2290 aspath = aspath_add_seq (aspath, peer->local_as);
2291 }
2292 }
2293 }
2294 else if (peer->sort == BGP_PEER_CONFED)
2295 {
2296 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2297 aspath = aspath_dup (attr->aspath);
2298 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2299 }
2300 else
2301 aspath = attr->aspath;
2302
2303 /* If peer is not AS4 capable, then:
2304 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2305 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2306 * types are in it (i.e. exclude them if they are there)
2307 * AND do this only if there is at least one asnum > 65535 in the path!
2308 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2309 * all ASnums > 65535 to BGP_AS_TRANS
2310 */
2311
2312 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2313 stream_putc (s, BGP_ATTR_AS_PATH);
2314 aspath_sizep = stream_get_endp (s);
2315 stream_putw (s, 0);
2316 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2317
2318 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2319 * in the path
2320 */
2321 if (!use32bit && aspath_has_as4 (aspath))
2322 send_as4_path = 1; /* we'll do this later, at the correct place */
2323
2324 /* Nexthop attribute. */
2325 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
2326 {
2327 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2328 stream_putc (s, BGP_ATTR_NEXT_HOP);
2329 stream_putc (s, 4);
2330 if (safi == SAFI_MPLS_VPN)
2331 {
2332 if (attr->nexthop.s_addr == 0)
2333 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2334 else
2335 stream_put_ipv4 (s, attr->nexthop.s_addr);
2336 }
2337 else
2338 stream_put_ipv4 (s, attr->nexthop.s_addr);
2339 }
2340
2341 /* MED attribute. */
2342 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) ||
2343 bgp->maxmed_active)
2344 {
2345 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2346 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2347 stream_putc (s, 4);
2348 stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med));
2349 }
2350
2351 /* Local preference. */
2352 if (peer->sort == BGP_PEER_IBGP ||
2353 peer->sort == BGP_PEER_CONFED)
2354 {
2355 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2356 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2357 stream_putc (s, 4);
2358 stream_putl (s, attr->local_pref);
2359 }
2360
2361 /* Atomic aggregate. */
2362 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2363 {
2364 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2365 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2366 stream_putc (s, 0);
2367 }
2368
2369 /* Aggregator. */
2370 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2371 {
2372 assert (attr->extra);
2373
2374 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
2375 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2376 stream_putc (s, BGP_ATTR_AGGREGATOR);
2377
2378 if (use32bit)
2379 {
2380 /* AS4 capable peer */
2381 stream_putc (s, 8);
2382 stream_putl (s, attr->extra->aggregator_as);
2383 }
2384 else
2385 {
2386 /* 2-byte AS peer */
2387 stream_putc (s, 6);
2388
2389 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2390 if ( attr->extra->aggregator_as > 65535 )
2391 {
2392 stream_putw (s, BGP_AS_TRANS);
2393
2394 /* we have to send AS4_AGGREGATOR, too.
2395 * we'll do that later in order to send attributes in ascending
2396 * order.
2397 */
2398 send_as4_aggregator = 1;
2399 }
2400 else
2401 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2402 }
2403 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2404 }
2405
2406 /* Community attribute. */
2407 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2408 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2409 {
2410 if (attr->community->size * 4 > 255)
2411 {
2412 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2413 stream_putc (s, BGP_ATTR_COMMUNITIES);
2414 stream_putw (s, attr->community->size * 4);
2415 }
2416 else
2417 {
2418 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2419 stream_putc (s, BGP_ATTR_COMMUNITIES);
2420 stream_putc (s, attr->community->size * 4);
2421 }
2422 stream_put (s, attr->community->val, attr->community->size * 4);
2423 }
2424
2425 /* Route Reflector. */
2426 if (peer->sort == BGP_PEER_IBGP
2427 && from
2428 && from->sort == BGP_PEER_IBGP)
2429 {
2430 /* Originator ID. */
2431 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2432 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2433 stream_putc (s, 4);
2434
2435 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
2436 stream_put_in_addr (s, &attr->extra->originator_id);
2437 else
2438 stream_put_in_addr (s, &from->remote_id);
2439
2440 /* Cluster list. */
2441 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2442 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2443
2444 if (attr->extra && attr->extra->cluster)
2445 {
2446 stream_putc (s, attr->extra->cluster->length + 4);
2447 /* If this peer configuration's parent BGP has cluster_id. */
2448 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2449 stream_put_in_addr (s, &bgp->cluster_id);
2450 else
2451 stream_put_in_addr (s, &bgp->router_id);
2452 stream_put (s, attr->extra->cluster->list,
2453 attr->extra->cluster->length);
2454 }
2455 else
2456 {
2457 stream_putc (s, 4);
2458 /* If this peer configuration's parent BGP has cluster_id. */
2459 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2460 stream_put_in_addr (s, &bgp->cluster_id);
2461 else
2462 stream_put_in_addr (s, &bgp->router_id);
2463 }
2464 }
2465
2466 /* Extended Communities attribute. */
2467 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2468 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2469 {
2470 struct attr_extra *attre = attr->extra;
2471
2472 assert (attre);
2473
2474 if (peer->sort == BGP_PEER_IBGP
2475 || peer->sort == BGP_PEER_CONFED)
2476 {
2477 if (attre->ecommunity->size * 8 > 255)
2478 {
2479 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2480 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2481 stream_putw (s, attre->ecommunity->size * 8);
2482 }
2483 else
2484 {
2485 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2486 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2487 stream_putc (s, attre->ecommunity->size * 8);
2488 }
2489 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
2490 }
2491 else
2492 {
2493 u_int8_t *pnt;
2494 int tbit;
2495 int ecom_tr_size = 0;
2496 int i;
2497
2498 for (i = 0; i < attre->ecommunity->size; i++)
2499 {
2500 pnt = attre->ecommunity->val + (i * 8);
2501 tbit = *pnt;
2502
2503 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2504 continue;
2505
2506 ecom_tr_size++;
2507 }
2508
2509 if (ecom_tr_size)
2510 {
2511 if (ecom_tr_size * 8 > 255)
2512 {
2513 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2514 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2515 stream_putw (s, ecom_tr_size * 8);
2516 }
2517 else
2518 {
2519 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2520 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2521 stream_putc (s, ecom_tr_size * 8);
2522 }
2523
2524 for (i = 0; i < attre->ecommunity->size; i++)
2525 {
2526 pnt = attre->ecommunity->val + (i * 8);
2527 tbit = *pnt;
2528
2529 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2530 continue;
2531
2532 stream_put (s, pnt, 8);
2533 }
2534 }
2535 }
2536 }
2537
2538 if ( send_as4_path )
2539 {
2540 /* If the peer is NOT As4 capable, AND */
2541 /* there are ASnums > 65535 in path THEN
2542 * give out AS4_PATH */
2543
2544 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2545 * path segments!
2546 * Hm, I wonder... confederation things *should* only be at
2547 * the beginning of an aspath, right? Then we should use
2548 * aspath_delete_confed_seq for this, because it is already
2549 * there! (JK)
2550 * Folks, talk to me: what is reasonable here!?
2551 */
2552 aspath = aspath_delete_confed_seq (aspath);
2553
2554 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2555 stream_putc (s, BGP_ATTR_AS4_PATH);
2556 aspath_sizep = stream_get_endp (s);
2557 stream_putw (s, 0);
2558 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2559 }
2560
2561 if (aspath != attr->aspath)
2562 aspath_free (aspath);
2563
2564 if ( send_as4_aggregator )
2565 {
2566 assert (attr->extra);
2567
2568 /* send AS4_AGGREGATOR, at this place */
2569 /* this section of code moved here in order to ensure the correct
2570 * *ascending* order of attributes
2571 */
2572 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2573 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2574 stream_putc (s, 8);
2575 stream_putl (s, attr->extra->aggregator_as);
2576 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2577 }
2578
2579 /* Unknown transit attribute. */
2580 if (attr->extra && attr->extra->transit)
2581 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
2582
2583 /* Return total size of attribute. */
2584 return stream_get_endp (s) - cp;
2585 }
2586
2587 size_t
2588 bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
2589 {
2590 unsigned long attrlen_pnt;
2591
2592 /* Set extended bit always to encode the attribute length as 2 bytes */
2593 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2594 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2595
2596 attrlen_pnt = stream_get_endp (s);
2597 stream_putw (s, 0); /* Length of this attribute. */
2598
2599 stream_putw (s, afi);
2600 safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi;
2601 stream_putc (s, safi);
2602 return attrlen_pnt;
2603 }
2604
2605 void
2606 bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2607 afi_t afi, safi_t safi, struct prefix_rd *prd,
2608 u_char *tag)
2609 {
2610 if (safi == SAFI_MPLS_VPN)
2611 {
2612 stream_putc (s, p->prefixlen + 88);
2613 stream_put (s, tag, 3);
2614 stream_put (s, prd->val, 8);
2615 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2616 }
2617 else
2618 stream_put_prefix (s, p);
2619 }
2620
2621 void
2622 bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2623 {
2624 bgp_size_t size;
2625
2626 /* Set MP attribute length. Don't count the (2) bytes used to encode
2627 the attr length */
2628 size = stream_get_endp (s) - attrlen_pnt - 2;
2629 stream_putw_at (s, attrlen_pnt, size);
2630 }
2631
2632 /* Initialization of attribute. */
2633 void
2634 bgp_attr_init (void)
2635 {
2636 aspath_init ();
2637 attrhash_init ();
2638 community_init ();
2639 ecommunity_init ();
2640 cluster_init ();
2641 transit_init ();
2642 }
2643
2644 void
2645 bgp_attr_finish (void)
2646 {
2647 aspath_finish ();
2648 attrhash_finish ();
2649 community_finish ();
2650 ecommunity_finish ();
2651 cluster_finish ();
2652 transit_finish ();
2653 }
2654
2655 /* Make attribute packet. */
2656 void
2657 bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2658 struct prefix *prefix)
2659 {
2660 unsigned long cp;
2661 unsigned long len;
2662 size_t aspath_lenp;
2663 struct aspath *aspath;
2664
2665 /* Remember current pointer. */
2666 cp = stream_get_endp (s);
2667
2668 /* Place holder of length. */
2669 stream_putw (s, 0);
2670
2671 /* Origin attribute. */
2672 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2673 stream_putc (s, BGP_ATTR_ORIGIN);
2674 stream_putc (s, 1);
2675 stream_putc (s, attr->origin);
2676
2677 aspath = attr->aspath;
2678
2679 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2680 stream_putc (s, BGP_ATTR_AS_PATH);
2681 aspath_lenp = stream_get_endp (s);
2682 stream_putw (s, 0);
2683
2684 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
2685
2686 /* Nexthop attribute. */
2687 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2688 if(prefix != NULL
2689 #ifdef HAVE_IPV6
2690 && prefix->family != AF_INET6
2691 #endif /* HAVE_IPV6 */
2692 )
2693 {
2694 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2695 stream_putc (s, BGP_ATTR_NEXT_HOP);
2696 stream_putc (s, 4);
2697 stream_put_ipv4 (s, attr->nexthop.s_addr);
2698 }
2699
2700 /* MED attribute. */
2701 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2702 {
2703 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2704 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2705 stream_putc (s, 4);
2706 stream_putl (s, attr->med);
2707 }
2708
2709 /* Local preference. */
2710 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2711 {
2712 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2713 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2714 stream_putc (s, 4);
2715 stream_putl (s, attr->local_pref);
2716 }
2717
2718 /* Atomic aggregate. */
2719 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2720 {
2721 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2722 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2723 stream_putc (s, 0);
2724 }
2725
2726 /* Aggregator. */
2727 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2728 {
2729 assert (attr->extra);
2730 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2731 stream_putc (s, BGP_ATTR_AGGREGATOR);
2732 stream_putc (s, 8);
2733 stream_putl (s, attr->extra->aggregator_as);
2734 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2735 }
2736
2737 /* Community attribute. */
2738 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2739 {
2740 if (attr->community->size * 4 > 255)
2741 {
2742 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2743 stream_putc (s, BGP_ATTR_COMMUNITIES);
2744 stream_putw (s, attr->community->size * 4);
2745 }
2746 else
2747 {
2748 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2749 stream_putc (s, BGP_ATTR_COMMUNITIES);
2750 stream_putc (s, attr->community->size * 4);
2751 }
2752 stream_put (s, attr->community->val, attr->community->size * 4);
2753 }
2754
2755 #ifdef HAVE_IPV6
2756 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
2757 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2758 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
2759 {
2760 int sizep;
2761 struct attr_extra *attre = attr->extra;
2762
2763 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2764 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
2765 sizep = stream_get_endp (s);
2766
2767 /* MP header */
2768 stream_putc (s, 0); /* Marker: Attribute length. */
2769 stream_putw(s, AFI_IP6); /* AFI */
2770 stream_putc(s, SAFI_UNICAST); /* SAFI */
2771
2772 /* Next hop */
2773 stream_putc(s, attre->mp_nexthop_len);
2774 stream_put(s, &attre->mp_nexthop_global, 16);
2775 if (attre->mp_nexthop_len == 32)
2776 stream_put(s, &attre->mp_nexthop_local, 16);
2777
2778 /* SNPA */
2779 stream_putc(s, 0);
2780
2781 /* Prefix */
2782 stream_put_prefix(s, prefix);
2783
2784 /* Set MP attribute length. */
2785 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
2786 }
2787 #endif /* HAVE_IPV6 */
2788
2789 /* Return total size of attribute. */
2790 len = stream_get_endp (s) - cp - 2;
2791 stream_putw_at (s, cp, len);
2792 }