📄 bgp_clist.c
字号:
} else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED) { if (ecommunity_regexp_match (ecom, entry->reg)) return entry->direct == COMMUNITY_PERMIT ? 1 : 0; } } return 0;}/* Perform exact matching. In case of expanded community-list, do same thing as community_list_match(). */intcommunity_list_exact_match (struct community *com, struct community_list *list){ struct community_entry *entry; for (entry = list->head; entry; entry = entry->next) { if (entry->any) return entry->direct == COMMUNITY_PERMIT ? 1 : 0; if (entry->style == COMMUNITY_LIST_STANDARD) { if (community_include (entry->u.com, COMMUNITY_INTERNET)) return entry->direct == COMMUNITY_PERMIT ? 1 : 0; if (community_cmp (com, entry->u.com)) return entry->direct == COMMUNITY_PERMIT ? 1 : 0; } else if (entry->style == COMMUNITY_LIST_EXPANDED) { if (community_regexp_match (com, entry->reg)) return entry->direct == COMMUNITY_PERMIT ? 1 : 0; } } return 0;}/* Do regular expression matching with single community val. */static intcomval_regexp_match (u_int32_t comval, regex_t *reg){ /* Maximum is "65535:65535" + '\0'. */ char c[12]; char *str; 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: snprintf (c, sizeof c, "%d:%d", (comval >> 16) & 0xFFFF, comval & 0xFFFF); str = c; break; } if (regexec (reg, str, 0, NULL, 0) == 0) return 1; return 0;}/* Delete all permitted communities in the list from com. */struct community *community_list_match_delete (struct community *com, struct community_list *clist){ int i; u_int32_t comval; struct community *merge; struct community_entry *entry; /* Empty community value check. */ if (! com) return NULL; /* Duplicate communities value. */ merge = community_dup (com); /* For each communities value, we have to check each community-list. */ for (i = 0; i < com->size; i ++) { /* Get one communities value. */ memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t)); comval = ntohl (comval); /* Loop community-list. */ for (entry = clist->head; entry; entry = entry->next) { /* Various match condition check. */ if (entry->any || (entry->style == COMMUNITY_LIST_STANDARD && entry->u.com && community_include (entry->u.com, comval)) || (entry->style == COMMUNITY_LIST_EXPANDED && entry->reg && comval_regexp_match (comval, entry->reg))) { /* If the rule is "permit", delete this community value. */ if (entry->direct == COMMUNITY_PERMIT) community_del_val (merge, com_nthval (com, i)); /* Exit community-list loop, goto next communities value. */ break; } } } return merge;}/* To avoid duplicated entry in the community-list, this function compares specified entry to existing entry. */intcommunity_list_dup_check (struct community_list *list, struct community_entry *new){ struct community_entry *entry; for (entry = list->head; entry; entry = entry->next) { if (entry->style != new->style) continue; if (entry->direct != new->direct) continue; if (entry->any != new->any) continue; if (entry->any) return 1; switch (entry->style) { case COMMUNITY_LIST_STANDARD: if (community_cmp (entry->u.com, new->u.com)) return 1; break; case EXTCOMMUNITY_LIST_STANDARD: if (ecommunity_cmp (entry->u.ecom, new->u.ecom)) return 1; break; case COMMUNITY_LIST_EXPANDED: case EXTCOMMUNITY_LIST_EXPANDED: if (strcmp (entry->config, new->config) == 0) return 1; break; default: break; } } return 0;}/* Set community-list. */intcommunity_list_set (struct community_list_handler *ch, char *name, char *str, int direct, int style){ struct community_entry *entry = NULL; struct community_list *list; struct community *com = NULL; regex_t *regex = NULL; /* Get community list. */ list = community_list_get (ch, name, COMMUNITY_LIST_MASTER); /* When community-list already has entry, new entry should have same style. If you want to have mixed style community-list, you can comment out this check. */ if (! community_list_empty_p (list)) { struct community_entry *first; first = list->head; if (style != first->style) { return (first->style == COMMUNITY_LIST_STANDARD ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); } } if (str) { if (style == COMMUNITY_LIST_STANDARD) com = community_str2com (str); else regex = bgp_regcomp (str); if (! com && ! regex) return COMMUNITY_LIST_ERR_MALFORMED_VAL; } entry = community_entry_new (); entry->direct = direct; entry->style = style; entry->any = (str ? 0 : 1); entry->u.com = com; entry->reg = regex; entry->config = (regex ? XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL); /* Do not put duplicated community entry. */ if (community_list_dup_check (list, entry)) community_entry_free (entry); else community_list_entry_add (list, entry); return 0;}/* Unset community-list. When str is NULL, delete all of community-list entry belongs to the specified name. */intcommunity_list_unset (struct community_list_handler *ch, char *name, char *str, int direct, int style){ struct community_entry *entry = NULL; struct community_list *list; struct community *com = NULL; regex_t *regex = NULL; /* Lookup community list. */ list = community_list_lookup (ch, name, COMMUNITY_LIST_MASTER); if (list == NULL) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; /* Delete all of entry belongs to this community-list. */ if (! str) { community_list_delete (list); return 0; } if (style == COMMUNITY_LIST_STANDARD) com = community_str2com (str); else regex = bgp_regcomp (str); if (! com && ! regex) return COMMUNITY_LIST_ERR_MALFORMED_VAL; if (com) entry = community_list_entry_lookup (list, com, direct); else entry = community_list_entry_lookup (list, str, direct); if (com) community_free (com); if (regex) bgp_regex_free (regex); if (! entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; community_list_entry_delete (list, entry, style); return 0;}/* Set extcommunity-list. */intextcommunity_list_set (struct community_list_handler *ch, char *name, char *str, int direct, int style){ struct community_entry *entry = NULL; struct community_list *list; struct ecommunity *ecom = NULL; regex_t *regex = NULL; entry = NULL; /* Get community list. */ list = community_list_get (ch, name, EXTCOMMUNITY_LIST_MASTER); /* When community-list already has entry, new entry should have same style. If you want to have mixed style community-list, you can comment out this check. */ if (! community_list_empty_p (list)) { struct community_entry *first; first = list->head; if (style != first->style) { return (first->style == EXTCOMMUNITY_LIST_STANDARD ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); } } if (str) { if (style == EXTCOMMUNITY_LIST_STANDARD) ecom = ecommunity_str2com (str, 0, 1); else regex = bgp_regcomp (str); if (! ecom && ! regex) return COMMUNITY_LIST_ERR_MALFORMED_VAL; } if (ecom) ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY); entry = community_entry_new (); entry->direct = direct; entry->style = style; entry->any = (str ? 0 : 1); if (ecom) entry->config = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_CONFIG); else if (regex) entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str); else entry->config = NULL; entry->u.ecom = ecom; entry->reg = regex; /* Do not put duplicated community entry. */ if (community_list_dup_check (list, entry)) community_entry_free (entry); else community_list_entry_add (list, entry); return 0;}/* Unset extcommunity-list. When str is NULL, delete all of extcommunity-list entry belongs to the specified name. */intextcommunity_list_unset (struct community_list_handler *ch, char *name, char *str, int direct, int style){ struct community_entry *entry = NULL; struct community_list *list; struct ecommunity *ecom = NULL; regex_t *regex = NULL; /* Lookup extcommunity list. */ list = community_list_lookup (ch, name, EXTCOMMUNITY_LIST_MASTER); if (list == NULL) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; /* Delete all of entry belongs to this extcommunity-list. */ if (! str) { community_list_delete (list); return 0; } if (style == EXTCOMMUNITY_LIST_STANDARD) ecom = ecommunity_str2com (str, 0, 1); else regex = bgp_regcomp (str); if (! ecom && ! regex) return COMMUNITY_LIST_ERR_MALFORMED_VAL; if (ecom) entry = community_list_entry_lookup (list, ecom, direct); else entry = community_list_entry_lookup (list, str, direct); if (ecom) ecommunity_free (ecom); if (regex) bgp_regex_free (regex); if (! entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; community_list_entry_delete (list, entry, style); return 0;}/* Initializa community-list. Return community-list handler. */struct community_list_handler *community_list_init (){ struct community_list_handler *ch; ch = XCALLOC (MTYPE_COMMUNITY_LIST_HANDLER, sizeof (struct community_list_handler)); return ch;}/* Terminate community-list. */voidcommunity_list_terminate (struct community_list_handler *ch){ struct community_list_master *cm; struct community_list *list; cm = &ch->community_list; while ((list = cm->num.head) != NULL) community_list_delete (list); while ((list = cm->str.head) != NULL) community_list_delete (list); cm = &ch->extcommunity_list; while ((list = cm->num.head) != NULL) community_list_delete (list); while ((list = cm->str.head) != NULL) community_list_delete (list); XFREE (MTYPE_COMMUNITY_LIST_HANDLER, ch);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -