]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_attr.c
BGP: add addpath RX support
[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_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_debug ("Strange, %s called for attr %s, but no problem found with flags"
892 " (real flags 0x%x, desired 0x%x)",
893 __func__, LOOKUP (attr_str, attr_code),
894 real_flags, desired_flags);
895 }
896 }
897
898 /* Required flags for attributes. EXTLEN will be masked off when testing,
899 * as will PARTIAL for optional+transitive attributes.
900 */
901 const u_int8_t attr_flags_values [] = {
902 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
903 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
904 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
905 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
906 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
907 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
908 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
909 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
910 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
911 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
912 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
913 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
914 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
915 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
916 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
917 };
918 static const size_t attr_flags_values_max =
919 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
920
921 static int
922 bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
923 {
924 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
925 const u_int8_t flags = args->flags;
926 const u_int8_t attr_code = args->type;
927 struct peer *const peer = args->peer;
928
929 /* there may be attributes we don't know about */
930 if (attr_code > attr_flags_values_max)
931 return 0;
932 if (attr_flags_values[attr_code] == 0)
933 return 0;
934
935 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
936 * 1."
937 */
938 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
939 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
940 {
941 zlog_err ("%s well-known attributes must have transitive flag set (%x)",
942 LOOKUP (attr_str, attr_code), flags);
943 return 1;
944 }
945
946 /* "For well-known attributes and for optional non-transitive attributes,
947 * the Partial bit MUST be set to 0."
948 */
949 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
950 {
951 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
952 {
953 zlog_err ("%s well-known attribute "
954 "must NOT have the partial flag set (%x)",
955 LOOKUP (attr_str, attr_code), flags);
956 return 1;
957 }
958 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
959 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
960 {
961 zlog_err ("%s optional + transitive attribute "
962 "must NOT have the partial flag set (%x)",
963 LOOKUP (attr_str, attr_code), flags);
964 return 1;
965 }
966 }
967
968 /* Optional transitive attributes may go through speakers that don't
969 * reocgnise them and set the Partial bit.
970 */
971 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
972 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
973 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
974
975 if ((flags & ~mask)
976 == attr_flags_values[attr_code])
977 return 0;
978
979 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
980 return 1;
981 }
982
983 /* Get origin attribute of the update message. */
984 static bgp_attr_parse_ret_t
985 bgp_attr_origin (struct bgp_attr_parser_args *args)
986 {
987 struct peer *const peer = args->peer;
988 struct attr *const attr = args->attr;
989 const bgp_size_t length = args->length;
990
991 /* If any recognized attribute has Attribute Length that conflicts
992 with the expected length (based on the attribute type code), then
993 the Error Subcode is set to Attribute Length Error. The Data
994 field contains the erroneous attribute (type, length and
995 value). */
996 if (length != 1)
997 {
998 zlog_err ("Origin attribute length is not one %d", length);
999 return bgp_attr_malformed (args,
1000 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1001 args->total);
1002 }
1003
1004 /* Fetch origin attribute. */
1005 attr->origin = stream_getc (BGP_INPUT (peer));
1006
1007 /* If the ORIGIN attribute has an undefined value, then the Error
1008 Subcode is set to Invalid Origin Attribute. The Data field
1009 contains the unrecognized attribute (type, length and value). */
1010 if ((attr->origin != BGP_ORIGIN_IGP)
1011 && (attr->origin != BGP_ORIGIN_EGP)
1012 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1013 {
1014 zlog_err ("Origin attribute value is invalid %d", attr->origin);
1015 return bgp_attr_malformed (args,
1016 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1017 args->total);
1018 }
1019
1020 /* Set oring attribute flag. */
1021 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1022
1023 return 0;
1024 }
1025
1026 /* Parse AS path information. This function is wrapper of
1027 aspath_parse. */
1028 static int
1029 bgp_attr_aspath (struct bgp_attr_parser_args *args)
1030 {
1031 struct attr *const attr = args->attr;
1032 struct peer *const peer = args->peer;
1033 const bgp_size_t length = args->length;
1034
1035 /*
1036 * peer with AS4 => will get 4Byte ASnums
1037 * otherwise, will get 16 Bit
1038 */
1039 attr->aspath = aspath_parse (peer->ibuf, length,
1040 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1041
1042 /* In case of IBGP, length will be zero. */
1043 if (! attr->aspath)
1044 {
1045 zlog_err ("Malformed AS path from %s, length is %d", peer->host, length);
1046 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
1047 }
1048
1049 /* Set aspath attribute flag. */
1050 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
1051
1052 return BGP_ATTR_PARSE_PROCEED;
1053 }
1054
1055 static bgp_attr_parse_ret_t
1056 bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
1057 {
1058 /* These checks were part of bgp_attr_aspath, but with
1059 * as4 we should to check aspath things when
1060 * aspath synthesizing with as4_path has already taken place.
1061 * Otherwise we check ASPATH and use the synthesized thing, and that is
1062 * not right.
1063 * So do the checks later, i.e. here
1064 */
1065 struct bgp *bgp = peer->bgp;
1066 struct aspath *aspath;
1067
1068 /* Confederation sanity check. */
1069 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1070 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
1071 {
1072 zlog_err ("Malformed AS path from %s", peer->host);
1073 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1074 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1075 return BGP_ATTR_PARSE_ERROR;
1076 }
1077
1078 /* First AS check for EBGP. */
1079 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1080 {
1081 if (peer->sort == BGP_PEER_EBGP
1082 && ! aspath_firstas_check (attr->aspath, peer->as))
1083 {
1084 zlog_err ("%s incorrect first AS (must be %u)", peer->host, peer->as);
1085 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1086 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1087 return BGP_ATTR_PARSE_ERROR;
1088 }
1089 }
1090
1091 /* local-as prepend */
1092 if (peer->change_local_as &&
1093 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1094 {
1095 aspath = aspath_dup (attr->aspath);
1096 aspath = aspath_add_seq (aspath, peer->change_local_as);
1097 aspath_unintern (&attr->aspath);
1098 attr->aspath = aspath_intern (aspath);
1099 }
1100
1101 return BGP_ATTR_PARSE_PROCEED;
1102 }
1103
1104 /* Parse AS4 path information. This function is another wrapper of
1105 aspath_parse. */
1106 static int
1107 bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
1108 {
1109 struct peer *const peer = args->peer;
1110 struct attr *const attr = args->attr;
1111 const bgp_size_t length = args->length;
1112
1113 *as4_path = aspath_parse (peer->ibuf, length, 1);
1114
1115 /* In case of IBGP, length will be zero. */
1116 if (!*as4_path)
1117 {
1118 zlog_err ("Malformed AS4 path from %s, length is %d", peer->host, length);
1119 return bgp_attr_malformed (args,
1120 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1121 0);
1122 }
1123
1124 /* Set aspath attribute flag. */
1125 if (as4_path)
1126 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1127
1128 return BGP_ATTR_PARSE_PROCEED;
1129 }
1130
1131 /* Nexthop attribute. */
1132 static bgp_attr_parse_ret_t
1133 bgp_attr_nexthop (struct bgp_attr_parser_args *args)
1134 {
1135 struct peer *const peer = args->peer;
1136 struct attr *const attr = args->attr;
1137 const bgp_size_t length = args->length;
1138
1139 in_addr_t nexthop_h, nexthop_n;
1140
1141 /* Check nexthop attribute length. */
1142 if (length != 4)
1143 {
1144 zlog_err ("Nexthop attribute length isn't four [%d]", length);
1145
1146 return bgp_attr_malformed (args,
1147 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1148 args->total);
1149 }
1150
1151 nexthop_n = stream_get_ipv4 (peer->ibuf);
1152 nexthop_h = ntohl (nexthop_n);
1153 if (!bgp_valid_host_address(nexthop_h))
1154 {
1155 char buf[INET_ADDRSTRLEN];
1156 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
1157 zlog_err ("Martian nexthop %s", buf);
1158 return bgp_attr_malformed (args,
1159 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
1160 args->total);
1161 }
1162
1163 attr->nexthop.s_addr = nexthop_n;
1164 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1165
1166 return BGP_ATTR_PARSE_PROCEED;
1167 }
1168
1169 /* MED atrribute. */
1170 static bgp_attr_parse_ret_t
1171 bgp_attr_med (struct bgp_attr_parser_args *args)
1172 {
1173 struct peer *const peer = args->peer;
1174 struct attr *const attr = args->attr;
1175 const bgp_size_t length = args->length;
1176
1177 /* Length check. */
1178 if (length != 4)
1179 {
1180 zlog_err ("MED attribute length isn't four [%d]", length);
1181
1182 return bgp_attr_malformed (args,
1183 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1184 args->total);
1185 }
1186
1187 attr->med = stream_getl (peer->ibuf);
1188
1189 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1190
1191 return BGP_ATTR_PARSE_PROCEED;
1192 }
1193
1194 /* Local preference attribute. */
1195 static bgp_attr_parse_ret_t
1196 bgp_attr_local_pref (struct bgp_attr_parser_args *args)
1197 {
1198 struct peer *const peer = args->peer;
1199 struct attr *const attr = args->attr;
1200 const bgp_size_t length = args->length;
1201
1202 /* Length check. */
1203 if (length != 4)
1204 {
1205 zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length);
1206 return bgp_attr_malformed (args,
1207 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1208 args->total);
1209 }
1210
1211 /* If it is contained in an UPDATE message that is received from an
1212 external peer, then this attribute MUST be ignored by the
1213 receiving speaker. */
1214 if (peer->sort == BGP_PEER_EBGP)
1215 {
1216 stream_forward_getp (peer->ibuf, length);
1217 return BGP_ATTR_PARSE_PROCEED;
1218 }
1219
1220 attr->local_pref = stream_getl (peer->ibuf);
1221
1222 /* Set atomic aggregate flag. */
1223 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1224
1225 return BGP_ATTR_PARSE_PROCEED;
1226 }
1227
1228 /* Atomic aggregate. */
1229 static int
1230 bgp_attr_atomic (struct bgp_attr_parser_args *args)
1231 {
1232 struct peer *const peer = args->peer;
1233 struct attr *const attr = args->attr;
1234 const bgp_size_t length = args->length;
1235
1236 /* Length check. */
1237 if (length != 0)
1238 {
1239 zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length);
1240 return bgp_attr_malformed (args,
1241 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1242 args->total);
1243 }
1244
1245 /* Set atomic aggregate flag. */
1246 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1247
1248 return BGP_ATTR_PARSE_PROCEED;
1249 }
1250
1251 /* Aggregator attribute */
1252 static int
1253 bgp_attr_aggregator (struct bgp_attr_parser_args *args)
1254 {
1255 struct peer *const peer = args->peer;
1256 struct attr *const attr = args->attr;
1257 const bgp_size_t length = args->length;
1258
1259 int wantedlen = 6;
1260 struct attr_extra *attre = bgp_attr_extra_get (attr);
1261
1262 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1263 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1264 wantedlen = 8;
1265
1266 if (length != wantedlen)
1267 {
1268 zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen, length);
1269 return bgp_attr_malformed (args,
1270 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1271 args->total);
1272 }
1273
1274 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1275 attre->aggregator_as = stream_getl (peer->ibuf);
1276 else
1277 attre->aggregator_as = stream_getw (peer->ibuf);
1278 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
1279
1280 /* Set atomic aggregate flag. */
1281 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1282
1283 return BGP_ATTR_PARSE_PROCEED;
1284 }
1285
1286 /* New Aggregator attribute */
1287 static bgp_attr_parse_ret_t
1288 bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1289 as_t *as4_aggregator_as,
1290 struct in_addr *as4_aggregator_addr)
1291 {
1292 struct peer *const peer = args->peer;
1293 struct attr *const attr = args->attr;
1294 const bgp_size_t length = args->length;
1295
1296 if (length != 8)
1297 {
1298 zlog_err ("New Aggregator length is not 8 [%d]", length);
1299 return bgp_attr_malformed (args,
1300 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1301 0);
1302 }
1303
1304 *as4_aggregator_as = stream_getl (peer->ibuf);
1305 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1306
1307 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1308
1309 return BGP_ATTR_PARSE_PROCEED;
1310 }
1311
1312 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1313 */
1314 static bgp_attr_parse_ret_t
1315 bgp_attr_munge_as4_attrs (struct peer *const peer,
1316 struct attr *const attr,
1317 struct aspath *as4_path, as_t as4_aggregator,
1318 struct in_addr *as4_aggregator_addr)
1319 {
1320 int ignore_as4_path = 0;
1321 struct aspath *newpath;
1322 struct attr_extra *attre = attr->extra;
1323
1324 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1325 {
1326 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1327 * if given.
1328 * It is worth a warning though, because the peer really
1329 * should not send them
1330 */
1331 if (BGP_DEBUG(as4, AS4))
1332 {
1333 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1334 zlog_debug ("[AS4] %s %s AS4_PATH",
1335 peer->host, "AS4 capable peer, yet it sent");
1336
1337 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1338 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1339 peer->host, "AS4 capable peer, yet it sent");
1340 }
1341
1342 return BGP_ATTR_PARSE_PROCEED;
1343 }
1344
1345 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1346 * because that may override AS4_PATH
1347 */
1348 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1349 {
1350 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
1351 {
1352 assert (attre);
1353
1354 /* received both.
1355 * if the as_number in aggregator is not AS_TRANS,
1356 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1357 * and the Aggregator shall be taken as
1358 * info on the aggregating node, and the AS_PATH
1359 * shall be taken as the AS_PATH
1360 * otherwise
1361 * the Aggregator shall be ignored and the
1362 * AS4_AGGREGATOR shall be taken as the
1363 * Aggregating node and the AS_PATH is to be
1364 * constructed "as in all other cases"
1365 */
1366 if (attre->aggregator_as != BGP_AS_TRANS)
1367 {
1368 /* ignore */
1369 if ( BGP_DEBUG(as4, AS4))
1370 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1371 " send AGGREGATOR != AS_TRANS and"
1372 " AS4_AGGREGATOR, so ignore"
1373 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1374 ignore_as4_path = 1;
1375 }
1376 else
1377 {
1378 /* "New_aggregator shall be taken as aggregator" */
1379 attre->aggregator_as = as4_aggregator;
1380 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1381 }
1382 }
1383 else
1384 {
1385 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1386 * That is bogus - but reading the conditions
1387 * we have to handle AS4_AGGREGATOR as if it were
1388 * AGGREGATOR in that case
1389 */
1390 if ( BGP_DEBUG(as4, AS4))
1391 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1392 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1393 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
1394 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
1395 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1396 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1397 }
1398 }
1399
1400 /* need to reconcile NEW_AS_PATH and AS_PATH */
1401 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
1402 {
1403 if (!attr->aspath)
1404 return BGP_ATTR_PARSE_PROCEED;
1405
1406 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1407 aspath_unintern (&attr->aspath);
1408 attr->aspath = aspath_intern (newpath);
1409 }
1410 return BGP_ATTR_PARSE_PROCEED;
1411 }
1412
1413 /* Community attribute. */
1414 static bgp_attr_parse_ret_t
1415 bgp_attr_community (struct bgp_attr_parser_args *args)
1416 {
1417 struct peer *const peer = args->peer;
1418 struct attr *const attr = args->attr;
1419 const bgp_size_t length = args->length;
1420
1421 if (length == 0)
1422 {
1423 attr->community = NULL;
1424 return BGP_ATTR_PARSE_PROCEED;
1425 }
1426
1427 attr->community =
1428 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1429
1430 /* XXX: fix community_parse to use stream API and remove this */
1431 stream_forward_getp (peer->ibuf, length);
1432
1433 if (!attr->community)
1434 return bgp_attr_malformed (args,
1435 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1436 args->total);
1437
1438 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1439
1440 return BGP_ATTR_PARSE_PROCEED;
1441 }
1442
1443 /* Originator ID attribute. */
1444 static bgp_attr_parse_ret_t
1445 bgp_attr_originator_id (struct bgp_attr_parser_args *args)
1446 {
1447 struct peer *const peer = args->peer;
1448 struct attr *const attr = args->attr;
1449 const bgp_size_t length = args->length;
1450
1451 /* Length check. */
1452 if (length != 4)
1453 {
1454 zlog_err ("Bad originator ID length %d", length);
1455
1456 return bgp_attr_malformed (args,
1457 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1458 args->total);
1459 }
1460
1461 (bgp_attr_extra_get (attr))->originator_id.s_addr
1462 = stream_get_ipv4 (peer->ibuf);
1463
1464 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1465
1466 return BGP_ATTR_PARSE_PROCEED;
1467 }
1468
1469 /* Cluster list attribute. */
1470 static bgp_attr_parse_ret_t
1471 bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
1472 {
1473 struct peer *const peer = args->peer;
1474 struct attr *const attr = args->attr;
1475 const bgp_size_t length = args->length;
1476
1477 /* Check length. */
1478 if (length % 4)
1479 {
1480 zlog_err ("Bad cluster list length %d", length);
1481
1482 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1483 args->total);
1484 }
1485
1486 (bgp_attr_extra_get (attr))->cluster
1487 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
1488
1489 /* XXX: Fix cluster_parse to use stream API and then remove this */
1490 stream_forward_getp (peer->ibuf, length);
1491
1492 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1493
1494 return BGP_ATTR_PARSE_PROCEED;
1495 }
1496
1497 /* Multiprotocol reachability information parse. */
1498 int
1499 bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1500 struct bgp_nlri *mp_update)
1501 {
1502 afi_t afi;
1503 safi_t safi;
1504 bgp_size_t nlri_len;
1505 size_t start;
1506 int ret;
1507 int num_mp_pfx = 0;
1508 struct stream *s;
1509 struct peer *const peer = args->peer;
1510 struct attr *const attr = args->attr;
1511 const bgp_size_t length = args->length;
1512 struct attr_extra *attre = bgp_attr_extra_get(attr);
1513
1514 /* Set end of packet. */
1515 s = BGP_INPUT(peer);
1516 start = stream_get_getp(s);
1517
1518 /* safe to read statically sized header? */
1519 #define BGP_MP_REACH_MIN_SIZE 5
1520 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1521 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
1522 {
1523 zlog_info ("%s: %s sent invalid length, %lu",
1524 __func__, peer->host, (unsigned long)length);
1525 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1526 }
1527
1528 /* Load AFI, SAFI. */
1529 afi = stream_getw (s);
1530 safi = stream_getc (s);
1531
1532 /* Get nexthop length. */
1533 attre->mp_nexthop_len = stream_getc (s);
1534
1535 if (LEN_LEFT < attre->mp_nexthop_len)
1536 {
1537 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1538 __func__, peer->host, attre->mp_nexthop_len);
1539 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1540 }
1541
1542 /* Nexthop length check. */
1543 switch (attre->mp_nexthop_len)
1544 {
1545 case 4:
1546 stream_get (&attre->mp_nexthop_global_in, s, 4);
1547 /* Probably needed for RFC 2283 */
1548 if (attr->nexthop.s_addr == 0)
1549 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
1550 break;
1551 case 12:
1552 stream_getl (s); /* RD high */
1553 stream_getl (s); /* RD low */
1554 stream_get (&attre->mp_nexthop_global_in, s, 4);
1555 break;
1556 #ifdef HAVE_IPV6
1557 case 16:
1558 stream_get (&attre->mp_nexthop_global, s, 16);
1559 break;
1560 case 32:
1561 stream_get (&attre->mp_nexthop_global, s, 16);
1562 stream_get (&attre->mp_nexthop_local, s, 16);
1563 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
1564 {
1565 char buf1[INET6_ADDRSTRLEN];
1566 char buf2[INET6_ADDRSTRLEN];
1567
1568 if (bgp_debug_update(peer, NULL, 1))
1569 zlog_debug ("%s sent two nexthops %s %s but second one is not a link-local nexthop", peer->host,
1570 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
1571 buf1, INET6_ADDRSTRLEN),
1572 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
1573 buf2, INET6_ADDRSTRLEN));
1574
1575 attre->mp_nexthop_len = 16;
1576 }
1577 break;
1578 #endif /* HAVE_IPV6 */
1579 default:
1580 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1581 __func__, peer->host, attre->mp_nexthop_len);
1582 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1583 }
1584
1585 if (!LEN_LEFT)
1586 {
1587 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1588 __func__, peer->host);
1589 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1590 }
1591
1592 {
1593 u_char val;
1594 if ((val = stream_getc (s)))
1595 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1596 peer->host, val);
1597 }
1598
1599 /* must have nrli_len, what is left of the attribute */
1600 nlri_len = LEN_LEFT;
1601 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
1602 {
1603 zlog_info ("%s: (%s) Failed to read NLRI",
1604 __func__, peer->host);
1605 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1606 }
1607
1608 if (safi != SAFI_MPLS_LABELED_VPN)
1609 {
1610 ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
1611 nlri_len, &num_mp_pfx);
1612 if (ret < 0)
1613 {
1614 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1615 __func__, peer->host);
1616 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1617 }
1618 }
1619
1620 mp_update->afi = afi;
1621 mp_update->safi = safi;
1622 mp_update->nlri = stream_pnt (s);
1623 mp_update->length = nlri_len;
1624
1625 stream_forward_getp (s, nlri_len);
1626
1627 return BGP_ATTR_PARSE_PROCEED;
1628 #undef LEN_LEFT
1629 }
1630
1631 /* Multiprotocol unreachable parse */
1632 int
1633 bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
1634 struct bgp_nlri *mp_withdraw)
1635 {
1636 struct stream *s;
1637 afi_t afi;
1638 safi_t safi;
1639 u_int16_t withdraw_len;
1640 int ret;
1641 int num_mp_pfx = 0;
1642 struct peer *const peer = args->peer;
1643 const bgp_size_t length = args->length;
1644
1645 s = peer->ibuf;
1646
1647 #define BGP_MP_UNREACH_MIN_SIZE 3
1648 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
1649 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1650
1651 afi = stream_getw (s);
1652 safi = stream_getc (s);
1653
1654 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
1655
1656 if (safi != SAFI_MPLS_LABELED_VPN)
1657 {
1658 ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
1659 withdraw_len, &num_mp_pfx);
1660 if (ret < 0)
1661 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1662 }
1663
1664 mp_withdraw->afi = afi;
1665 mp_withdraw->safi = safi;
1666 mp_withdraw->nlri = stream_pnt (s);
1667 mp_withdraw->length = withdraw_len;
1668
1669 stream_forward_getp (s, withdraw_len);
1670
1671 return BGP_ATTR_PARSE_PROCEED;
1672 }
1673
1674 /* Extended Community attribute. */
1675 static bgp_attr_parse_ret_t
1676 bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
1677 {
1678 struct peer *const peer = args->peer;
1679 struct attr *const attr = args->attr;
1680 const bgp_size_t length = args->length;
1681
1682 if (length == 0)
1683 {
1684 if (attr->extra)
1685 attr->extra->ecommunity = NULL;
1686 /* Empty extcomm doesn't seem to be invalid per se */
1687 return BGP_ATTR_PARSE_PROCEED;
1688 }
1689
1690 (bgp_attr_extra_get (attr))->ecommunity =
1691 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1692 /* XXX: fix ecommunity_parse to use stream API */
1693 stream_forward_getp (peer->ibuf, length);
1694
1695 if (!attr->extra->ecommunity)
1696 return bgp_attr_malformed (args,
1697 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1698 args->total);
1699
1700 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1701
1702 return BGP_ATTR_PARSE_PROCEED;
1703 }
1704
1705 /* BGP unknown attribute treatment. */
1706 static bgp_attr_parse_ret_t
1707 bgp_attr_unknown (struct bgp_attr_parser_args *args)
1708 {
1709 bgp_size_t total = args->total;
1710 struct transit *transit;
1711 struct attr_extra *attre;
1712 struct peer *const peer = args->peer;
1713 struct attr *const attr = args->attr;
1714 u_char *const startp = args->startp;
1715 const u_char type = args->type;
1716 const u_char flag = args->flags;
1717 const bgp_size_t length = args->length;
1718
1719 if (bgp_debug_update(peer, NULL, 1))
1720 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1721 peer->host, type, length);
1722
1723 /* Forward read pointer of input stream. */
1724 stream_forward_getp (peer->ibuf, length);
1725
1726 /* If any of the mandatory well-known attributes are not recognized,
1727 then the Error Subcode is set to Unrecognized Well-known
1728 Attribute. The Data field contains the unrecognized attribute
1729 (type, length and value). */
1730 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
1731 {
1732 return bgp_attr_malformed (args,
1733 BGP_NOTIFY_UPDATE_UNREC_ATTR,
1734 args->total);
1735 }
1736
1737 /* Unrecognized non-transitive optional attributes must be quietly
1738 ignored and not passed along to other BGP peers. */
1739 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
1740 return BGP_ATTR_PARSE_PROCEED;
1741
1742 /* If a path with recognized transitive optional attribute is
1743 accepted and passed along to other BGP peers and the Partial bit
1744 in the Attribute Flags octet is set to 1 by some previous AS, it
1745 is not set back to 0 by the current AS. */
1746 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1747
1748 /* Store transitive attribute to the end of attr->transit. */
1749 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
1750 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
1751
1752 transit = attre->transit;
1753
1754 if (transit->val)
1755 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1756 transit->length + total);
1757 else
1758 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1759
1760 memcpy (transit->val + transit->length, startp, total);
1761 transit->length += total;
1762
1763 return BGP_ATTR_PARSE_PROCEED;
1764 }
1765
1766 /* Read attribute of update packet. This function is called from
1767 bgp_update_receive() in bgp_packet.c. */
1768 bgp_attr_parse_ret_t
1769 bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1770 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1771 {
1772 int ret;
1773 u_char flag = 0;
1774 u_char type = 0;
1775 bgp_size_t length;
1776 u_char *startp, *endp;
1777 u_char *attr_endp;
1778 u_char seen[BGP_ATTR_BITMAP_SIZE];
1779 /* we need the as4_path only until we have synthesized the as_path with it */
1780 /* same goes for as4_aggregator */
1781 struct aspath *as4_path = NULL;
1782 as_t as4_aggregator = 0;
1783 struct in_addr as4_aggregator_addr = { 0 };
1784
1785 /* Initialize bitmap. */
1786 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1787
1788 /* End pointer of BGP attribute. */
1789 endp = BGP_INPUT_PNT (peer) + size;
1790
1791 /* Get attributes to the end of attribute length. */
1792 while (BGP_INPUT_PNT (peer) < endp)
1793 {
1794 /* Check remaining length check.*/
1795 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1796 {
1797 /* XXX warning: long int format, int arg (arg 5) */
1798 zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
1799 peer->host,
1800 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1801
1802 bgp_notify_send (peer,
1803 BGP_NOTIFY_UPDATE_ERR,
1804 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1805 return BGP_ATTR_PARSE_ERROR;
1806 }
1807
1808 /* Fetch attribute flag and type. */
1809 startp = BGP_INPUT_PNT (peer);
1810 /* "The lower-order four bits of the Attribute Flags octet are
1811 unused. They MUST be zero when sent and MUST be ignored when
1812 received." */
1813 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
1814 type = stream_getc (BGP_INPUT (peer));
1815
1816 /* Check whether Extended-Length applies and is in bounds */
1817 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1818 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1819 {
1820 zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
1821 peer->host,
1822 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1823
1824 bgp_notify_send (peer,
1825 BGP_NOTIFY_UPDATE_ERR,
1826 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1827 return BGP_ATTR_PARSE_ERROR;
1828 }
1829
1830 /* Check extended attribue length bit. */
1831 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1832 length = stream_getw (BGP_INPUT (peer));
1833 else
1834 length = stream_getc (BGP_INPUT (peer));
1835
1836 /* If any attribute appears more than once in the UPDATE
1837 message, then the Error Subcode is set to Malformed Attribute
1838 List. */
1839
1840 if (CHECK_BITMAP (seen, type))
1841 {
1842 zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
1843 peer->host, type);
1844
1845 bgp_notify_send (peer,
1846 BGP_NOTIFY_UPDATE_ERR,
1847 BGP_NOTIFY_UPDATE_MAL_ATTR);
1848 return BGP_ATTR_PARSE_ERROR;
1849 }
1850
1851 /* Set type to bitmap to check duplicate attribute. `type' is
1852 unsigned char so it never overflow bitmap range. */
1853
1854 SET_BITMAP (seen, type);
1855
1856 /* Overflow check. */
1857 attr_endp = BGP_INPUT_PNT (peer) + length;
1858
1859 if (attr_endp > endp)
1860 {
1861 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);
1862 bgp_notify_send_with_data (peer,
1863 BGP_NOTIFY_UPDATE_ERR,
1864 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1865 startp, attr_endp - startp);
1866 return BGP_ATTR_PARSE_ERROR;
1867 }
1868
1869 struct bgp_attr_parser_args attr_args = {
1870 .peer = peer,
1871 .length = length,
1872 .attr = attr,
1873 .type = type,
1874 .flags = flag,
1875 .startp = startp,
1876 .total = attr_endp - startp,
1877 };
1878
1879
1880 /* If any recognized attribute has Attribute Flags that conflict
1881 with the Attribute Type Code, then the Error Subcode is set to
1882 Attribute Flags Error. The Data field contains the erroneous
1883 attribute (type, length and value). */
1884 if (bgp_attr_flag_invalid (&attr_args))
1885 {
1886 bgp_attr_parse_ret_t ret;
1887 ret = bgp_attr_malformed (&attr_args,
1888 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1889 attr_args.total);
1890 if (ret == BGP_ATTR_PARSE_PROCEED)
1891 continue;
1892 return ret;
1893 }
1894
1895 /* OK check attribute and store it's value. */
1896 switch (type)
1897 {
1898 case BGP_ATTR_ORIGIN:
1899 ret = bgp_attr_origin (&attr_args);
1900 break;
1901 case BGP_ATTR_AS_PATH:
1902 ret = bgp_attr_aspath (&attr_args);
1903 break;
1904 case BGP_ATTR_AS4_PATH:
1905 ret = bgp_attr_as4_path (&attr_args, &as4_path);
1906 break;
1907 case BGP_ATTR_NEXT_HOP:
1908 ret = bgp_attr_nexthop (&attr_args);
1909 break;
1910 case BGP_ATTR_MULTI_EXIT_DISC:
1911 ret = bgp_attr_med (&attr_args);
1912 break;
1913 case BGP_ATTR_LOCAL_PREF:
1914 ret = bgp_attr_local_pref (&attr_args);
1915 break;
1916 case BGP_ATTR_ATOMIC_AGGREGATE:
1917 ret = bgp_attr_atomic (&attr_args);
1918 break;
1919 case BGP_ATTR_AGGREGATOR:
1920 ret = bgp_attr_aggregator (&attr_args);
1921 break;
1922 case BGP_ATTR_AS4_AGGREGATOR:
1923 ret = bgp_attr_as4_aggregator (&attr_args,
1924 &as4_aggregator,
1925 &as4_aggregator_addr);
1926 break;
1927 case BGP_ATTR_COMMUNITIES:
1928 ret = bgp_attr_community (&attr_args);
1929 break;
1930 case BGP_ATTR_ORIGINATOR_ID:
1931 ret = bgp_attr_originator_id (&attr_args);
1932 break;
1933 case BGP_ATTR_CLUSTER_LIST:
1934 ret = bgp_attr_cluster_list (&attr_args);
1935 break;
1936 case BGP_ATTR_MP_REACH_NLRI:
1937 ret = bgp_mp_reach_parse (&attr_args, mp_update);
1938 break;
1939 case BGP_ATTR_MP_UNREACH_NLRI:
1940 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
1941 break;
1942 case BGP_ATTR_EXT_COMMUNITIES:
1943 ret = bgp_attr_ext_communities (&attr_args);
1944 break;
1945 default:
1946 ret = bgp_attr_unknown (&attr_args);
1947 break;
1948 }
1949
1950 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
1951 {
1952 bgp_notify_send (peer,
1953 BGP_NOTIFY_UPDATE_ERR,
1954 BGP_NOTIFY_UPDATE_MAL_ATTR);
1955 ret = BGP_ATTR_PARSE_ERROR;
1956 }
1957
1958 /* If hard error occured immediately return to the caller. */
1959 if (ret == BGP_ATTR_PARSE_ERROR)
1960 {
1961 zlog_warn ("%s: Attribute %s, parse error",
1962 peer->host,
1963 LOOKUP (attr_str, type));
1964 if (as4_path)
1965 aspath_unintern (&as4_path);
1966 return ret;
1967 }
1968 if (ret == BGP_ATTR_PARSE_WITHDRAW)
1969 {
1970
1971 zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
1972 peer->host,
1973 LOOKUP (attr_str, type));
1974 if (as4_path)
1975 aspath_unintern (&as4_path);
1976 return ret;
1977 }
1978
1979 /* Check the fetched length. */
1980 if (BGP_INPUT_PNT (peer) != attr_endp)
1981 {
1982 zlog_warn ("%s: BGP attribute %s, fetch error",
1983 peer->host, LOOKUP (attr_str, type));
1984 bgp_notify_send (peer,
1985 BGP_NOTIFY_UPDATE_ERR,
1986 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1987 if (as4_path)
1988 aspath_unintern (&as4_path);
1989 return BGP_ATTR_PARSE_ERROR;
1990 }
1991 }
1992
1993 /* Check final read pointer is same as end pointer. */
1994 if (BGP_INPUT_PNT (peer) != endp)
1995 {
1996 zlog_warn ("%s: BGP attribute %s, length mismatch",
1997 peer->host, LOOKUP (attr_str, type));
1998 bgp_notify_send (peer,
1999 BGP_NOTIFY_UPDATE_ERR,
2000 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
2001 if (as4_path)
2002 aspath_unintern (&as4_path);
2003 return BGP_ATTR_PARSE_ERROR;
2004 }
2005
2006 /*
2007 * At this place we can see whether we got AS4_PATH and/or
2008 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2009 * We can not do this before we've read all attributes because
2010 * the as4 handling does not say whether AS4_PATH has to be sent
2011 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2012 * in relationship to AGGREGATOR.
2013 * So, to be defensive, we are not relying on any order and read
2014 * all attributes first, including these 32bit ones, and now,
2015 * afterwards, we look what and if something is to be done for as4.
2016 */
2017 /* actually... this doesn't ever return failure currently, but
2018 * better safe than sorry */
2019 if (bgp_attr_munge_as4_attrs (peer, attr, as4_path,
2020 as4_aggregator, &as4_aggregator_addr))
2021 {
2022 bgp_notify_send (peer,
2023 BGP_NOTIFY_UPDATE_ERR,
2024 BGP_NOTIFY_UPDATE_MAL_ATTR);
2025 if (as4_path)
2026 aspath_unintern (&as4_path);
2027 return BGP_ATTR_PARSE_ERROR;
2028 }
2029
2030 /* At this stage, we have done all fiddling with as4, and the
2031 * resulting info is in attr->aggregator resp. attr->aspath
2032 * so we can chuck as4_aggregator and as4_path alltogether in
2033 * order to save memory
2034 */
2035 if (as4_path)
2036 {
2037 aspath_unintern (&as4_path); /* unintern - it is in the hash */
2038 /* The flag that we got this is still there, but that does not
2039 * do any trouble
2040 */
2041 }
2042 /*
2043 * The "rest" of the code does nothing with as4_aggregator.
2044 * there is no memory attached specifically which is not part
2045 * of the attr.
2046 * so ignoring just means do nothing.
2047 */
2048 /*
2049 * Finally do the checks on the aspath we did not do yet
2050 * because we waited for a potentially synthesized aspath.
2051 */
2052 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
2053 {
2054 ret = bgp_attr_aspath_check (peer, attr);
2055 if (ret != BGP_ATTR_PARSE_PROCEED)
2056 return ret;
2057 }
2058
2059 /* Finally intern unknown attribute. */
2060 if (attr->extra && attr->extra->transit)
2061 attr->extra->transit = transit_intern (attr->extra->transit);
2062
2063 return BGP_ATTR_PARSE_PROCEED;
2064 }
2065
2066 /* Well-known attribute check. */
2067 int
2068 bgp_attr_check (struct peer *peer, struct attr *attr)
2069 {
2070 u_char type = 0;
2071
2072 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2073 type = BGP_ATTR_ORIGIN;
2074
2075 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2076 type = BGP_ATTR_AS_PATH;
2077
2078 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
2079 type = BGP_ATTR_NEXT_HOP;
2080
2081 if (peer->sort == BGP_PEER_IBGP
2082 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2083 type = BGP_ATTR_LOCAL_PREF;
2084
2085 if (type)
2086 {
2087 zlog_warn ("%s Missing well-known attribute %d.", peer->host, type);
2088 bgp_notify_send_with_data (peer,
2089 BGP_NOTIFY_UPDATE_ERR,
2090 BGP_NOTIFY_UPDATE_MISS_ATTR,
2091 &type, 1);
2092 return BGP_ATTR_PARSE_ERROR;
2093 }
2094 return BGP_ATTR_PARSE_PROCEED;
2095 }
2096
2097 int stream_put_prefix (struct stream *, struct prefix *);
2098
2099 size_t
2100 bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2101 struct attr *attr)
2102 {
2103 size_t sizep;
2104
2105 /* Set extended bit always to encode the attribute length as 2 bytes */
2106 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2107 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2108 sizep = stream_get_endp (s);
2109 stream_putw (s, 0); /* Marker: Attribute length. */
2110 stream_putw (s, afi); /* AFI */
2111 stream_putc (s, safi); /* SAFI */
2112
2113 /* Nexthop */
2114 switch (afi)
2115 {
2116 case AFI_IP:
2117 switch (safi)
2118 {
2119 case SAFI_UNICAST:
2120 case SAFI_MULTICAST:
2121 stream_putc (s, 4);
2122 stream_put_ipv4 (s, attr->nexthop.s_addr);
2123 break;
2124 case SAFI_MPLS_VPN:
2125 stream_putc (s, 12);
2126 stream_putl (s, 0);
2127 stream_putl (s, 0);
2128 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2129 break;
2130 default:
2131 break;
2132 }
2133 break;
2134 #ifdef HAVE_IPV6
2135 case AFI_IP6:
2136 switch (safi)
2137 {
2138 case SAFI_UNICAST:
2139 case SAFI_MULTICAST:
2140 {
2141 unsigned long sizep;
2142 struct attr_extra *attre = attr->extra;
2143
2144 assert (attr->extra);
2145 stream_putc (s, attre->mp_nexthop_len);
2146 stream_put (s, &attre->mp_nexthop_global, 16);
2147 if (attre->mp_nexthop_len == 32)
2148 stream_put (s, &attre->mp_nexthop_local, 16);
2149 }
2150 default:
2151 break;
2152 }
2153 break;
2154 #endif /*HAVE_IPV6*/
2155 default:
2156 break;
2157 }
2158
2159 /* SNPA */
2160 stream_putc (s, 0);
2161 return sizep;
2162 }
2163
2164 void
2165 bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2166 struct prefix *p, struct prefix_rd *prd,
2167 u_char *tag)
2168 {
2169 switch (safi)
2170 {
2171 case SAFI_MPLS_VPN:
2172 /* Tag, RD, Prefix write. */
2173 stream_putc (s, p->prefixlen + 88);
2174 stream_put (s, tag, 3);
2175 stream_put (s, prd->val, 8);
2176 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2177 break;
2178 default:
2179 /* Prefix write. */
2180 stream_put_prefix (s, p);
2181 break;
2182 }
2183 }
2184
2185 void
2186 bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2187 {
2188 /* Set MP attribute length. Don't count the (2) bytes used to encode
2189 the attr length */
2190 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2191 }
2192
2193 /* Make attribute packet. */
2194 bgp_size_t
2195 bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
2196 struct stream *s, struct attr *attr,
2197 struct prefix *p, afi_t afi, safi_t safi,
2198 struct peer *from, struct prefix_rd *prd, u_char *tag)
2199 {
2200 size_t cp;
2201 size_t aspath_sizep;
2202 struct aspath *aspath;
2203 int send_as4_path = 0;
2204 int send_as4_aggregator = 0;
2205 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
2206 size_t mpattrlen_pos = 0;
2207
2208 if (! bgp)
2209 bgp = bgp_get_default ();
2210
2211 /* Remember current pointer. */
2212 cp = stream_get_endp (s);
2213
2214 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2215 {
2216 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2217 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2218 bgp_packet_mpattr_end(s, mpattrlen_pos);
2219 }
2220
2221 /* Origin attribute. */
2222 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2223 stream_putc (s, BGP_ATTR_ORIGIN);
2224 stream_putc (s, 1);
2225 stream_putc (s, attr->origin);
2226
2227 /* AS path attribute. */
2228
2229 /* If remote-peer is EBGP */
2230 if (peer->sort == BGP_PEER_EBGP
2231 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
2232 || attr->aspath->segments == NULL)
2233 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
2234 {
2235 aspath = aspath_dup (attr->aspath);
2236
2237 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2238 {
2239 /* Strip the confed info, and then stuff our path CONFED_ID
2240 on the front */
2241 aspath = aspath_delete_confed_seq (aspath);
2242 aspath = aspath_add_seq (aspath, bgp->confed_id);
2243 }
2244 else
2245 {
2246 if (peer->change_local_as) {
2247 /* If replace-as is specified, we only use the change_local_as when
2248 advertising routes. */
2249 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2250 aspath = aspath_add_seq (aspath, peer->local_as);
2251 }
2252 aspath = aspath_add_seq (aspath, peer->change_local_as);
2253 } else {
2254 aspath = aspath_add_seq (aspath, peer->local_as);
2255 }
2256 }
2257 }
2258 else if (peer->sort == BGP_PEER_CONFED)
2259 {
2260 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2261 aspath = aspath_dup (attr->aspath);
2262 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2263 }
2264 else
2265 aspath = attr->aspath;
2266
2267 /* If peer is not AS4 capable, then:
2268 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2269 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2270 * types are in it (i.e. exclude them if they are there)
2271 * AND do this only if there is at least one asnum > 65535 in the path!
2272 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2273 * all ASnums > 65535 to BGP_AS_TRANS
2274 */
2275
2276 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2277 stream_putc (s, BGP_ATTR_AS_PATH);
2278 aspath_sizep = stream_get_endp (s);
2279 stream_putw (s, 0);
2280 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2281
2282 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2283 * in the path
2284 */
2285 if (!use32bit && aspath_has_as4 (aspath))
2286 send_as4_path = 1; /* we'll do this later, at the correct place */
2287
2288 /* Nexthop attribute. */
2289 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
2290 {
2291 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2292 stream_putc (s, BGP_ATTR_NEXT_HOP);
2293 stream_putc (s, 4);
2294 if (safi == SAFI_MPLS_VPN)
2295 {
2296 if (attr->nexthop.s_addr == 0)
2297 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2298 else
2299 stream_put_ipv4 (s, attr->nexthop.s_addr);
2300 }
2301 else
2302 stream_put_ipv4 (s, attr->nexthop.s_addr);
2303 }
2304
2305 /* MED attribute. */
2306 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) ||
2307 bgp->maxmed_active)
2308 {
2309 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2310 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2311 stream_putc (s, 4);
2312 stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med));
2313 }
2314
2315 /* Local preference. */
2316 if (peer->sort == BGP_PEER_IBGP ||
2317 peer->sort == BGP_PEER_CONFED)
2318 {
2319 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2320 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2321 stream_putc (s, 4);
2322 stream_putl (s, attr->local_pref);
2323 }
2324
2325 /* Atomic aggregate. */
2326 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2327 {
2328 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2329 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2330 stream_putc (s, 0);
2331 }
2332
2333 /* Aggregator. */
2334 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2335 {
2336 assert (attr->extra);
2337
2338 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
2339 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2340 stream_putc (s, BGP_ATTR_AGGREGATOR);
2341
2342 if (use32bit)
2343 {
2344 /* AS4 capable peer */
2345 stream_putc (s, 8);
2346 stream_putl (s, attr->extra->aggregator_as);
2347 }
2348 else
2349 {
2350 /* 2-byte AS peer */
2351 stream_putc (s, 6);
2352
2353 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2354 if ( attr->extra->aggregator_as > 65535 )
2355 {
2356 stream_putw (s, BGP_AS_TRANS);
2357
2358 /* we have to send AS4_AGGREGATOR, too.
2359 * we'll do that later in order to send attributes in ascending
2360 * order.
2361 */
2362 send_as4_aggregator = 1;
2363 }
2364 else
2365 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2366 }
2367 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2368 }
2369
2370 /* Community attribute. */
2371 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2372 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2373 {
2374 if (attr->community->size * 4 > 255)
2375 {
2376 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2377 stream_putc (s, BGP_ATTR_COMMUNITIES);
2378 stream_putw (s, attr->community->size * 4);
2379 }
2380 else
2381 {
2382 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2383 stream_putc (s, BGP_ATTR_COMMUNITIES);
2384 stream_putc (s, attr->community->size * 4);
2385 }
2386 stream_put (s, attr->community->val, attr->community->size * 4);
2387 }
2388
2389 /* Route Reflector. */
2390 if (peer->sort == BGP_PEER_IBGP
2391 && from
2392 && from->sort == BGP_PEER_IBGP)
2393 {
2394 /* Originator ID. */
2395 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2396 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2397 stream_putc (s, 4);
2398
2399 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
2400 stream_put_in_addr (s, &attr->extra->originator_id);
2401 else
2402 stream_put_in_addr (s, &from->remote_id);
2403
2404 /* Cluster list. */
2405 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2406 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2407
2408 if (attr->extra && attr->extra->cluster)
2409 {
2410 stream_putc (s, attr->extra->cluster->length + 4);
2411 /* If this peer configuration's parent BGP has cluster_id. */
2412 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2413 stream_put_in_addr (s, &bgp->cluster_id);
2414 else
2415 stream_put_in_addr (s, &bgp->router_id);
2416 stream_put (s, attr->extra->cluster->list,
2417 attr->extra->cluster->length);
2418 }
2419 else
2420 {
2421 stream_putc (s, 4);
2422 /* If this peer configuration's parent BGP has cluster_id. */
2423 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2424 stream_put_in_addr (s, &bgp->cluster_id);
2425 else
2426 stream_put_in_addr (s, &bgp->router_id);
2427 }
2428 }
2429
2430 /* Extended Communities attribute. */
2431 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2432 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2433 {
2434 struct attr_extra *attre = attr->extra;
2435
2436 assert (attre);
2437
2438 if (peer->sort == BGP_PEER_IBGP
2439 || peer->sort == BGP_PEER_CONFED)
2440 {
2441 if (attre->ecommunity->size * 8 > 255)
2442 {
2443 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2444 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2445 stream_putw (s, attre->ecommunity->size * 8);
2446 }
2447 else
2448 {
2449 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2450 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2451 stream_putc (s, attre->ecommunity->size * 8);
2452 }
2453 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
2454 }
2455 else
2456 {
2457 u_int8_t *pnt;
2458 int tbit;
2459 int ecom_tr_size = 0;
2460 int i;
2461
2462 for (i = 0; i < attre->ecommunity->size; i++)
2463 {
2464 pnt = attre->ecommunity->val + (i * 8);
2465 tbit = *pnt;
2466
2467 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2468 continue;
2469
2470 ecom_tr_size++;
2471 }
2472
2473 if (ecom_tr_size)
2474 {
2475 if (ecom_tr_size * 8 > 255)
2476 {
2477 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2478 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2479 stream_putw (s, ecom_tr_size * 8);
2480 }
2481 else
2482 {
2483 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2484 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2485 stream_putc (s, ecom_tr_size * 8);
2486 }
2487
2488 for (i = 0; i < attre->ecommunity->size; i++)
2489 {
2490 pnt = attre->ecommunity->val + (i * 8);
2491 tbit = *pnt;
2492
2493 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2494 continue;
2495
2496 stream_put (s, pnt, 8);
2497 }
2498 }
2499 }
2500 }
2501
2502 if ( send_as4_path )
2503 {
2504 /* If the peer is NOT As4 capable, AND */
2505 /* there are ASnums > 65535 in path THEN
2506 * give out AS4_PATH */
2507
2508 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2509 * path segments!
2510 * Hm, I wonder... confederation things *should* only be at
2511 * the beginning of an aspath, right? Then we should use
2512 * aspath_delete_confed_seq for this, because it is already
2513 * there! (JK)
2514 * Folks, talk to me: what is reasonable here!?
2515 */
2516 aspath = aspath_delete_confed_seq (aspath);
2517
2518 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2519 stream_putc (s, BGP_ATTR_AS4_PATH);
2520 aspath_sizep = stream_get_endp (s);
2521 stream_putw (s, 0);
2522 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2523 }
2524
2525 if (aspath != attr->aspath)
2526 aspath_free (aspath);
2527
2528 if ( send_as4_aggregator )
2529 {
2530 assert (attr->extra);
2531
2532 /* send AS4_AGGREGATOR, at this place */
2533 /* this section of code moved here in order to ensure the correct
2534 * *ascending* order of attributes
2535 */
2536 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2537 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2538 stream_putc (s, 8);
2539 stream_putl (s, attr->extra->aggregator_as);
2540 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2541 }
2542
2543 /* Unknown transit attribute. */
2544 if (attr->extra && attr->extra->transit)
2545 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
2546
2547 /* Return total size of attribute. */
2548 return stream_get_endp (s) - cp;
2549 }
2550
2551 size_t
2552 bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
2553 {
2554 unsigned long attrlen_pnt;
2555
2556 /* Set extended bit always to encode the attribute length as 2 bytes */
2557 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2558 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2559
2560 attrlen_pnt = stream_get_endp (s);
2561 stream_putw (s, 0); /* Length of this attribute. */
2562
2563 stream_putw (s, afi);
2564 safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi;
2565 stream_putc (s, safi);
2566 return attrlen_pnt;
2567 }
2568
2569 void
2570 bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2571 afi_t afi, safi_t safi, struct prefix_rd *prd,
2572 u_char *tag)
2573 {
2574 if (safi == SAFI_MPLS_VPN)
2575 {
2576 stream_putc (s, p->prefixlen + 88);
2577 stream_put (s, tag, 3);
2578 stream_put (s, prd->val, 8);
2579 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2580 }
2581 else
2582 stream_put_prefix (s, p);
2583 }
2584
2585 void
2586 bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2587 {
2588 bgp_size_t size;
2589
2590 /* Set MP attribute length. Don't count the (2) bytes used to encode
2591 the attr length */
2592 size = stream_get_endp (s) - attrlen_pnt - 2;
2593 stream_putw_at (s, attrlen_pnt, size);
2594 }
2595
2596 /* Initialization of attribute. */
2597 void
2598 bgp_attr_init (void)
2599 {
2600 aspath_init ();
2601 attrhash_init ();
2602 community_init ();
2603 ecommunity_init ();
2604 cluster_init ();
2605 transit_init ();
2606 }
2607
2608 void
2609 bgp_attr_finish (void)
2610 {
2611 aspath_finish ();
2612 attrhash_finish ();
2613 community_finish ();
2614 ecommunity_finish ();
2615 cluster_finish ();
2616 transit_finish ();
2617 }
2618
2619 /* Make attribute packet. */
2620 void
2621 bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2622 struct prefix *prefix)
2623 {
2624 unsigned long cp;
2625 unsigned long len;
2626 size_t aspath_lenp;
2627 struct aspath *aspath;
2628
2629 /* Remember current pointer. */
2630 cp = stream_get_endp (s);
2631
2632 /* Place holder of length. */
2633 stream_putw (s, 0);
2634
2635 /* Origin attribute. */
2636 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2637 stream_putc (s, BGP_ATTR_ORIGIN);
2638 stream_putc (s, 1);
2639 stream_putc (s, attr->origin);
2640
2641 aspath = attr->aspath;
2642
2643 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2644 stream_putc (s, BGP_ATTR_AS_PATH);
2645 aspath_lenp = stream_get_endp (s);
2646 stream_putw (s, 0);
2647
2648 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
2649
2650 /* Nexthop attribute. */
2651 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2652 if(prefix != NULL
2653 #ifdef HAVE_IPV6
2654 && prefix->family != AF_INET6
2655 #endif /* HAVE_IPV6 */
2656 )
2657 {
2658 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2659 stream_putc (s, BGP_ATTR_NEXT_HOP);
2660 stream_putc (s, 4);
2661 stream_put_ipv4 (s, attr->nexthop.s_addr);
2662 }
2663
2664 /* MED attribute. */
2665 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2666 {
2667 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2668 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2669 stream_putc (s, 4);
2670 stream_putl (s, attr->med);
2671 }
2672
2673 /* Local preference. */
2674 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2675 {
2676 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2677 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2678 stream_putc (s, 4);
2679 stream_putl (s, attr->local_pref);
2680 }
2681
2682 /* Atomic aggregate. */
2683 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2684 {
2685 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2686 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2687 stream_putc (s, 0);
2688 }
2689
2690 /* Aggregator. */
2691 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2692 {
2693 assert (attr->extra);
2694 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2695 stream_putc (s, BGP_ATTR_AGGREGATOR);
2696 stream_putc (s, 8);
2697 stream_putl (s, attr->extra->aggregator_as);
2698 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2699 }
2700
2701 /* Community attribute. */
2702 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2703 {
2704 if (attr->community->size * 4 > 255)
2705 {
2706 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2707 stream_putc (s, BGP_ATTR_COMMUNITIES);
2708 stream_putw (s, attr->community->size * 4);
2709 }
2710 else
2711 {
2712 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2713 stream_putc (s, BGP_ATTR_COMMUNITIES);
2714 stream_putc (s, attr->community->size * 4);
2715 }
2716 stream_put (s, attr->community->val, attr->community->size * 4);
2717 }
2718
2719 #ifdef HAVE_IPV6
2720 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
2721 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2722 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
2723 {
2724 int sizep;
2725 struct attr_extra *attre = attr->extra;
2726
2727 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2728 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
2729 sizep = stream_get_endp (s);
2730
2731 /* MP header */
2732 stream_putc (s, 0); /* Marker: Attribute length. */
2733 stream_putw(s, AFI_IP6); /* AFI */
2734 stream_putc(s, SAFI_UNICAST); /* SAFI */
2735
2736 /* Next hop */
2737 stream_putc(s, attre->mp_nexthop_len);
2738 stream_put(s, &attre->mp_nexthop_global, 16);
2739 if (attre->mp_nexthop_len == 32)
2740 stream_put(s, &attre->mp_nexthop_local, 16);
2741
2742 /* SNPA */
2743 stream_putc(s, 0);
2744
2745 /* Prefix */
2746 stream_put_prefix(s, prefix);
2747
2748 /* Set MP attribute length. */
2749 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
2750 }
2751 #endif /* HAVE_IPV6 */
2752
2753 /* Return total size of attribute. */
2754 len = stream_get_endp (s) - cp - 2;
2755 stream_putw_at (s, cp, len);
2756 }