blob: cad9168d7106bc472cff2a7336a918bc638f3b56 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP attributes management routines.
2 Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-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
32#include "bgpd/bgpd.h"
33#include "bgpd/bgp_attr.h"
34#include "bgpd/bgp_route.h"
35#include "bgpd/bgp_aspath.h"
36#include "bgpd/bgp_community.h"
37#include "bgpd/bgp_debug.h"
38#include "bgpd/bgp_packet.h"
39#include "bgpd/bgp_ecommunity.h"
40
41/* Attribute strings for logging. */
42struct message attr_str [] =
43{
44 { BGP_ATTR_ORIGIN, "ORIGIN" },
45 { BGP_ATTR_AS_PATH, "AS_PATH" },
46 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
47 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
48 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
49 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
50 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
51 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
52 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
53 { BGP_ATTR_CLUSTER_LIST, "CLUSTERLIST" },
54 { BGP_ATTR_DPA, "DPA" },
55 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
56 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
57 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
58 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
59 { 0, NULL }
60};
61
62struct hash *cluster_hash;
63
64void *
65cluster_hash_alloc (struct cluster_list *val)
66{
67 struct cluster_list *cluster;
68
69 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
70 cluster->length = val->length;
71
72 if (cluster->length)
73 {
74 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
75 memcpy (cluster->list, val->list, val->length);
76 }
77 else
78 cluster->list = NULL;
79
80 cluster->refcnt = 0;
81
82 return cluster;
83}
84
85/* Cluster list related functions. */
86struct cluster_list *
paul5228ad22004-06-04 17:58:18 +000087cluster_parse (struct in_addr * pnt, int length)
paul718e3742002-12-13 20:15:29 +000088{
89 struct cluster_list tmp;
90 struct cluster_list *cluster;
91
92 tmp.length = length;
paul5228ad22004-06-04 17:58:18 +000093 tmp.list = pnt;
paul718e3742002-12-13 20:15:29 +000094
95 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
96 cluster->refcnt++;
97 return cluster;
98}
99
100int
101cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
102{
103 int i;
104
105 for (i = 0; i < cluster->length / 4; i++)
106 if (cluster->list[i].s_addr == originator.s_addr)
107 return 1;
108 return 0;
109}
110
111unsigned int
112cluster_hash_key_make (struct cluster_list *cluster)
113{
114 unsigned int key = 0;
115 int length;
116 caddr_t pnt;
117
118 length = cluster->length;
119 pnt = (caddr_t) cluster->list;
120
121 while (length)
122 key += pnt[--length];
123
124 return key;
125}
126
127int
128cluster_hash_cmp (struct cluster_list *cluster1, struct cluster_list *cluster2)
129{
130 if (cluster1->length == cluster2->length &&
131 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0)
132 return 1;
133 return 0;
134}
135
136void
137cluster_free (struct cluster_list *cluster)
138{
139 if (cluster->list)
140 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
141 XFREE (MTYPE_CLUSTER, cluster);
142}
143
144struct cluster_list *
145cluster_dup (struct cluster_list *cluster)
146{
147 struct cluster_list *new;
148
149 new = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
150 memset (new, 0, sizeof (struct cluster_list));
151 new->length = cluster->length;
152
153 if (cluster->length)
154 {
155 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
156 memcpy (new->list, cluster->list, cluster->length);
157 }
158 else
159 new->list = NULL;
160
161 return new;
162}
163
164struct cluster_list *
165cluster_intern (struct cluster_list *cluster)
166{
167 struct cluster_list *find;
168
169 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
170 find->refcnt++;
171
172 return find;
173}
174
175void
176cluster_unintern (struct cluster_list *cluster)
177{
178 struct cluster_list *ret;
179
180 if (cluster->refcnt)
181 cluster->refcnt--;
182
183 if (cluster->refcnt == 0)
184 {
185 ret = hash_release (cluster_hash, cluster);
186 cluster_free (cluster);
187 }
188}
189
190void
191cluster_init ()
192{
193 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
194}
195
196/* Unknown transit attribute. */
197struct hash *transit_hash;
198
199void
200transit_free (struct transit *transit)
201{
202 if (transit->val)
203 XFREE (MTYPE_TRANSIT_VAL, transit->val);
204 XFREE (MTYPE_TRANSIT, transit);
205}
206
207void *
208transit_hash_alloc (struct transit *transit)
209{
210 /* Transit structure is already allocated. */
211 return transit;
212}
213
214struct transit *
215transit_intern (struct transit *transit)
216{
217 struct transit *find;
218
219 find = hash_get (transit_hash, transit, transit_hash_alloc);
220 if (find != transit)
221 transit_free (transit);
222 find->refcnt++;
223
224 return find;
225}
226
227void
228transit_unintern (struct transit *transit)
229{
230 struct transit *ret;
231
232 if (transit->refcnt)
233 transit->refcnt--;
234
235 if (transit->refcnt == 0)
236 {
237 ret = hash_release (transit_hash, transit);
238 transit_free (transit);
239 }
240}
241
242unsigned int
243transit_hash_key_make (struct transit *transit)
244{
245 unsigned int key = 0;
246 int length;
247 caddr_t pnt;
248
249 length = transit->length;
250 pnt = (caddr_t) transit->val;
251
252 while (length)
253 key += pnt[--length];
254
255 return key;
256}
257
258int
259transit_hash_cmp (struct transit *transit1, struct transit *transit2)
260{
261 if (transit1->length == transit2->length &&
262 memcmp (transit1->val, transit2->val, transit1->length) == 0)
263 return 1;
264 return 0;
265}
266
267void
268transit_init ()
269{
270 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
271}
272
273/* Attribute hash routines. */
274
275struct hash *attrhash;
276
277unsigned int
278attrhash_key_make (struct attr *attr)
279{
280 unsigned int key = 0;
281
282 key += attr->origin;
283 key += attr->nexthop.s_addr;
284 key += attr->med;
285 key += attr->local_pref;
286 key += attr->aggregator_as;
287 key += attr->aggregator_addr.s_addr;
288 key += attr->weight;
289
290 key += attr->mp_nexthop_global_in.s_addr;
291 if (attr->aspath)
292 key += aspath_key_make (attr->aspath);
293 if (attr->community)
294 key += community_hash_make (attr->community);
295 if (attr->ecommunity)
296 key += ecommunity_hash_make (attr->ecommunity);
297 if (attr->cluster)
298 key += cluster_hash_key_make (attr->cluster);
299 if (attr->transit)
300 key += transit_hash_key_make (attr->transit);
301
302#ifdef HAVE_IPV6
303 {
304 int i;
305
306 key += attr->mp_nexthop_len;
307 for (i = 0; i < 16; i++)
308 key += attr->mp_nexthop_global.s6_addr[i];
309 for (i = 0; i < 16; i++)
310 key += attr->mp_nexthop_local.s6_addr[i];
311 }
312#endif /* HAVE_IPV6 */
313
314 return key;
315}
316
317int
318attrhash_cmp (struct attr *attr1, struct attr *attr2)
319{
320 if (attr1->flag == attr2->flag
321 && attr1->origin == attr2->origin
322 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
323 && attr1->med == attr2->med
324 && attr1->local_pref == attr2->local_pref
325 && attr1->aggregator_as == attr2->aggregator_as
326 && attr1->aggregator_addr.s_addr == attr2->aggregator_addr.s_addr
327 && attr1->weight == attr2->weight
328#ifdef HAVE_IPV6
329 && attr1->mp_nexthop_len == attr2->mp_nexthop_len
330 && IPV6_ADDR_SAME (&attr1->mp_nexthop_global, &attr2->mp_nexthop_global)
331 && IPV6_ADDR_SAME (&attr1->mp_nexthop_local, &attr2->mp_nexthop_local)
332#endif /* HAVE_IPV6 */
333 && IPV4_ADDR_SAME (&attr1->mp_nexthop_global_in, &attr2->mp_nexthop_global_in)
334 && attr1->aspath == attr2->aspath
335 && attr1->community == attr2->community
336 && attr1->ecommunity == attr2->ecommunity
337 && attr1->cluster == attr2->cluster
338 && attr1->transit == attr2->transit)
339 return 1;
340 else
341 return 0;
342}
343
344void
345attrhash_init ()
346{
347 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
348}
349
350void
351attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
352{
353 struct attr *attr = backet->data;
354
355 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
356 inet_ntoa (attr->nexthop), VTY_NEWLINE);
357}
358
359void
360attr_show_all (struct vty *vty)
361{
362 hash_iterate (attrhash,
363 (void (*)(struct hash_backet *, void *))
364 attr_show_all_iterator,
365 vty);
366}
367
368void *
369bgp_attr_hash_alloc (struct attr *val)
370{
371 struct attr *attr;
372
373 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
374 *attr = *val;
375 attr->refcnt = 0;
376 return attr;
377}
378
379/* Internet argument attribute. */
380struct attr *
381bgp_attr_intern (struct attr *attr)
382{
383 struct attr *find;
384
385 /* Intern referenced strucutre. */
386 if (attr->aspath)
387 {
388 if (! attr->aspath->refcnt)
389 attr->aspath = aspath_intern (attr->aspath);
390 else
391 attr->aspath->refcnt++;
392 }
393 if (attr->community)
394 {
395 if (! attr->community->refcnt)
396 attr->community = community_intern (attr->community);
397 else
398 attr->community->refcnt++;
399 }
400 if (attr->ecommunity)
401 {
402 if (! attr->ecommunity->refcnt)
403 attr->ecommunity = ecommunity_intern (attr->ecommunity);
404 else
405 attr->ecommunity->refcnt++;
406 }
407 if (attr->cluster)
408 {
409 if (! attr->cluster->refcnt)
410 attr->cluster = cluster_intern (attr->cluster);
411 else
412 attr->cluster->refcnt++;
413 }
414 if (attr->transit)
415 {
416 if (! attr->transit->refcnt)
417 attr->transit = transit_intern (attr->transit);
418 else
419 attr->transit->refcnt++;
420 }
421
422 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
423 find->refcnt++;
424
425 return find;
426}
427
428/* Make network statement's attribute. */
429struct attr *
430bgp_attr_default_set (struct attr *attr, u_char origin)
431{
432 memset (attr, 0, sizeof (struct attr));
433
434 attr->origin = origin;
435 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
436 attr->aspath = aspath_empty ();
437 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
438 attr->weight = 32768;
439 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
440#ifdef HAVE_IPV6
441 attr->mp_nexthop_len = 16;
442#endif
443 return attr;
444}
445
446/* Make network statement's attribute. */
447struct attr *
448bgp_attr_default_intern (u_char origin)
449{
450 struct attr attr;
451 struct attr *new;
452
453 memset (&attr, 0, sizeof (struct attr));
454
455 attr.origin = origin;
456 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
457 attr.aspath = aspath_empty ();
458 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
459 attr.weight = 32768;
460 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
461#ifdef HAVE_IPV6
462 attr.mp_nexthop_len = 16;
463#endif
464
465 new = bgp_attr_intern (&attr);
466 aspath_unintern (new->aspath);
467 return new;
468}
469
470struct attr *
471bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
472 struct aspath *aspath,
473 struct community *community, int as_set)
474{
475 struct attr attr;
476 struct attr *new;
477
478 memset (&attr, 0, sizeof (struct attr));
479
480 /* Origin attribute. */
481 attr.origin = origin;
482 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
483
484 /* AS path attribute. */
485 if (aspath)
486 attr.aspath = aspath_intern (aspath);
487 else
488 attr.aspath = aspath_empty ();
489 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
490
491 /* Next hop attribute. */
492 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
493
494 if (community)
495 {
496 attr.community = community;
497 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
498 }
499
500 attr.weight = 32768;
501#ifdef HAVE_IPV6
502 attr.mp_nexthop_len = 16;
503#endif
504 if (! as_set)
505 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
506 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
507 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
508 attr.aggregator_as = bgp->confed_id;
509 else
510 attr.aggregator_as = bgp->as;
511 attr.aggregator_addr = bgp->router_id;
512
513 new = bgp_attr_intern (&attr);
514 aspath_unintern (new->aspath);
515 return new;
516}
517
518/* Free bgp attribute and aspath. */
519void
520bgp_attr_unintern (struct attr *attr)
521{
522 struct attr *ret;
523 struct aspath *aspath;
524 struct community *community;
525 struct ecommunity *ecommunity;
526 struct cluster_list *cluster;
527 struct transit *transit;
528
529 /* Decrement attribute reference. */
530 attr->refcnt--;
531 aspath = attr->aspath;
532 community = attr->community;
533 ecommunity = attr->ecommunity;
534 cluster = attr->cluster;
535 transit = attr->transit;
536
537 /* If reference becomes zero then free attribute object. */
538 if (attr->refcnt == 0)
539 {
540 ret = hash_release (attrhash, attr);
541 assert (ret != NULL);
542 XFREE (MTYPE_ATTR, attr);
543 }
544
545 /* aspath refcount shoud be decrement. */
546 if (aspath)
547 aspath_unintern (aspath);
548 if (community)
549 community_unintern (community);
550 if (ecommunity)
551 ecommunity_unintern (ecommunity);
552 if (cluster)
553 cluster_unintern (cluster);
554 if (transit)
555 transit_unintern (transit);
556}
557
558void
559bgp_attr_flush (struct attr *attr)
560{
561 if (attr->aspath && ! attr->aspath->refcnt)
562 aspath_free (attr->aspath);
563 if (attr->community && ! attr->community->refcnt)
564 community_free (attr->community);
565 if (attr->ecommunity && ! attr->ecommunity->refcnt)
566 ecommunity_free (attr->ecommunity);
567 if (attr->cluster && ! attr->cluster->refcnt)
568 cluster_free (attr->cluster);
569 if (attr->transit && ! attr->transit->refcnt)
570 transit_free (attr->transit);
571}
572
573/* Get origin attribute of the update message. */
574int
575bgp_attr_origin (struct peer *peer, bgp_size_t length,
576 struct attr *attr, u_char flag, u_char *startp)
577{
578 bgp_size_t total;
579
580 /* total is entire attribute length include Attribute Flags (1),
581 Attribute Type code (1) and Attribute length (1 or 2). */
582 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
583
584 /* If any recognized attribute has Attribute Flags that conflict
585 with the Attribute Type Code, then the Error Subcode is set to
586 Attribute Flags Error. The Data field contains the erroneous
587 attribute (type, length and value). */
588 if (flag != BGP_ATTR_FLAG_TRANS)
589 {
590 zlog (peer->log, LOG_ERR,
591 "Origin attribute flag isn't transitive %d", flag);
592 bgp_notify_send_with_data (peer,
593 BGP_NOTIFY_UPDATE_ERR,
594 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
595 startp, total);
596 return -1;
597 }
598
599 /* If any recognized attribute has Attribute Length that conflicts
600 with the expected length (based on the attribute type code), then
601 the Error Subcode is set to Attribute Length Error. The Data
602 field contains the erroneous attribute (type, length and
603 value). */
604 if (length != 1)
605 {
606 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
607 length);
608 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR,
609 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
610 startp, total);
611 return -1;
612 }
613
614 /* Fetch origin attribute. */
615 attr->origin = stream_getc (BGP_INPUT (peer));
616
617 /* If the ORIGIN attribute has an undefined value, then the Error
618 Subcode is set to Invalid Origin Attribute. The Data field
619 contains the unrecognized attribute (type, length and value). */
620 if ((attr->origin != BGP_ORIGIN_IGP)
621 && (attr->origin != BGP_ORIGIN_EGP)
622 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
623 {
624 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
625 attr->origin);
626
627 bgp_notify_send_with_data (peer,
628 BGP_NOTIFY_UPDATE_ERR,
629 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
630 startp, total);
631 return -1;
632 }
633
634 /* Set oring attribute flag. */
635 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
636
637 return 0;
638}
639
640/* Parse AS path information. This function is wrapper of
641 aspath_parse. */
642int
643bgp_attr_aspath (struct peer *peer, bgp_size_t length,
644 struct attr *attr, u_char flag, u_char *startp)
645{
646 struct bgp *bgp;
647 struct aspath *aspath;
648 bgp_size_t total;
649
650 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
651
652 /* Flag check. */
653 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
654 || ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
655 {
656 zlog (peer->log, LOG_ERR,
657 "Origin attribute flag isn't transitive %d", flag);
658 bgp_notify_send_with_data (peer,
659 BGP_NOTIFY_UPDATE_ERR,
660 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
661 startp, total);
662 return -1;
663 }
664
665 /* In case of IBGP, length will be zero. */
666 attr->aspath = aspath_parse (stream_pnt (peer->ibuf), length);
667 if (! attr->aspath)
668 {
669 zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);
670 bgp_notify_send (peer,
671 BGP_NOTIFY_UPDATE_ERR,
672 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
673 return -1;
674 }
675
676 bgp = peer->bgp;
677
678 /* First AS check for EBGP. */
679 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
680 {
681 if (peer_sort (peer) == BGP_PEER_EBGP
682 && ! aspath_firstas_check (attr->aspath, peer->as))
683 {
684 zlog (peer->log, LOG_ERR,
685 "%s incorrect first AS (must be %d)", peer->host, peer->as);
686 bgp_notify_send (peer,
687 BGP_NOTIFY_UPDATE_ERR,
688 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
689 return -1;
690 }
691 }
692
693 /* local-as prepend */
694 if (peer->change_local_as &&
695 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
696 {
697 aspath = aspath_dup (attr->aspath);
698 aspath = aspath_add_seq (aspath, peer->change_local_as);
699 aspath_unintern (attr->aspath);
700 attr->aspath = aspath_intern (aspath);
701 }
702
703 /* Forward pointer. */
704 stream_forward (peer->ibuf, length);
705
706 /* Set aspath attribute flag. */
707 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
708
709 return 0;
710}
711
712/* Nexthop attribute. */
713int
714bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
715 struct attr *attr, u_char flag, u_char *startp)
716{
717 bgp_size_t total;
718
719 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
720
721 /* Flag check. */
722 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
723 || ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
724 {
725 zlog (peer->log, LOG_ERR,
726 "Origin attribute flag isn't transitive %d", flag);
727 bgp_notify_send_with_data (peer,
728 BGP_NOTIFY_UPDATE_ERR,
729 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
730 startp, total);
731 return -1;
732 }
733
734 /* Check nexthop attribute length. */
735 if (length != 4)
736 {
737 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
738 length);
739
740 bgp_notify_send_with_data (peer,
741 BGP_NOTIFY_UPDATE_ERR,
742 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
743 startp, total);
744 return -1;
745 }
746
747 attr->nexthop.s_addr = stream_get_ipv4 (peer->ibuf);
748 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
749
750 return 0;
751}
752
753/* MED atrribute. */
754int
755bgp_attr_med (struct peer *peer, bgp_size_t length,
756 struct attr *attr, u_char flag, u_char *startp)
757{
758 bgp_size_t total;
759
760 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
761
762 /* Length check. */
763 if (length != 4)
764 {
765 zlog (peer->log, LOG_ERR,
766 "MED attribute length isn't four [%d]", length);
767
768 bgp_notify_send_with_data (peer,
769 BGP_NOTIFY_UPDATE_ERR,
770 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
771 startp, total);
772 return -1;
773 }
774
775 attr->med = stream_getl (peer->ibuf);
776
777 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
778
779 return 0;
780}
781
782/* Local preference attribute. */
783int
784bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
785 struct attr *attr, u_char flag)
786{
787 /* If it is contained in an UPDATE message that is received from an
788 external peer, then this attribute MUST be ignored by the
789 receiving speaker. */
790 if (peer_sort (peer) == BGP_PEER_EBGP)
791 {
792 stream_forward (peer->ibuf, length);
793 return 0;
794 }
795
796 if (length == 4)
797 attr->local_pref = stream_getl (peer->ibuf);
798 else
799 attr->local_pref = 0;
800
801 /* Set atomic aggregate flag. */
802 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
803
804 return 0;
805}
806
807/* Atomic aggregate. */
808int
809bgp_attr_atomic (struct peer *peer, bgp_size_t length,
810 struct attr *attr, u_char flag)
811{
812 if (length != 0)
813 {
814 zlog (peer->log, LOG_ERR, "Bad atomic aggregate length %d", length);
815
816 bgp_notify_send (peer,
817 BGP_NOTIFY_UPDATE_ERR,
818 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
819 return -1;
820 }
821
822 /* Set atomic aggregate flag. */
823 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
824
825 return 0;
826}
827
828/* Aggregator attribute */
829int
830bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
831 struct attr *attr, u_char flag)
832{
833 if (length != 6)
834 {
835 zlog (peer->log, LOG_ERR, "Aggregator length is not 6 [%d]", length);
836
837 bgp_notify_send (peer,
838 BGP_NOTIFY_UPDATE_ERR,
839 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
840 return -1;
841 }
842 attr->aggregator_as = stream_getw (peer->ibuf);
843 attr->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
844
845 /* Set atomic aggregate flag. */
846 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
847
848 return 0;
849}
850
851/* Community attribute. */
852int
853bgp_attr_community (struct peer *peer, bgp_size_t length,
854 struct attr *attr, u_char flag)
855{
856 if (length == 0)
857 attr->community = NULL;
858 else
859 {
paul5228ad22004-06-04 17:58:18 +0000860 attr->community =
861 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
paul718e3742002-12-13 20:15:29 +0000862 stream_forward (peer->ibuf, length);
863 }
864
865 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
866
867 return 0;
868}
869
870/* Originator ID attribute. */
871int
872bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
873 struct attr *attr, u_char flag)
874{
875 if (length != 4)
876 {
877 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
878
879 bgp_notify_send (peer,
880 BGP_NOTIFY_UPDATE_ERR,
881 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
882 return -1;
883 }
884
885 attr->originator_id.s_addr = stream_get_ipv4 (peer->ibuf);
886
887 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
888
889 return 0;
890}
891
892/* Cluster list attribute. */
893int
894bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
895 struct attr *attr, u_char flag)
896{
897 /* Check length. */
898 if (length % 4)
899 {
900 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
901
902 bgp_notify_send (peer,
903 BGP_NOTIFY_UPDATE_ERR,
904 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
905 return -1;
906 }
907
paul5228ad22004-06-04 17:58:18 +0000908 attr->cluster = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf),
909 length);
paul718e3742002-12-13 20:15:29 +0000910
911 stream_forward (peer->ibuf, length);;
912
913 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
914
915 return 0;
916}
917
918/* Multiprotocol reachability information parse. */
919int
920bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
921 struct bgp_nlri *mp_update)
922{
923 u_int16_t afi;
924 u_char safi;
925 u_char snpa_num;
926 u_char snpa_len;
927 u_char *lim;
928 bgp_size_t nlri_len;
929 int ret;
930 struct stream *s;
931
932 /* Set end of packet. */
933 s = peer->ibuf;
934 lim = stream_pnt (s) + length;
935
936 /* Load AFI, SAFI. */
937 afi = stream_getw (s);
938 safi = stream_getc (s);
939
940 /* Get nexthop length. */
941 attr->mp_nexthop_len = stream_getc (s);
942
943 /* Nexthop length check. */
944 switch (attr->mp_nexthop_len)
945 {
946 case 4:
947 stream_get (&attr->mp_nexthop_global_in, s, 4);
948 break;
949 case 12:
950 {
951 u_int32_t rd_high;
952 u_int32_t rd_low;
953
954 rd_high = stream_getl (s);
955 rd_low = stream_getl (s);
956 stream_get (&attr->mp_nexthop_global_in, s, 4);
957 }
958 break;
959#ifdef HAVE_IPV6
960 case 16:
961 stream_get (&attr->mp_nexthop_global, s, 16);
962 break;
963 case 32:
964 stream_get (&attr->mp_nexthop_global, s, 16);
965 stream_get (&attr->mp_nexthop_local, s, 16);
966 if (! IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local))
967 {
968 char buf1[INET6_ADDRSTRLEN];
969 char buf2[INET6_ADDRSTRLEN];
970
971 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +0000972 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
paul718e3742002-12-13 20:15:29 +0000973 inet_ntop (AF_INET6, &attr->mp_nexthop_global,
974 buf1, INET6_ADDRSTRLEN),
975 inet_ntop (AF_INET6, &attr->mp_nexthop_local,
976 buf2, INET6_ADDRSTRLEN));
977
978 attr->mp_nexthop_len = 16;
979 }
980 break;
981#endif /* HAVE_IPV6 */
982 default:
983 zlog_info ("Wrong multiprotocol next hop length: %d",
984 attr->mp_nexthop_len);
985 return -1;
986 break;
987 }
988
989 snpa_num = stream_getc (s);
990
991 while (snpa_num--)
992 {
993 snpa_len = stream_getc (s);
994 stream_forward (s, (snpa_len + 1) >> 1);
995 }
996
997 /* If peer is based on old draft-00. I read NLRI length from the
998 packet. */
999 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1000 {
1001 bgp_size_t nlri_total_len;
1002 nlri_total_len = stream_getw (s);
1003 }
1004
1005 nlri_len = lim - stream_pnt (s);
1006
1007 if (safi != BGP_SAFI_VPNV4)
1008 {
1009 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
1010 if (ret < 0)
1011 return -1;
1012 }
1013
1014 mp_update->afi = afi;
1015 mp_update->safi = safi;
1016 mp_update->nlri = stream_pnt (s);
1017 mp_update->length = nlri_len;
1018
1019 stream_forward (s, nlri_len);
1020
1021 return 0;
1022}
1023
1024/* Multiprotocol unreachable parse */
1025int
1026bgp_mp_unreach_parse (struct peer *peer, int length,
1027 struct bgp_nlri *mp_withdraw)
1028{
1029 struct stream *s;
1030 u_int16_t afi;
1031 u_char safi;
1032 u_char *lim;
1033 u_int16_t withdraw_len;
1034 int ret;
1035
1036 s = peer->ibuf;
1037 lim = stream_pnt (s) + length;
1038
1039 afi = stream_getw (s);
1040 safi = stream_getc (s);
1041
1042 withdraw_len = lim - stream_pnt (s);
1043
1044 if (safi != BGP_SAFI_VPNV4)
1045 {
1046 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
1047 if (ret < 0)
1048 return -1;
1049 }
1050
1051 mp_withdraw->afi = afi;
1052 mp_withdraw->safi = safi;
1053 mp_withdraw->nlri = stream_pnt (s);
1054 mp_withdraw->length = withdraw_len;
1055
1056 stream_forward (s, withdraw_len);
1057
1058 return 0;
1059}
1060
1061/* Extended Community attribute. */
1062int
1063bgp_attr_ext_communities (struct peer *peer, bgp_size_t length,
1064 struct attr *attr, u_char flag)
1065{
1066 if (length == 0)
1067 attr->ecommunity = NULL;
1068 else
1069 {
paul5228ad22004-06-04 17:58:18 +00001070 attr->ecommunity =
1071 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
paul718e3742002-12-13 20:15:29 +00001072 stream_forward (peer->ibuf, length);
1073 }
1074 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1075
1076 return 0;
1077}
1078
1079/* BGP unknown attribute treatment. */
1080int
1081bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
1082 u_char type, bgp_size_t length, u_char *startp)
1083{
1084 bgp_size_t total;
1085 struct transit *transit;
1086
hassof4184462005-02-01 20:13:16 +00001087 if (BGP_DEBUG (normal, NORMAL))
1088 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1089 peer->host, type, length);
1090
paul718e3742002-12-13 20:15:29 +00001091 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001092 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001093 "Unknown attribute type %d length %d is received", type, length);
1094
1095 /* Forward read pointer of input stream. */
1096 stream_forward (peer->ibuf, length);
1097
1098 /* Adjest total length to include type and length. */
1099 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1100
1101 /* If any of the mandatory well-known attributes are not recognized,
1102 then the Error Subcode is set to Unrecognized Well-known
1103 Attribute. The Data field contains the unrecognized attribute
1104 (type, length and value). */
1105 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
1106 {
1107 /* Adjust startp to do not include flag value. */
1108 bgp_notify_send_with_data (peer,
1109 BGP_NOTIFY_UPDATE_ERR,
1110 BGP_NOTIFY_UPDATE_UNREC_ATTR,
1111 startp, total);
1112 return -1;
1113 }
1114
1115 /* Unrecognized non-transitive optional attributes must be quietly
1116 ignored and not passed along to other BGP peers. */
1117 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
1118 return 0;
1119
1120 /* If a path with recognized transitive optional attribute is
1121 accepted and passed along to other BGP peers and the Partial bit
1122 in the Attribute Flags octet is set to 1 by some previous AS, it
1123 is not set back to 0 by the current AS. */
1124 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1125
1126 /* Store transitive attribute to the end of attr->transit. */
1127 if (! attr->transit)
1128 {
1129 attr->transit = XMALLOC (MTYPE_TRANSIT, sizeof (struct transit));
1130 memset (attr->transit, 0, sizeof (struct transit));
1131 }
1132
1133 transit = attr->transit;
1134
1135 if (transit->val)
1136 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1137 transit->length + total);
1138 else
1139 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1140
1141 memcpy (transit->val + transit->length, startp, total);
1142 transit->length += total;
1143
1144 return 0;
1145}
1146
1147/* Read attribute of update packet. This function is called from
1148 bgp_update() in bgpd.c. */
1149int
1150bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1151 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1152{
1153 int ret;
1154 u_char flag;
1155 u_char type;
1156 bgp_size_t length;
1157 u_char *startp, *endp;
1158 u_char *attr_endp;
1159 u_char seen[BGP_ATTR_BITMAP_SIZE];
1160
1161 /* Initialize bitmap. */
1162 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1163
1164 /* End pointer of BGP attribute. */
1165 endp = BGP_INPUT_PNT (peer) + size;
1166
1167 /* Get attributes to the end of attribute length. */
1168 while (BGP_INPUT_PNT (peer) < endp)
1169 {
1170 /* Check remaining length check.*/
1171 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1172 {
gdtc29fdba2004-12-09 14:46:46 +00001173 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00001174 zlog (peer->log, LOG_WARNING,
paula2b1ecd2004-10-31 18:58:09 +00001175 "%s error BGP attribute length %ld is smaller than min len",
paul718e3742002-12-13 20:15:29 +00001176 peer->host, endp - STREAM_PNT (BGP_INPUT (peer)));
1177
1178 bgp_notify_send (peer,
1179 BGP_NOTIFY_UPDATE_ERR,
1180 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1181 return -1;
1182 }
1183
1184 /* Fetch attribute flag and type. */
1185 startp = BGP_INPUT_PNT (peer);
1186 flag = stream_getc (BGP_INPUT (peer));
1187 type = stream_getc (BGP_INPUT (peer));
1188
1189 /* Check extended attribue length bit. */
1190 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1191 length = stream_getw (BGP_INPUT (peer));
1192 else
1193 length = stream_getc (BGP_INPUT (peer));
1194
1195 /* If any attribute appears more than once in the UPDATE
1196 message, then the Error Subcode is set to Malformed Attribute
1197 List. */
1198
1199 if (CHECK_BITMAP (seen, type))
1200 {
1201 zlog (peer->log, LOG_WARNING,
1202 "%s error BGP attribute type %d appears twice in a message",
1203 peer->host, type);
1204
1205 bgp_notify_send (peer,
1206 BGP_NOTIFY_UPDATE_ERR,
1207 BGP_NOTIFY_UPDATE_MAL_ATTR);
1208 return -1;
1209 }
1210
1211 /* Set type to bitmap to check duplicate attribute. `type' is
1212 unsigned char so it never overflow bitmap range. */
1213
1214 SET_BITMAP (seen, type);
1215
1216 /* Overflow check. */
1217 attr_endp = BGP_INPUT_PNT (peer) + length;
1218
1219 if (attr_endp > endp)
1220 {
1221 zlog (peer->log, LOG_WARNING,
1222 "%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);
1223 bgp_notify_send (peer,
1224 BGP_NOTIFY_UPDATE_ERR,
1225 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1226 return -1;
1227 }
1228
1229 /* OK check attribute and store it's value. */
1230 switch (type)
1231 {
1232 case BGP_ATTR_ORIGIN:
1233 ret = bgp_attr_origin (peer, length, attr, flag, startp);
1234 break;
1235 case BGP_ATTR_AS_PATH:
1236 ret = bgp_attr_aspath (peer, length, attr, flag, startp);
1237 break;
1238 case BGP_ATTR_NEXT_HOP:
1239 ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
1240 break;
1241 case BGP_ATTR_MULTI_EXIT_DISC:
1242 ret = bgp_attr_med (peer, length, attr, flag, startp);
1243 break;
1244 case BGP_ATTR_LOCAL_PREF:
1245 ret = bgp_attr_local_pref (peer, length, attr, flag);
1246 break;
1247 case BGP_ATTR_ATOMIC_AGGREGATE:
1248 ret = bgp_attr_atomic (peer, length, attr, flag);
1249 break;
1250 case BGP_ATTR_AGGREGATOR:
1251 ret = bgp_attr_aggregator (peer, length, attr, flag);
1252 break;
1253 case BGP_ATTR_COMMUNITIES:
1254 ret = bgp_attr_community (peer, length, attr, flag);
1255 break;
1256 case BGP_ATTR_ORIGINATOR_ID:
1257 ret = bgp_attr_originator_id (peer, length, attr, flag);
1258 break;
1259 case BGP_ATTR_CLUSTER_LIST:
1260 ret = bgp_attr_cluster_list (peer, length, attr, flag);
1261 break;
1262 case BGP_ATTR_MP_REACH_NLRI:
1263 ret = bgp_mp_reach_parse (peer, length, attr, mp_update);
1264 break;
1265 case BGP_ATTR_MP_UNREACH_NLRI:
1266 ret = bgp_mp_unreach_parse (peer, length, mp_withdraw);
1267 break;
1268 case BGP_ATTR_EXT_COMMUNITIES:
1269 ret = bgp_attr_ext_communities (peer, length, attr, flag);
1270 break;
1271 default:
1272 ret = bgp_attr_unknown (peer, attr, flag, type, length, startp);
1273 break;
1274 }
1275
1276 /* If error occured immediately return to the caller. */
1277 if (ret < 0)
1278 return ret;
1279
1280 /* Check the fetched length. */
1281 if (BGP_INPUT_PNT (peer) != attr_endp)
1282 {
1283 zlog (peer->log, LOG_WARNING,
1284 "%s BGP attribute fetch error", peer->host);
1285 bgp_notify_send (peer,
1286 BGP_NOTIFY_UPDATE_ERR,
1287 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1288 return -1;
1289 }
1290 }
1291
1292 /* Check final read pointer is same as end pointer. */
1293 if (BGP_INPUT_PNT (peer) != endp)
1294 {
1295 zlog (peer->log, LOG_WARNING,
1296 "%s BGP attribute length mismatch", peer->host);
1297 bgp_notify_send (peer,
1298 BGP_NOTIFY_UPDATE_ERR,
1299 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1300 return -1;
1301 }
1302
1303 /* Finally intern unknown attribute. */
1304 if (attr->transit)
1305 attr->transit = transit_intern (attr->transit);
1306
1307 return 0;
1308}
1309
1310/* Well-known attribute check. */
1311int
1312bgp_attr_check (struct peer *peer, struct attr *attr)
1313{
1314 u_char type = 0;
1315
1316 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
1317 type = BGP_ATTR_ORIGIN;
1318
1319 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
1320 type = BGP_ATTR_AS_PATH;
1321
1322 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
1323 type = BGP_ATTR_NEXT_HOP;
1324
1325 if (peer_sort (peer) == BGP_PEER_IBGP
1326 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
1327 type = BGP_ATTR_LOCAL_PREF;
1328
1329 if (type)
1330 {
1331 zlog (peer->log, LOG_WARNING,
1332 "%s Missing well-known attribute %d.",
1333 peer->host, type);
1334 bgp_notify_send_with_data (peer,
1335 BGP_NOTIFY_UPDATE_ERR,
1336 BGP_NOTIFY_UPDATE_MISS_ATTR,
1337 &type, 1);
1338 return -1;
1339 }
1340 return 0;
1341}
1342
1343int stream_put_prefix (struct stream *, struct prefix *);
1344
1345/* Make attribute packet. */
1346bgp_size_t
1347bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
1348 struct stream *s, struct attr *attr, struct prefix *p,
1349 afi_t afi, safi_t safi, struct peer *from,
paul5228ad22004-06-04 17:58:18 +00001350 struct prefix_rd *prd, char *tag)
paul718e3742002-12-13 20:15:29 +00001351{
1352 unsigned long cp;
1353 struct aspath *aspath;
1354
1355 if (! bgp)
1356 bgp = bgp_get_default ();
1357
1358 /* Remember current pointer. */
1359 cp = stream_get_putp (s);
1360
1361 /* Origin attribute. */
1362 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1363 stream_putc (s, BGP_ATTR_ORIGIN);
1364 stream_putc (s, 1);
1365 stream_putc (s, attr->origin);
1366
1367 /* AS path attribute. */
1368
1369 /* If remote-peer is EBGP */
1370 if (peer_sort (peer) == BGP_PEER_EBGP
1371 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
1372 || attr->aspath->length == 0)
paulfee0f4c2004-09-13 05:12:46 +00001373 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00001374 {
1375 aspath = aspath_dup (attr->aspath);
1376
1377 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
1378 {
1379 /* Strip the confed info, and then stuff our path CONFED_ID
1380 on the front */
1381 aspath = aspath_delete_confed_seq (aspath);
1382 aspath = aspath_add_seq (aspath, bgp->confed_id);
1383 }
1384 else
1385 {
1386 aspath = aspath_add_seq (aspath, peer->local_as);
1387 if (peer->change_local_as)
1388 aspath = aspath_add_seq (aspath, peer->change_local_as);
1389 }
1390 }
1391 else if (peer_sort (peer) == BGP_PEER_CONFED)
1392 {
1393 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
1394 aspath = aspath_dup (attr->aspath);
1395 aspath = aspath_add_confed_seq (aspath, peer->local_as);
1396 }
1397 else
1398 aspath = attr->aspath;
1399
1400 /* AS path attribute extended length bit check. */
1401 if (aspath->length > 255)
1402 {
1403 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1404 stream_putc (s, BGP_ATTR_AS_PATH);
1405 stream_putw (s, aspath->length);
1406 }
1407 else
1408 {
1409 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1410 stream_putc(s, BGP_ATTR_AS_PATH);
1411 stream_putc (s, aspath->length);
1412 }
1413 stream_put (s, aspath->data, aspath->length);
1414
1415 if (aspath != attr->aspath)
1416 aspath_free (aspath);
1417
1418 /* Nexthop attribute. */
1419 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
1420 {
1421 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1422 stream_putc (s, BGP_ATTR_NEXT_HOP);
1423 stream_putc (s, 4);
1424 if (safi == SAFI_MPLS_VPN)
1425 {
1426 if (attr->nexthop.s_addr == 0)
1427 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
1428 else
1429 stream_put_ipv4 (s, attr->nexthop.s_addr);
1430 }
1431 else
1432 stream_put_ipv4 (s, attr->nexthop.s_addr);
1433 }
1434
1435 /* MED attribute. */
1436 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
1437 {
1438 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1439 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
1440 stream_putc (s, 4);
1441 stream_putl (s, attr->med);
1442 }
1443
1444 /* Local preference. */
1445 if (peer_sort (peer) == BGP_PEER_IBGP ||
1446 peer_sort (peer) == BGP_PEER_CONFED)
1447 {
1448 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1449 stream_putc (s, BGP_ATTR_LOCAL_PREF);
1450 stream_putc (s, 4);
1451 stream_putl (s, attr->local_pref);
1452 }
1453
1454 /* Atomic aggregate. */
1455 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
1456 {
1457 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1458 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
1459 stream_putc (s, 0);
1460 }
1461
1462 /* Aggregator. */
1463 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
1464 {
1465 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1466 stream_putc (s, BGP_ATTR_AGGREGATOR);
1467 stream_putc (s, 6);
1468 stream_putw (s, attr->aggregator_as);
1469 stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
1470 }
1471
1472 /* Community attribute. */
1473 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
1474 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
1475 {
1476 if (attr->community->size * 4 > 255)
1477 {
1478 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1479 stream_putc (s, BGP_ATTR_COMMUNITIES);
1480 stream_putw (s, attr->community->size * 4);
1481 }
1482 else
1483 {
1484 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1485 stream_putc (s, BGP_ATTR_COMMUNITIES);
1486 stream_putc (s, attr->community->size * 4);
1487 }
1488 stream_put (s, attr->community->val, attr->community->size * 4);
1489 }
1490
1491 /* Route Reflector. */
1492 if (peer_sort (peer) == BGP_PEER_IBGP
1493 && from
1494 && peer_sort (from) == BGP_PEER_IBGP)
1495 {
1496 /* Originator ID. */
1497 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1498 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
1499 stream_putc (s, 4);
1500
1501 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1502 stream_put_in_addr (s, &attr->originator_id);
1503 else
1504 {
1505 if (from)
1506 stream_put_in_addr (s, &from->remote_id);
1507 else
1508 stream_put_in_addr (s, &attr->originator_id);
1509 }
1510
1511 /* Cluster list. */
1512 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1513 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
1514
1515 if (attr->cluster)
1516 {
1517 stream_putc (s, attr->cluster->length + 4);
1518 /* If this peer configuration's parent BGP has cluster_id. */
1519 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
1520 stream_put_in_addr (s, &bgp->cluster_id);
1521 else
1522 stream_put_in_addr (s, &bgp->router_id);
1523 stream_put (s, attr->cluster->list, attr->cluster->length);
1524 }
1525 else
1526 {
1527 stream_putc (s, 4);
1528 /* If this peer configuration's parent BGP has cluster_id. */
1529 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
1530 stream_put_in_addr (s, &bgp->cluster_id);
1531 else
1532 stream_put_in_addr (s, &bgp->router_id);
1533 }
1534 }
1535
1536#ifdef HAVE_IPV6
1537 /* If p is IPv6 address put it into attribute. */
1538 if (p->family == AF_INET6)
1539 {
1540 unsigned long sizep;
1541 unsigned long draftp = 0;
1542
1543 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1544 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
1545 sizep = stream_get_putp (s);
1546 stream_putc (s, 0); /* Length of this attribute. */
1547 stream_putw (s, AFI_IP6); /* AFI */
1548 stream_putc (s, safi); /* SAFI */
1549
1550 stream_putc (s, attr->mp_nexthop_len);
1551
1552 if (attr->mp_nexthop_len == 16)
1553 stream_put (s, &attr->mp_nexthop_global, 16);
1554 else if (attr->mp_nexthop_len == 32)
1555 {
1556 stream_put (s, &attr->mp_nexthop_global, 16);
1557 stream_put (s, &attr->mp_nexthop_local, 16);
1558 }
1559
1560 /* SNPA */
1561 stream_putc (s, 0);
1562
1563 /* In case of old draft BGP-4+. */
1564 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1565 {
1566 draftp = stream_get_putp (s);
1567 stream_putw (s, 0);
1568 }
1569
1570 /* Prefix write. */
1571 stream_put_prefix (s, p);
1572
1573 /* Set MP attribute length. */
1574 stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
1575
1576 /* In case of old draft BGP-4+. */
1577 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1578 stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
1579 }
1580#endif /* HAVE_IPV6 */
1581
1582 if (p->family == AF_INET && safi == SAFI_MULTICAST)
1583 {
1584 unsigned long sizep;
1585 unsigned long draftp = 0;
1586
1587 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1588 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
1589 sizep = stream_get_putp (s);
1590 stream_putc (s, 0); /* Length of this attribute. */
1591 stream_putw (s, AFI_IP); /* AFI */
1592 stream_putc (s, SAFI_MULTICAST); /* SAFI */
1593
1594 stream_putc (s, 4);
1595 stream_put_ipv4 (s, attr->nexthop.s_addr);
1596
1597 /* SNPA */
1598 stream_putc (s, 0);
1599
1600 /* In case of old draft BGP-4+. */
1601 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1602 {
1603 draftp = stream_get_putp (s);
1604 stream_putw (s, 0);
1605 }
1606
1607 /* Prefix write. */
1608 stream_put_prefix (s, p);
1609
1610 /* Set MP attribute length. */
1611 stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
1612
1613 /* In case of old draft BGP-4+. */
1614 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1615 stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
1616 }
1617
1618 if (p->family == AF_INET && safi == SAFI_MPLS_VPN)
1619 {
1620 unsigned long sizep;
1621 unsigned long draftp = 0;
1622
1623 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1624 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
1625 sizep = stream_get_putp (s);
1626 stream_putc (s, 0); /* Length of this attribute. */
1627 stream_putw (s, AFI_IP); /* AFI */
1628 stream_putc (s, BGP_SAFI_VPNV4); /* SAFI */
1629
1630 stream_putc (s, 12);
1631 stream_putl (s, 0);
1632 stream_putl (s, 0);
1633 stream_put (s, &attr->mp_nexthop_global_in, 4);
1634
1635 /* SNPA */
1636 stream_putc (s, 0);
1637
1638 /* In case of old draft BGP-4+. */
1639 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1640 {
1641 draftp = stream_get_putp (s);
1642 stream_putw (s, 0);
1643 }
1644
1645 /* Tag, RD, Prefix write. */
1646 stream_putc (s, p->prefixlen + 88);
1647 stream_put (s, tag, 3);
1648 stream_put (s, prd->val, 8);
1649 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
1650
1651 /* Set MP attribute length. */
1652 stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
1653
1654 /* In case of old draft BGP-4+. */
1655 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
1656 stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
1657 }
1658
1659 /* Extended Communities attribute. */
1660 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
1661 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
1662 {
hasso4372df72004-05-20 10:20:02 +00001663 if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00001664 {
hasso4372df72004-05-20 10:20:02 +00001665 if (attr->ecommunity->size * 8 > 255)
1666 {
1667 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1668 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
1669 stream_putw (s, attr->ecommunity->size * 8);
1670 }
1671 else
1672 {
1673 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1674 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
1675 stream_putc (s, attr->ecommunity->size * 8);
1676 }
1677 stream_put (s, attr->ecommunity->val, attr->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00001678 }
1679 else
1680 {
paul5228ad22004-06-04 17:58:18 +00001681 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00001682 int tbit;
1683 int ecom_tr_size = 0;
1684 int i;
1685
1686 for (i = 0; i < attr->ecommunity->size; i++)
1687 {
1688 pnt = attr->ecommunity->val + (i * 8);
1689 tbit = *pnt;
1690
1691 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
1692 continue;
1693
1694 ecom_tr_size++;
1695 }
1696
1697 if (ecom_tr_size)
1698 {
1699 if (ecom_tr_size * 8 > 255)
1700 {
1701 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1702 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
1703 stream_putw (s, ecom_tr_size * 8);
1704 }
1705 else
1706 {
1707 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1708 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
1709 stream_putc (s, ecom_tr_size * 8);
1710 }
1711
1712 for (i = 0; i < attr->ecommunity->size; i++)
1713 {
1714 pnt = attr->ecommunity->val + (i * 8);
1715 tbit = *pnt;
1716
1717 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
1718 continue;
1719
1720 stream_put (s, pnt, 8);
1721 }
1722 }
paul718e3742002-12-13 20:15:29 +00001723 }
paul718e3742002-12-13 20:15:29 +00001724 }
1725
1726 /* Unknown transit attribute. */
1727 if (attr->transit)
1728 stream_put (s, attr->transit->val, attr->transit->length);
1729
1730 /* Return total size of attribute. */
1731 return stream_get_putp (s) - cp;
1732}
1733
1734bgp_size_t
1735bgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p,
1736 afi_t afi, safi_t safi, struct prefix_rd *prd,
paul5228ad22004-06-04 17:58:18 +00001737 char *tag)
paul718e3742002-12-13 20:15:29 +00001738{
1739 unsigned long cp;
1740 unsigned long attrlen_pnt;
1741 bgp_size_t size;
1742
1743 cp = stream_get_putp (s);
1744
1745 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1746 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
1747
1748 attrlen_pnt = stream_get_putp (s);
1749 stream_putc (s, 0); /* Length of this attribute. */
1750
1751 stream_putw (s, family2afi (p->family));
1752
1753 if (safi == SAFI_MPLS_VPN)
1754 {
1755 /* SAFI */
1756 stream_putc (s, BGP_SAFI_VPNV4);
1757
1758 /* prefix. */
1759 stream_putc (s, p->prefixlen + 88);
1760 stream_put (s, tag, 3);
1761 stream_put (s, prd->val, 8);
1762 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
1763 }
1764 else
1765 {
1766 /* SAFI */
1767 stream_putc (s, safi);
1768
1769 /* prefix */
1770 stream_put_prefix (s, p);
1771 }
1772
1773 /* Set MP attribute length. */
1774 size = stream_get_putp (s) - attrlen_pnt - 1;
1775 stream_putc_at (s, attrlen_pnt, size);
1776
1777 return stream_get_putp (s) - cp;
1778}
1779
1780/* Initialization of attribute. */
1781void
1782bgp_attr_init ()
1783{
1784 void attrhash_init ();
1785
1786 aspath_init ();
1787 attrhash_init ();
1788 community_init ();
1789 ecommunity_init ();
1790 cluster_init ();
1791 transit_init ();
1792}
1793
1794/* Make attribute packet. */
1795void
paula3845922003-10-18 01:30:50 +00001796bgp_dump_routes_attr (struct stream *s, struct attr *attr,
1797 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00001798{
1799 unsigned long cp;
1800 unsigned long len;
1801 struct aspath *aspath;
1802
1803 /* Remember current pointer. */
1804 cp = stream_get_putp (s);
1805
1806 /* Place holder of length. */
1807 stream_putw (s, 0);
1808
1809 /* Origin attribute. */
1810 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1811 stream_putc (s, BGP_ATTR_ORIGIN);
1812 stream_putc (s, 1);
1813 stream_putc (s, attr->origin);
1814
1815 aspath = attr->aspath;
1816
1817 if (aspath->length > 255)
1818 {
1819 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1820 stream_putc (s, BGP_ATTR_AS_PATH);
1821 stream_putw (s, aspath->length);
1822 }
1823 else
1824 {
1825 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1826 stream_putc (s, BGP_ATTR_AS_PATH);
1827 stream_putc (s, aspath->length);
1828 }
1829 stream_put (s, aspath->data, aspath->length);
1830
1831 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00001832 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
1833 if(prefix != NULL
1834#ifdef HAVE_IPV6
1835 && prefix->family != AF_INET6
1836#endif /* HAVE_IPV6 */
1837 )
1838 {
1839 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1840 stream_putc (s, BGP_ATTR_NEXT_HOP);
1841 stream_putc (s, 4);
1842 stream_put_ipv4 (s, attr->nexthop.s_addr);
1843 }
paul718e3742002-12-13 20:15:29 +00001844
1845 /* MED attribute. */
1846 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
1847 {
1848 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
1849 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
1850 stream_putc (s, 4);
1851 stream_putl (s, attr->med);
1852 }
1853
1854 /* Local preference. */
1855 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
1856 {
1857 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1858 stream_putc (s, BGP_ATTR_LOCAL_PREF);
1859 stream_putc (s, 4);
1860 stream_putl (s, attr->local_pref);
1861 }
1862
1863 /* Atomic aggregate. */
1864 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
1865 {
1866 stream_putc (s, BGP_ATTR_FLAG_TRANS);
1867 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
1868 stream_putc (s, 0);
1869 }
1870
1871 /* Aggregator. */
1872 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
1873 {
1874 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1875 stream_putc (s, BGP_ATTR_AGGREGATOR);
1876 stream_putc (s, 6);
1877 stream_putw (s, attr->aggregator_as);
1878 stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
1879 }
1880
1881 /* Community attribute. */
1882 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
1883 {
1884 if (attr->community->size * 4 > 255)
1885 {
1886 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
1887 stream_putc (s, BGP_ATTR_COMMUNITIES);
1888 stream_putw (s, attr->community->size * 4);
1889 }
1890 else
1891 {
1892 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
1893 stream_putc (s, BGP_ATTR_COMMUNITIES);
1894 stream_putc (s, attr->community->size * 4);
1895 }
1896 stream_put (s, attr->community->val, attr->community->size * 4);
1897 }
1898
paula3845922003-10-18 01:30:50 +00001899#ifdef HAVE_IPV6
1900 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
1901 if(prefix != NULL && prefix->family == AF_INET6 &&
1902 (attr->mp_nexthop_len == 16 || attr->mp_nexthop_len == 32) )
1903 {
1904 int sizep;
1905
1906 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
1907 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
1908 sizep = stream_get_putp (s);
1909
1910 /* MP header */
1911 stream_putc (s, 0); /* Length of this attribute. */
1912 stream_putw(s, AFI_IP6); /* AFI */
1913 stream_putc(s, SAFI_UNICAST); /* SAFI */
1914
1915 /* Next hop */
1916 stream_putc(s, attr->mp_nexthop_len);
1917 stream_put(s, &attr->mp_nexthop_global, 16);
1918 if(attr->mp_nexthop_len == 32)
1919 stream_put(s, &attr->mp_nexthop_local, 16);
1920
1921 /* SNPA */
1922 stream_putc(s, 0);
1923
1924 /* Prefix */
1925 stream_put_prefix(s, prefix);
1926
1927 /* Set MP attribute length. */
1928 stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
1929 }
1930#endif /* HAVE_IPV6 */
1931
paul718e3742002-12-13 20:15:29 +00001932 /* Return total size of attribute. */
1933 len = stream_get_putp (s) - cp - 2;
1934 stream_putw_at (s, cp, len);
1935}