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