version 1.1, 2012/02/21 17:26:12
|
version 1.1.1.2, 2016/11/02 10:09:10
|
Line 23 Software Foundation, Inc., 59 Temple Place - Suite 330
|
Line 23 Software Foundation, Inc., 59 Temple Place - Suite 330
|
#include "command.h" |
#include "command.h" |
#include "prefix.h" |
#include "prefix.h" |
#include "memory.h" |
#include "memory.h" |
|
#include "filter.h" |
|
|
#include "bgpd/bgpd.h" |
#include "bgpd/bgpd.h" |
#include "bgpd/bgp_community.h" |
#include "bgpd/bgp_community.h" |
Line 30 Software Foundation, Inc., 59 Temple Place - Suite 330
|
Line 31 Software Foundation, Inc., 59 Temple Place - Suite 330
|
#include "bgpd/bgp_aspath.h" |
#include "bgpd/bgp_aspath.h" |
#include "bgpd/bgp_regex.h" |
#include "bgpd/bgp_regex.h" |
#include "bgpd/bgp_clist.h" |
#include "bgpd/bgp_clist.h" |
| |
/* Lookup master structure for community-list or |
/* Lookup master structure for community-list or |
extcommunity-list. */ |
extcommunity-list. */ |
struct community_list_master * |
struct community_list_master * |
Line 262 community_list_empty_p (struct community_list *list)
|
Line 263 community_list_empty_p (struct community_list *list)
|
{ |
{ |
return (list->head == NULL && list->tail == NULL) ? 1 : 0; |
return (list->head == NULL && list->tail == NULL) ? 1 : 0; |
} |
} |
| |
/* Add community-list entry to the list. */ |
/* Add community-list entry to the list. */ |
static void |
static void |
community_list_entry_add (struct community_list *list, |
community_list_entry_add (struct community_list *list, |
Line 329 community_list_entry_lookup (struct community_list *li
|
Line 330 community_list_entry_lookup (struct community_list *li
|
} |
} |
return NULL; |
return NULL; |
} |
} |
| |
| static char * |
| community_str_get (struct community *com, int i) |
| { |
| int len; |
| u_int32_t comval; |
| u_int16_t as; |
| u_int16_t val; |
| char *str; |
| char *pnt; |
| |
| memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t)); |
| comval = ntohl (comval); |
| |
| switch (comval) |
| { |
| case COMMUNITY_INTERNET: |
| len = strlen (" internet"); |
| break; |
| case COMMUNITY_NO_EXPORT: |
| len = strlen (" no-export"); |
| break; |
| case COMMUNITY_NO_ADVERTISE: |
| len = strlen (" no-advertise"); |
| break; |
| case COMMUNITY_LOCAL_AS: |
| len = strlen (" local-AS"); |
| break; |
| default: |
| len = strlen (" 65536:65535"); |
| break; |
| } |
| |
| /* Allocate memory. */ |
| str = pnt = XMALLOC (MTYPE_COMMUNITY_STR, len); |
| |
| switch (comval) |
| { |
| case COMMUNITY_INTERNET: |
| strcpy (pnt, "internet"); |
| pnt += strlen ("internet"); |
| break; |
| case COMMUNITY_NO_EXPORT: |
| strcpy (pnt, "no-export"); |
| pnt += strlen ("no-export"); |
| break; |
| case COMMUNITY_NO_ADVERTISE: |
| strcpy (pnt, "no-advertise"); |
| pnt += strlen ("no-advertise"); |
| break; |
| case COMMUNITY_LOCAL_AS: |
| strcpy (pnt, "local-AS"); |
| pnt += strlen ("local-AS"); |
| break; |
| default: |
| as = (comval >> 16) & 0xFFFF; |
| val = comval & 0xFFFF; |
| sprintf (pnt, "%u:%d", as, val); |
| pnt += strlen (pnt); |
| break; |
| } |
| |
| *pnt = '\0'; |
| |
| return str; |
| } |
| |
| /* Internal function to perform regular expression match for |
| * * a single community. */ |
| static int |
| community_regexp_include (regex_t * reg, struct community *com, int i) |
| { |
| const char *str; |
| |
| /* When there is no communities attribute it is treated as empty |
| * string. */ |
| if (com == NULL || com->size == 0) |
| str = ""; |
| else |
| str = community_str_get (com, i); |
| |
| /* Regular expression match. */ |
| if (regexec (reg, str, 0, NULL, 0) == 0) |
| return 1; |
| |
| /* No match. */ |
| return 0; |
| } |
| |
/* Internal function to perform regular expression match for community |
/* Internal function to perform regular expression match for community |
attribute. */ |
attribute. */ |
static int |
static int |
Line 372 ecommunity_regexp_match (struct ecommunity *ecom, rege
|
Line 461 ecommunity_regexp_match (struct ecommunity *ecom, rege
|
return 0; |
return 0; |
} |
} |
|
|
/* Delete community attribute using regular expression match. Return |
|
modified communites attribute. */ |
|
static struct community * |
|
community_regexp_delete (struct community *com, regex_t * reg) |
|
{ |
|
int i; |
|
u_int32_t comval; |
|
/* Maximum is "65535:65535" + '\0'. */ |
|
char c[12]; |
|
const char *str; |
|
|
|
if (!com) |
|
return NULL; |
|
|
|
i = 0; |
|
while (i < com->size) |
|
{ |
|
memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t)); |
|
comval = ntohl (comval); |
|
|
|
switch (comval) |
|
{ |
|
case COMMUNITY_INTERNET: |
|
str = "internet"; |
|
break; |
|
case COMMUNITY_NO_EXPORT: |
|
str = "no-export"; |
|
break; |
|
case COMMUNITY_NO_ADVERTISE: |
|
str = "no-advertise"; |
|
break; |
|
case COMMUNITY_LOCAL_AS: |
|
str = "local-AS"; |
|
break; |
|
default: |
|
sprintf (c, "%d:%d", (comval >> 16) & 0xFFFF, comval & 0xFFFF); |
|
str = c; |
|
break; |
|
} |
|
|
|
if (regexec (reg, str, 0, NULL, 0) == 0) |
|
community_del_val (com, com_nthval (com, i)); |
|
else |
|
i++; |
|
} |
|
return com; |
|
} |
|
|
|
/* When given community attribute matches to the community-list return |
/* When given community attribute matches to the community-list return |
1 else return 0. */ |
1 else return 0. */ |
int |
int |
Line 509 community_list_match_delete (struct community *com,
|
Line 550 community_list_match_delete (struct community *com,
|
struct community_list *list) |
struct community_list *list) |
{ |
{ |
struct community_entry *entry; |
struct community_entry *entry; |
|
u_int32_t val; |
|
u_int32_t com_index_to_delete[com->size]; |
|
int delete_index = 0; |
|
int i; |
|
|
for (entry = list->head; entry; entry = entry->next) | /* Loop over each community value and evaluate each against the |
| * community-list. If we need to delete a community value add its index to |
| * com_index_to_delete. |
| */ |
| for (i = 0; i < com->size; i++) |
{ |
{ |
if (entry->any) | val = community_val_get (com, i); |
| |
| for (entry = list->head; entry; entry = entry->next) |
{ |
{ |
if (entry->direct == COMMUNITY_PERMIT) | if (entry->any) |
{ |
{ |
/* This is a tricky part. Currently only | if (entry->direct == COMMUNITY_PERMIT) |
* route_set_community_delete() uses this function. In the | { |
* function com->size is zero, it free the community | com_index_to_delete[delete_index] = i; |
* structure. | delete_index++; |
*/ | } |
com->size = 0; | break; |
} |
} |
return com; |
|
} |
|
|
|
if ((entry->style == COMMUNITY_LIST_STANDARD) | else if ((entry->style == COMMUNITY_LIST_STANDARD) |
&& (community_include (entry->u.com, COMMUNITY_INTERNET) | && (community_include (entry->u.com, COMMUNITY_INTERNET) |
|| community_match (com, entry->u.com) )) | || community_include (entry->u.com, val) )) |
{ | { |
if (entry->direct == COMMUNITY_PERMIT) |
if (entry->direct == COMMUNITY_PERMIT) |
community_delete (com, entry->u.com); | { |
else | com_index_to_delete[delete_index] = i; |
break; | delete_index++; |
} | } |
else if ((entry->style == COMMUNITY_LIST_EXPANDED) | break; |
&& community_regexp_match (com, entry->reg)) | } |
{ | |
if (entry->direct == COMMUNITY_PERMIT) | else if ((entry->style == COMMUNITY_LIST_EXPANDED) |
community_regexp_delete (com, entry->reg); | && community_regexp_include (entry->reg, com, i)) |
else | { |
break; | if (entry->direct == COMMUNITY_PERMIT) |
} | { |
| com_index_to_delete[delete_index] = i; |
| delete_index++; |
| } |
| break; |
| } |
| } |
| } |
| |
| /* Delete all of the communities we flagged for deletion */ |
| for (i = delete_index-1; i >= 0; i--) |
| { |
| val = community_val_get (com, com_index_to_delete[i]); |
| community_del_val (com, &val); |
} |
} |
|
|
return com; |
return com; |
} |
} |
|
|
Line 590 community_list_dup_check (struct community_list *list,
|
Line 653 community_list_dup_check (struct community_list *list,
|
} |
} |
return 0; |
return 0; |
} |
} |
| |
/* Set community-list. */ |
/* Set community-list. */ |
int |
int |
community_list_set (struct community_list_handler *ch, |
community_list_set (struct community_list_handler *ch, |