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