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