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