File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_attr.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:37 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>