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

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

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