Annotation of embedaddon/quagga/bgpd/bgp_ecommunity.c, revision 1.1.1.1

1.1       misho       1: /* BGP Extended Communities Attribute
                      2:    Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
                      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 "hash.h"
                     24: #include "memory.h"
                     25: #include "prefix.h"
                     26: #include "command.h"
                     27: 
                     28: #include "bgpd/bgpd.h"
                     29: #include "bgpd/bgp_ecommunity.h"
                     30: #include "bgpd/bgp_aspath.h"
                     31: 
                     32: /* Hash of community attribute. */
                     33: static struct hash *ecomhash;
                     34: 
                     35: /* Allocate a new ecommunities.  */
                     36: static struct ecommunity *
                     37: ecommunity_new (void)
                     38: {
                     39:   return (struct ecommunity *) XCALLOC (MTYPE_ECOMMUNITY,
                     40:                                        sizeof (struct ecommunity));
                     41: }
                     42: 
                     43: /* Allocate ecommunities.  */
                     44: void
                     45: ecommunity_free (struct ecommunity **ecom)
                     46: {
                     47:   if ((*ecom)->val)
                     48:     XFREE (MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
                     49:   if ((*ecom)->str)
                     50:     XFREE (MTYPE_ECOMMUNITY_STR, (*ecom)->str);
                     51:   XFREE (MTYPE_ECOMMUNITY, *ecom);
                     52:   ecom = NULL;
                     53: }
                     54: 
                     55: /* Add a new Extended Communities value to Extended Communities
                     56:    Attribute structure.  When the value is already exists in the
                     57:    structure, we don't add the value.  Newly added value is sorted by
                     58:    numerical order.  When the value is added to the structure return 1
                     59:    else return 0.  */
                     60: static int
                     61: ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval)
                     62: {
                     63:   u_int8_t *p;
                     64:   int ret;
                     65:   int c;
                     66: 
                     67:   /* When this is fist value, just add it.  */
                     68:   if (ecom->val == NULL)
                     69:     {
                     70:       ecom->size++;
                     71:       ecom->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom_length (ecom));
                     72:       memcpy (ecom->val, eval->val, ECOMMUNITY_SIZE);
                     73:       return 1;
                     74:     }
                     75: 
                     76:   /* If the value already exists in the structure return 0.  */
                     77:   c = 0;
                     78:   for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++)
                     79:     {
                     80:       ret = memcmp (p, eval->val, ECOMMUNITY_SIZE);
                     81:       if (ret == 0)
                     82:         return 0;
                     83:       if (ret > 0)
                     84:         break;
                     85:     }
                     86: 
                     87:   /* Add the value to the structure with numerical sorting.  */
                     88:   ecom->size++;
                     89:   ecom->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom->val, ecom_length (ecom));
                     90: 
                     91:   memmove (ecom->val + (c + 1) * ECOMMUNITY_SIZE,
                     92:           ecom->val + c * ECOMMUNITY_SIZE,
                     93:           (ecom->size - 1 - c) * ECOMMUNITY_SIZE);
                     94:   memcpy (ecom->val + c * ECOMMUNITY_SIZE, eval->val, ECOMMUNITY_SIZE);
                     95: 
                     96:   return 1;
                     97: }
                     98: 
                     99: /* This function takes pointer to Extended Communites strucutre then
                    100:    create a new Extended Communities structure by uniq and sort each
                    101:    Extended Communities value.  */
                    102: static struct ecommunity *
                    103: ecommunity_uniq_sort (struct ecommunity *ecom)
                    104: {
                    105:   int i;
                    106:   struct ecommunity *new;
                    107:   struct ecommunity_val *eval;
                    108:   
                    109:   if (! ecom)
                    110:     return NULL;
                    111:   
                    112:   new = ecommunity_new ();
                    113:   
                    114:   for (i = 0; i < ecom->size; i++)
                    115:     {
                    116:       eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE));
                    117:       ecommunity_add_val (new, eval);
                    118:     }
                    119:   return new;
                    120: }
                    121: 
                    122: /* Parse Extended Communites Attribute in BGP packet.  */
                    123: struct ecommunity *
                    124: ecommunity_parse (u_int8_t *pnt, u_short length)
                    125: {
                    126:   struct ecommunity tmp;
                    127:   struct ecommunity *new;
                    128: 
                    129:   /* Length check.  */
                    130:   if (length % ECOMMUNITY_SIZE)
                    131:     return NULL;
                    132: 
                    133:   /* Prepare tmporary structure for making a new Extended Communities
                    134:      Attribute.  */
                    135:   tmp.size = length / ECOMMUNITY_SIZE;
                    136:   tmp.val = pnt;
                    137: 
                    138:   /* Create a new Extended Communities Attribute by uniq and sort each
                    139:      Extended Communities value  */
                    140:   new = ecommunity_uniq_sort (&tmp);
                    141: 
                    142:   return ecommunity_intern (new);
                    143: }
                    144: 
                    145: /* Duplicate the Extended Communities Attribute structure.  */
                    146: struct ecommunity *
                    147: ecommunity_dup (struct ecommunity *ecom)
                    148: {
                    149:   struct ecommunity *new;
                    150: 
                    151:   new = XCALLOC (MTYPE_ECOMMUNITY, sizeof (struct ecommunity));
                    152:   new->size = ecom->size;
                    153:   if (new->size)
                    154:     {
                    155:       new->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE);
                    156:       memcpy (new->val, ecom->val, ecom->size * ECOMMUNITY_SIZE);
                    157:     }
                    158:   else
                    159:     new->val = NULL;
                    160:   return new;
                    161: }
                    162: 
                    163: /* Retrun string representation of communities attribute. */
                    164: char *
                    165: ecommunity_str (struct ecommunity *ecom)
                    166: {
                    167:   if (! ecom->str)
                    168:     ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY);
                    169:   return ecom->str;
                    170: }
                    171: 
                    172: /* Merge two Extended Communities Attribute structure.  */
                    173: struct ecommunity *
                    174: ecommunity_merge (struct ecommunity *ecom1, struct ecommunity *ecom2)
                    175: {
                    176:   if (ecom1->val)
                    177:     ecom1->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom1->val, 
                    178:                           (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE);
                    179:   else
                    180:     ecom1->val = XMALLOC (MTYPE_ECOMMUNITY_VAL,
                    181:                          (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE);
                    182: 
                    183:   memcpy (ecom1->val + (ecom1->size * ECOMMUNITY_SIZE),
                    184:          ecom2->val, ecom2->size * ECOMMUNITY_SIZE);
                    185:   ecom1->size += ecom2->size;
                    186: 
                    187:   return ecom1;
                    188: }
                    189: 
                    190: /* Intern Extended Communities Attribute.  */
                    191: struct ecommunity *
                    192: ecommunity_intern (struct ecommunity *ecom)
                    193: {
                    194:   struct ecommunity *find;
                    195: 
                    196:   assert (ecom->refcnt == 0);
                    197: 
                    198:   find = (struct ecommunity *) hash_get (ecomhash, ecom, hash_alloc_intern);
                    199: 
                    200:   if (find != ecom)
                    201:     ecommunity_free (&ecom);
                    202: 
                    203:   find->refcnt++;
                    204: 
                    205:   if (! find->str)
                    206:     find->str = ecommunity_ecom2str (find, ECOMMUNITY_FORMAT_DISPLAY);
                    207: 
                    208:   return find;
                    209: }
                    210: 
                    211: /* Unintern Extended Communities Attribute.  */
                    212: void
                    213: ecommunity_unintern (struct ecommunity **ecom)
                    214: {
                    215:   struct ecommunity *ret;
                    216: 
                    217:   if ((*ecom)->refcnt)
                    218:     (*ecom)->refcnt--;
                    219:     
                    220:   /* Pull off from hash.  */
                    221:   if ((*ecom)->refcnt == 0)
                    222:     {
                    223:       /* Extended community must be in the hash.  */
                    224:       ret = (struct ecommunity *) hash_release (ecomhash, *ecom);
                    225:       assert (ret != NULL);
                    226: 
                    227:       ecommunity_free (ecom);
                    228:     }
                    229: }
                    230: 
                    231: /* Utinity function to make hash key.  */
                    232: unsigned int
                    233: ecommunity_hash_make (void *arg)
                    234: {
                    235:   const struct ecommunity *ecom = arg;
                    236:   int c;
                    237:   unsigned int key;
                    238:   u_int8_t *pnt;
                    239: 
                    240:   key = 0;
                    241:   pnt = ecom->val;
                    242:   
                    243:   for (c = 0; c < ecom->size * ECOMMUNITY_SIZE; c++)
                    244:     key += pnt[c];
                    245: 
                    246:   return key;
                    247: }
                    248: 
                    249: /* Compare two Extended Communities Attribute structure.  */
                    250: int
                    251: ecommunity_cmp (const void *arg1, const void *arg2)
                    252: {
                    253:   const struct ecommunity *ecom1 = arg1;
                    254:   const struct ecommunity *ecom2 = arg2;
                    255:   
                    256:   return (ecom1->size == ecom2->size
                    257:          && memcmp (ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) == 0);
                    258: }
                    259: 
                    260: /* Initialize Extended Comminities related hash. */
                    261: void
                    262: ecommunity_init (void)
                    263: {
                    264:   ecomhash = hash_create (ecommunity_hash_make, ecommunity_cmp);
                    265: }
                    266: 
                    267: void
                    268: ecommunity_finish (void)
                    269: {
                    270:   hash_free (ecomhash);
                    271:   ecomhash = NULL;
                    272: }
                    273: 
                    274: /* Extended Communities token enum. */
                    275: enum ecommunity_token
                    276: {
                    277:   ecommunity_token_rt,
                    278:   ecommunity_token_soo,
                    279:   ecommunity_token_val,
                    280:   ecommunity_token_unknown
                    281: };
                    282: 
                    283: /* Get next Extended Communities token from the string. */
                    284: static const char *
                    285: ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
                    286:                     enum ecommunity_token *token)
                    287: {
                    288:   int ret;
                    289:   int dot = 0;
                    290:   int digit = 0;
                    291:   int separator = 0;
                    292:   const char *p = str;
                    293:   char *endptr;
                    294:   struct in_addr ip;
                    295:   as_t as = 0;
                    296:   u_int32_t val = 0;
                    297:   char buf[INET_ADDRSTRLEN + 1];
                    298: 
                    299:   /* Skip white space. */
                    300:   while (isspace ((int) *p))
                    301:     {
                    302:       p++;
                    303:       str++;
                    304:     }
                    305: 
                    306:   /* Check the end of the line. */
                    307:   if (*p == '\0')
                    308:     return NULL;
                    309: 
                    310:   /* "rt" and "soo" keyword parse. */
                    311:   if (! isdigit ((int) *p)) 
                    312:     {
                    313:       /* "rt" match check.  */
                    314:       if (tolower ((int) *p) == 'r')
                    315:        {
                    316:          p++;
                    317:          if (tolower ((int) *p) == 't')
                    318:            {
                    319:              p++;
                    320:              *token = ecommunity_token_rt;
                    321:              return p;
                    322:            }
                    323:          if (isspace ((int) *p) || *p == '\0')
                    324:            {
                    325:              *token = ecommunity_token_rt;
                    326:              return p;
                    327:            }
                    328:          goto error;
                    329:        }
                    330:       /* "soo" match check.  */
                    331:       else if (tolower ((int) *p) == 's')
                    332:        {
                    333:          p++;
                    334:          if (tolower ((int) *p) == 'o')
                    335:            {
                    336:              p++;
                    337:              if (tolower ((int) *p) == 'o')
                    338:                {
                    339:                  p++;
                    340:                  *token = ecommunity_token_soo;
                    341:                  return p;
                    342:                }
                    343:              if (isspace ((int) *p) || *p == '\0')
                    344:                {
                    345:                  *token = ecommunity_token_soo;
                    346:                  return p;
                    347:                }
                    348:              goto error;
                    349:            }
                    350:          if (isspace ((int) *p) || *p == '\0')
                    351:            {
                    352:              *token = ecommunity_token_soo;
                    353:              return p;
                    354:            }
                    355:          goto error;
                    356:        }
                    357:       goto error;
                    358:     }
                    359:   
                    360:   /* What a mess, there are several possibilities:
                    361:    *
                    362:    * a) A.B.C.D:MN
                    363:    * b) EF:OPQR
                    364:    * c) GHJK:MN
                    365:    *
                    366:    * A.B.C.D: Four Byte IP
                    367:    * EF:      Two byte ASN
                    368:    * GHJK:    Four-byte ASN
                    369:    * MN:      Two byte value
                    370:    * OPQR:    Four byte value
                    371:    *
                    372:    */
                    373:   while (isdigit ((int) *p) || *p == ':' || *p == '.') 
                    374:     {
                    375:       if (*p == ':')
                    376:        {
                    377:          if (separator)
                    378:            goto error;
                    379: 
                    380:          separator = 1;
                    381:          digit = 0;
                    382:          
                    383:          if ((p - str) > INET_ADDRSTRLEN)
                    384:            goto error;
                    385:           memset (buf, 0, INET_ADDRSTRLEN + 1);
                    386:           memcpy (buf, str, p - str);
                    387:           
                    388:          if (dot)
                    389:            {
                    390:              /* Parsing A.B.C.D in:
                    391:                * A.B.C.D:MN
                    392:                */
                    393:              ret = inet_aton (buf, &ip);
                    394:              if (ret == 0)
                    395:                goto error;
                    396:            }
                    397:           else
                    398:             {
                    399:               /* ASN */
                    400:               as = strtoul (buf, &endptr, 10);
                    401:               if (*endptr != '\0' || as == BGP_AS4_MAX)
                    402:                 goto error;
                    403:             }
                    404:        }
                    405:       else if (*p == '.')
                    406:        {
                    407:          if (separator)
                    408:            goto error;
                    409:          dot++;
                    410:          if (dot > 4)
                    411:            goto error;
                    412:        }
                    413:       else
                    414:        {
                    415:          digit = 1;
                    416:          
                    417:          /* We're past the IP/ASN part */
                    418:          if (separator)
                    419:            {
                    420:              val *= 10;
                    421:              val += (*p - '0');
                    422:             }
                    423:        }
                    424:       p++;
                    425:     }
                    426: 
                    427:   /* Low digit part must be there. */
                    428:   if (!digit || !separator)
                    429:     goto error;
                    430: 
                    431:   /* Encode result into routing distinguisher.  */
                    432:   if (dot)
                    433:     {
                    434:       if (val > UINT16_MAX)
                    435:         goto error;
                    436:       
                    437:       eval->val[0] = ECOMMUNITY_ENCODE_IP;
                    438:       eval->val[1] = 0;
                    439:       memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
                    440:       eval->val[6] = (val >> 8) & 0xff;
                    441:       eval->val[7] = val & 0xff;
                    442:     }
                    443:   else if (as > BGP_AS_MAX)
                    444:     {
                    445:       if (val > UINT16_MAX)
                    446:         goto error;
                    447:       
                    448:       eval->val[0] = ECOMMUNITY_ENCODE_AS4;
                    449:       eval->val[1] = 0;
                    450:       eval->val[2] = (as >>24) & 0xff;
                    451:       eval->val[3] = (as >>16) & 0xff;
                    452:       eval->val[4] = (as >>8) & 0xff;
                    453:       eval->val[5] =  as & 0xff;
                    454:       eval->val[6] = (val >> 8) & 0xff;
                    455:       eval->val[7] = val & 0xff;
                    456:     }
                    457:   else
                    458:     {
                    459:       eval->val[0] = ECOMMUNITY_ENCODE_AS;
                    460:       eval->val[1] = 0;
                    461:       
                    462:       eval->val[2] = (as >>8) & 0xff;
                    463:       eval->val[3] = as & 0xff;
                    464:       eval->val[4] = (val >>24) & 0xff;
                    465:       eval->val[5] = (val >>16) & 0xff;
                    466:       eval->val[6] = (val >>8) & 0xff;
                    467:       eval->val[7] = val & 0xff;
                    468:     }
                    469:   *token = ecommunity_token_val;
                    470:   return p;
                    471: 
                    472:  error:
                    473:   *token = ecommunity_token_unknown;
                    474:   return p;
                    475: }
                    476: 
                    477: /* Convert string to extended community attribute. 
                    478: 
                    479:    When type is already known, please specify both str and type.  str
                    480:    should not include keyword such as "rt" and "soo".  Type is
                    481:    ECOMMUNITY_ROUTE_TARGET or ECOMMUNITY_SITE_ORIGIN.
                    482:    keyword_included should be zero.
                    483: 
                    484:    For example route-map's "set extcommunity" command case:
                    485: 
                    486:    "rt 100:1 100:2 100:3"        -> str = "100:1 100:2 100:3"
                    487:                                     type = ECOMMUNITY_ROUTE_TARGET
                    488:                                     keyword_included = 0
                    489: 
                    490:    "soo 100:1"                   -> str = "100:1"
                    491:                                     type = ECOMMUNITY_SITE_ORIGIN
                    492:                                     keyword_included = 0
                    493: 
                    494:    When string includes keyword for each extended community value.
                    495:    Please specify keyword_included as non-zero value.
                    496: 
                    497:    For example standard extcommunity-list case:
                    498: 
                    499:    "rt 100:1 rt 100:2 soo 100:1" -> str = "rt 100:1 rt 100:2 soo 100:1"
                    500:                                     type = 0
                    501:                                     keyword_include = 1
                    502: */
                    503: struct ecommunity *
                    504: ecommunity_str2com (const char *str, int type, int keyword_included)
                    505: {
                    506:   struct ecommunity *ecom = NULL;
                    507:   enum ecommunity_token token;
                    508:   struct ecommunity_val eval;
                    509:   int keyword = 0;
                    510: 
                    511:   while ((str = ecommunity_gettoken (str, &eval, &token)))
                    512:     {
                    513:       switch (token)
                    514:        {
                    515:        case ecommunity_token_rt:
                    516:        case ecommunity_token_soo:
                    517:          if (! keyword_included || keyword)
                    518:            {
                    519:              if (ecom)
                    520:                ecommunity_free (&ecom);
                    521:              return NULL;
                    522:            }
                    523:          keyword = 1;
                    524: 
                    525:          if (token == ecommunity_token_rt)
                    526:            {
                    527:              type = ECOMMUNITY_ROUTE_TARGET;
                    528:            }
                    529:          if (token == ecommunity_token_soo)
                    530:            {
                    531:              type = ECOMMUNITY_SITE_ORIGIN;
                    532:            }
                    533:          break;
                    534:        case ecommunity_token_val:
                    535:          if (keyword_included)
                    536:            {
                    537:              if (! keyword)
                    538:                {
                    539:                  if (ecom)
                    540:                    ecommunity_free (&ecom);
                    541:                  return NULL;
                    542:                }
                    543:              keyword = 0;
                    544:            }
                    545:          if (ecom == NULL)
                    546:            ecom = ecommunity_new ();
                    547:          eval.val[1] = type;
                    548:          ecommunity_add_val (ecom, &eval);
                    549:          break;
                    550:        case ecommunity_token_unknown:
                    551:        default:
                    552:          if (ecom)
                    553:            ecommunity_free (&ecom);
                    554:          return NULL;
                    555:        }
                    556:     }
                    557:   return ecom;
                    558: }
                    559: 
                    560: /* Convert extended community attribute to string.  
                    561: 
                    562:    Due to historical reason of industry standard implementation, there
                    563:    are three types of format.
                    564: 
                    565:    route-map set extcommunity format
                    566:         "rt 100:1 100:2"
                    567:         "soo 100:3"
                    568: 
                    569:    extcommunity-list
                    570:         "rt 100:1 rt 100:2 soo 100:3"
                    571: 
                    572:    "show ip bgp" and extcommunity-list regular expression matching
                    573:         "RT:100:1 RT:100:2 SoO:100:3"
                    574: 
                    575:    For each formath please use below definition for format:
                    576: 
                    577:    ECOMMUNITY_FORMAT_ROUTE_MAP
                    578:    ECOMMUNITY_FORMAT_COMMUNITY_LIST
                    579:    ECOMMUNITY_FORMAT_DISPLAY
                    580: */
                    581: char *
                    582: ecommunity_ecom2str (struct ecommunity *ecom, int format)
                    583: {
                    584:   int i;
                    585:   u_int8_t *pnt;
                    586:   int encode = 0;
                    587:   int type = 0;
                    588: #define ECOMMUNITY_STR_DEFAULT_LEN  27
                    589:   int str_size;
                    590:   int str_pnt;
                    591:   char *str_buf;
                    592:   const char *prefix;
                    593:   int len = 0;
                    594:   int first = 1;
                    595: 
                    596:   /* For parse Extended Community attribute tupple. */
                    597:   struct ecommunity_as
                    598:   {
                    599:     as_t as;
                    600:     u_int32_t val;
                    601:   } eas;
                    602: 
                    603:   struct ecommunity_ip
                    604:   {
                    605:     struct in_addr ip;
                    606:     u_int16_t val;
                    607:   } eip;
                    608: 
                    609:   if (ecom->size == 0)
                    610:     {
                    611:       str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, 1);
                    612:       str_buf[0] = '\0';
                    613:       return str_buf;
                    614:     }
                    615: 
                    616:   /* Prepare buffer.  */
                    617:   str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, ECOMMUNITY_STR_DEFAULT_LEN + 1);
                    618:   str_size = ECOMMUNITY_STR_DEFAULT_LEN + 1;
                    619:   str_pnt = 0;
                    620: 
                    621:   for (i = 0; i < ecom->size; i++)
                    622:     {
                    623:       /* Make it sure size is enough.  */
                    624:       while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size)
                    625:        {
                    626:          str_size *= 2;
                    627:          str_buf = XREALLOC (MTYPE_ECOMMUNITY_STR, str_buf, str_size);
                    628:        }
                    629: 
                    630:       /* Space between each value.  */
                    631:       if (! first)
                    632:        str_buf[str_pnt++] = ' ';
                    633: 
                    634:       pnt = ecom->val + (i * 8);
                    635: 
                    636:       /* High-order octet of type. */
                    637:       encode = *pnt++;
                    638:       if (encode != ECOMMUNITY_ENCODE_AS && encode != ECOMMUNITY_ENCODE_IP
                    639:                      && encode != ECOMMUNITY_ENCODE_AS4)
                    640:        {
                    641:          len = sprintf (str_buf + str_pnt, "?");
                    642:          str_pnt += len;
                    643:          first = 0;
                    644:          continue;
                    645:        }
                    646:       
                    647:       /* Low-order octet of type. */
                    648:       type = *pnt++;
                    649:       if (type !=  ECOMMUNITY_ROUTE_TARGET && type != ECOMMUNITY_SITE_ORIGIN)
                    650:        {
                    651:          len = sprintf (str_buf + str_pnt, "?");
                    652:          str_pnt += len;
                    653:          first = 0;
                    654:          continue;
                    655:        }
                    656: 
                    657:       switch (format)
                    658:        {
                    659:        case ECOMMUNITY_FORMAT_COMMUNITY_LIST:
                    660:          prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo ");
                    661:          break;
                    662:        case ECOMMUNITY_FORMAT_DISPLAY:
                    663:          prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:");
                    664:          break;
                    665:        case ECOMMUNITY_FORMAT_ROUTE_MAP:
                    666:          prefix = "";
                    667:          break;
                    668:        default:
                    669:          prefix = "";
                    670:          break;
                    671:        }
                    672: 
                    673:       /* Put string into buffer.  */
                    674:       if (encode == ECOMMUNITY_ENCODE_AS4)
                    675:        {
                    676:          eas.as = (*pnt++ << 24);
                    677:          eas.as |= (*pnt++ << 16);
                    678:          eas.as |= (*pnt++ << 8);
                    679:          eas.as |= (*pnt++);
                    680: 
                    681:          eas.val = (*pnt++ << 8);
                    682:          eas.val |= (*pnt++);
                    683: 
                    684:          len = sprintf( str_buf + str_pnt, "%s%u:%d", prefix,
                    685:                         eas.as, eas.val );
                    686:          str_pnt += len;
                    687:          first = 0;
                    688:        }
                    689:       if (encode == ECOMMUNITY_ENCODE_AS)
                    690:        {
                    691:          eas.as = (*pnt++ << 8);
                    692:          eas.as |= (*pnt++);
                    693: 
                    694:          eas.val = (*pnt++ << 24);
                    695:          eas.val |= (*pnt++ << 16);
                    696:          eas.val |= (*pnt++ << 8);
                    697:          eas.val |= (*pnt++);
                    698: 
                    699:          len = sprintf (str_buf + str_pnt, "%s%u:%d", prefix,
                    700:                         eas.as, eas.val);
                    701:          str_pnt += len;
                    702:          first = 0;
                    703:        }
                    704:       else if (encode == ECOMMUNITY_ENCODE_IP)
                    705:        {
                    706:          memcpy (&eip.ip, pnt, 4);
                    707:          pnt += 4;
                    708:          eip.val = (*pnt++ << 8);
                    709:          eip.val |= (*pnt++);
                    710: 
                    711:          len = sprintf (str_buf + str_pnt, "%s%s:%d", prefix,
                    712:                         inet_ntoa (eip.ip), eip.val);
                    713:          str_pnt += len;
                    714:          first = 0;
                    715:        }
                    716:     }
                    717:   return str_buf;
                    718: }
                    719: 
                    720: int
                    721: ecommunity_match (const struct ecommunity *ecom1, 
                    722:                   const struct ecommunity *ecom2)
                    723: {
                    724:   int i = 0;
                    725:   int j = 0;
                    726: 
                    727:   if (ecom1 == NULL && ecom2 == NULL)
                    728:     return 1;
                    729: 
                    730:   if (ecom1 == NULL || ecom2 == NULL)
                    731:     return 0;
                    732: 
                    733:   if (ecom1->size < ecom2->size)
                    734:     return 0;
                    735: 
                    736:   /* Every community on com2 needs to be on com1 for this to match */
                    737:   while (i < ecom1->size && j < ecom2->size)
                    738:     {
                    739:       if (memcmp (ecom1->val + i, ecom2->val + j, ECOMMUNITY_SIZE) == 0)
                    740:         j++;
                    741:       i++;
                    742:     }
                    743: 
                    744:   if (j == ecom2->size)
                    745:     return 1;
                    746:   else
                    747:     return 0;
                    748: }
                    749: 

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