Annotation of embedaddon/quagga/bgpd/bgp_ecommunity.c, revision 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>