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