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