File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_attr.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

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