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