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