Annotation of embedaddon/quagga/bgpd/bgp_attr.c, revision 1.1.1.3

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

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