📄 bgp_ecommunity.c
字号:
/* BGP Extended Communities Attribute Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>This file is part of GNU Zebra.GNU Zebra is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version.GNU Zebra is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Zebra; see the file COPYING. If not, write to the FreeSoftware Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. */#include <zebra.h>#include "hash.h"#include "memory.h"#include "prefix.h"#include "command.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_ecommunity.h"/* Hash of community attribute. */struct hash *ecomhash;/* Allocate a new ecommunities. */struct ecommunity *ecommunity_new (){ return (struct ecommunity *) XCALLOC (MTYPE_ECOMMUNITY, sizeof (struct ecommunity));}/* Allocate ecommunities. */voidecommunity_free (struct ecommunity *ecom){ if (ecom->val) XFREE (MTYPE_ECOMMUNITY_VAL, ecom->val); if (ecom->str) XFREE (MTYPE_ECOMMUNITY_STR, ecom->str); XFREE (MTYPE_ECOMMUNITY, ecom);}/* Add a new Extended Communities value to Extended Communities Attribute structure. When the value is already exists in the structure, we don't add the value. Newly added value is sorted by numerical order. When the value is added to the structure return 1 else return 0. */static intecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval){ u_char *p; int ret; int c; /* When this is fist value, just add it. */ if (ecom->val == NULL) { ecom->size++; ecom->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom_length (ecom)); memcpy (ecom->val, eval->val, ECOMMUNITY_SIZE); return 1; } /* If the value already exists in the structure return 0. */ c = 0; for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) { ret = memcmp (p, eval->val, ECOMMUNITY_SIZE); if (ret == 0) return 0; if (ret > 0) break; } /* Add the value to the structure with numerical sorting. */ ecom->size++; ecom->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom->val, ecom_length (ecom)); memmove (ecom->val + (c + 1) * ECOMMUNITY_SIZE, ecom->val + c * ECOMMUNITY_SIZE, (ecom->size - 1 - c) * ECOMMUNITY_SIZE); memcpy (ecom->val + c * ECOMMUNITY_SIZE, eval->val, ECOMMUNITY_SIZE); return 1;}/* This function takes pointer to Extended Communites strucutre then create a new Extended Communities structure by uniq and sort each Exteneded Communities value. */struct ecommunity *ecommunity_uniq_sort (struct ecommunity *ecom){ int i; struct ecommunity *new; struct ecommunity_val *eval; if (! ecom) return NULL; new = ecommunity_new ();; for (i = 0; i < ecom->size; i++) { eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); ecommunity_add_val (new, eval); } return new;}/* Parse Extended Communites Attribute in BGP packet. */struct ecommunity *ecommunity_parse (char *pnt, u_short length){ struct ecommunity tmp; struct ecommunity *new; /* Length check. */ if (length % ECOMMUNITY_SIZE) return NULL; /* Prepare tmporary structure for making a new Extended Communities Attribute. */ tmp.size = length / ECOMMUNITY_SIZE; tmp.val = pnt; /* Create a new Extended Communities Attribute by uniq and sort each Extended Communities value */ new = ecommunity_uniq_sort (&tmp); return ecommunity_intern (new);}/* Duplicate the Extended Communities Attribute structure. */struct ecommunity *ecommunity_dup (struct ecommunity *ecom){ struct ecommunity *new; new = XCALLOC (MTYPE_ECOMMUNITY, sizeof (struct ecommunity)); new->size = ecom->size; if (new->size) { new->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE); memcpy (new->val, ecom->val, ecom->size * ECOMMUNITY_SIZE); } else new->val = NULL; return new;}/* Retrun string representation of communities attribute. */char *ecommunity_str (struct ecommunity *ecom){ if (! ecom->str) ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY); return ecom->str;}/* Merge two Extended Communities Attribute structure. */struct ecommunity *ecommunity_merge (struct ecommunity *ecom1, struct ecommunity *ecom2){ if (ecom1->val) ecom1->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom1->val, (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE); else ecom1->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE); memcpy (ecom1->val + (ecom1->size * ECOMMUNITY_SIZE), ecom2->val, ecom2->size * ECOMMUNITY_SIZE); ecom1->size += ecom2->size; return ecom1;}/* Intern Extended Communities Attribute. */struct ecommunity *ecommunity_intern (struct ecommunity *ecom){ struct ecommunity *find; assert (ecom->refcnt == 0); find = (struct ecommunity *) hash_get (ecomhash, ecom, hash_alloc_intern); if (find != ecom) ecommunity_free (ecom); find->refcnt++; if (! find->str) find->str = ecommunity_ecom2str (find, ECOMMUNITY_FORMAT_DISPLAY); return find;}/* Unintern Extended Communities Attribute. */voidecommunity_unintern (struct ecommunity *ecom){ struct ecommunity *ret; if (ecom->refcnt) ecom->refcnt--; /* Pull off from hash. */ if (ecom->refcnt == 0) { /* Extended community must be in the hash. */ ret = (struct ecommunity *) hash_release (ecomhash, ecom); assert (ret != NULL); ecommunity_free (ecom); }}/* Utinity function to make hash key. */unsigned intecommunity_hash_make (struct ecommunity *ecom){ int c; unsigned int key; unsigned char *pnt; key = 0; pnt = ecom->val; for (c = 0; c < ecom->size * ECOMMUNITY_SIZE; c++) key += pnt[c]; return key;}/* Compare two Extended Communities Attribute structure. */intecommunity_cmp (struct ecommunity *ecom1, struct ecommunity *ecom2){ if (ecom1->size == ecom2->size && memcmp (ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) == 0) return 1; return 0;}/* Initialize Extended Comminities related hash. */voidecommunity_init (){ ecomhash = hash_create (ecommunity_hash_make, ecommunity_cmp);}/* Extended Communities token enum. */enum ecommunity_token{ ecommunity_token_rt, ecommunity_token_soo, ecommunity_token_val, ecommunity_token_unknown};/* Get next Extended Communities token from the string. */char *ecommunity_gettoken (char *str, struct ecommunity_val *eval, enum ecommunity_token *token){ int ret; int dot = 0; int digit = 0; int separator = 0; u_int32_t val_low = 0; u_int32_t val_high = 0; char *p = str; struct in_addr ip; char ipstr[INET_ADDRSTRLEN + 1]; /* Skip white space. */ while (isspace ((int) *p)) { p++; str++; } /* Check the end of the line. */ if (*p == '\0') return NULL; /* "rt" and "soo" keyword parse. */ if (! isdigit ((int) *p)) { /* "rt" match check. */ if (tolower ((int) *p) == 'r') { p++; if (tolower ((int) *p) == 't') { p++; *token = ecommunity_token_rt; return p; } if (isspace ((int) *p) || *p == '\0') { *token = ecommunity_token_rt; return p; } goto error; } /* "soo" match check. */ else if (tolower ((int) *p) == 's') { p++; if (tolower ((int) *p) == 'o') { p++; if (tolower ((int) *p) == 'o') { p++; *token = ecommunity_token_soo; return p; } if (isspace ((int) *p) || *p == '\0') { *token = ecommunity_token_soo; return p; } goto error; } if (isspace ((int) *p) || *p == '\0') { *token = ecommunity_token_soo; return p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -