📄 routemap.c
字号:
/* Route map function. Copyright (C) 1998, 1999 Kunihiro IshiguroThis 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 "linklist.h"#include "memory.h"#include "vector.h"#include "prefix.h"#include "routemap.h"#include "command.h"/* Vector for route match rules. */static vector route_match_vec;/* Vector for route set rules. */static vector route_set_vec;/* Route map rule. This rule has both `match' rule and `set' rule. */struct route_map_rule{ /* Rule type. */ struct route_map_rule_cmd *cmd; /* For pretty printing. */ char *rule_str; /* Pre-compiled match rule. */ void *value; /* Linked list. */ struct route_map_rule *next; struct route_map_rule *prev;};/* Making route map list. */struct route_map_list{ struct route_map *head; struct route_map *tail; void (*add_hook) (char *); void (*delete_hook) (char *); void (*event_hook) (route_map_event_t, char *); };/* Master list of route map. */static struct route_map_list route_map_master = { NULL, NULL, NULL, NULL };static voidroute_map_rule_delete (struct route_map_rule_list *, struct route_map_rule *);static voidroute_map_index_delete (struct route_map_index *, int);/* New route map allocation. Please note route map's name must be specified. */static struct route_map *route_map_new (char *name){ struct route_map *new; new = XCALLOC (MTYPE_ROUTE_MAP, sizeof (struct route_map)); new->name = XSTRDUP (MTYPE_ROUTE_MAP_NAME, name); return new;}/* Add new name to route_map. */static struct route_map *route_map_add (char *name){ struct route_map *map; struct route_map_list *list; map = route_map_new (name); list = &route_map_master; map->next = NULL; map->prev = list->tail; if (list->tail) list->tail->next = map; else list->head = map; list->tail = map; /* Execute hook. */ if (route_map_master.add_hook) (*route_map_master.add_hook) (name); return map;}/* Route map delete from list. */static voidroute_map_delete (struct route_map *map){ struct route_map_list *list; struct route_map_index *index; char *name; while ((index = map->head) != NULL) route_map_index_delete (index, 0); name = map->name; list = &route_map_master; if (map->next) map->next->prev = map->prev; else list->tail = map->prev; if (map->prev) map->prev->next = map->next; else list->head = map->next; XFREE (MTYPE_ROUTE_MAP, map); /* Execute deletion hook. */ if (route_map_master.delete_hook) (*route_map_master.delete_hook) (name); if (name) XFREE (MTYPE_ROUTE_MAP_NAME, name);}/* Lookup route map by route map name string. */struct route_map *route_map_lookup_by_name (char *name){ struct route_map *map; for (map = route_map_master.head; map; map = map->next) if (strcmp (map->name, name) == 0) return map; return NULL;}/* Lookup route map. If there isn't route map create one and return it. */struct route_map *route_map_get (char *name){ struct route_map *map; map = route_map_lookup_by_name (name); if (map == NULL) map = route_map_add (name); return map;}/* Return route map's type string. */static char *route_map_type_str (enum route_map_type type){ switch (type) { case RMAP_PERMIT: return "permit"; break; case RMAP_DENY: return "deny"; break; default: return ""; break; }}introute_map_empty (struct route_map *map){ if (map->head == NULL && map->tail == NULL) return 1; else return 0;}/* For debug. */voidroute_map_print (){ struct route_map *map; struct route_map_index *index; struct route_map_rule *rule; for (map = route_map_master.head; map; map = map->next) for (index = map->head; index; index = index->next) { printf ("route-map %s %s %d\n", map->name, route_map_type_str (index->type), index->pref); for (rule = index->match_list.head; rule; rule = rule->next) printf (" match %s %s\n", rule->cmd->str, rule->rule_str); for (rule = index->set_list.head; rule; rule = rule->next) printf (" set %s %s\n", rule->cmd->str, rule->rule_str); if (index->exitpolicy == RMAP_GOTO) printf (" on-match goto %d\n", index->nextpref); if (index->exitpolicy == RMAP_NEXT) printf (" on-match next\n"); }}/* New route map allocation. Please note route map's name must be specified. */struct route_map_index *route_map_index_new (){ struct route_map_index *new; new = XCALLOC (MTYPE_ROUTE_MAP_INDEX, sizeof (struct route_map_index)); new->exitpolicy = RMAP_EXIT; /* Default to Cisco-style */ return new;}/* Free route map index. */static voidroute_map_index_delete (struct route_map_index *index, int notify){ struct route_map_rule *rule; /* Free route match. */ while ((rule = index->match_list.head) != NULL) route_map_rule_delete (&index->match_list, rule); /* Free route set. */ while ((rule = index->set_list.head) != NULL) route_map_rule_delete (&index->set_list, rule); /* Remove index from route map list. */ if (index->next) index->next->prev = index->prev; else index->map->tail = index->prev; if (index->prev) index->prev->next = index->next; else index->map->head = index->next; /* Execute event hook. */ if (route_map_master.event_hook && notify) (*route_map_master.event_hook) (RMAP_EVENT_INDEX_DELETED, index->map->name); XFREE (MTYPE_ROUTE_MAP_INDEX, index);}/* Lookup index from route map. */struct route_map_index *route_map_index_lookup (struct route_map *map, enum route_map_type type, int pref){ struct route_map_index *index; for (index = map->head; index; index = index->next) if ((index->type == type || type == RMAP_ANY) && index->pref == pref) return index; return NULL;}/* Add new index to route map. */struct route_map_index *route_map_index_add (struct route_map *map, enum route_map_type type, int pref){ struct route_map_index *index; struct route_map_index *point; /* Allocate new route map inex. */ index = route_map_index_new (); index->map = map; index->type = type; index->pref = pref; /* Compare preference. */ for (point = map->head; point; point = point->next) if (point->pref >= pref) break; if (map->head == NULL) { map->head = map->tail = index; } else if (point == NULL) { index->prev = map->tail; map->tail->next = index; map->tail = index; } else if (point == map->head) { index->next = map->head; map->head->prev = index; map->head = index; } else { index->next = point; index->prev = point->prev; if (point->prev) point->prev->next = index; point->prev = index; } /* Execute event hook. */ if (route_map_master.event_hook) (*route_map_master.event_hook) (RMAP_EVENT_INDEX_ADDED, map->name); return index;}/* Get route map index. */struct route_map_index *route_map_index_get (struct route_map *map, enum route_map_type type, int pref){ struct route_map_index *index; index = route_map_index_lookup (map, RMAP_ANY, pref); if (index && index->type != type) { /* Delete index from route map. */ route_map_index_delete (index, 1); index = NULL; } if (index == NULL) index = route_map_index_add (map, type, pref); return index;}/* New route map rule */struct route_map_rule *route_map_rule_new (){ struct route_map_rule *new; new = XCALLOC (MTYPE_ROUTE_MAP_RULE, sizeof (struct route_map_rule)); return new;}/* Install rule command to the match list. */voidroute_map_install_match (struct route_map_rule_cmd *cmd){ vector_set (route_match_vec, cmd);}/* Install rule command to the set list. */voidroute_map_install_set (struct route_map_rule_cmd *cmd){ vector_set (route_set_vec, cmd);}/* Lookup rule command from match list. */struct route_map_rule_cmd *route_map_lookup_match (char *name){ int i; struct route_map_rule_cmd *rule; for (i = 0; i < vector_max (route_match_vec); i++) if ((rule = vector_slot (route_match_vec, i)) != NULL) if (strcmp (rule->str, name) == 0) return rule; return NULL;}/* Lookup rule command from set list. */struct route_map_rule_cmd *route_map_lookup_set (char *name){ int i; struct route_map_rule_cmd *rule; for (i = 0; i < vector_max (route_set_vec); i++) if ((rule = vector_slot (route_set_vec, i)) != NULL) if (strcmp (rule->str, name) == 0) return rule; return NULL;}/* Add match and set rule to rule list. */static voidroute_map_rule_add (struct route_map_rule_list *list, struct route_map_rule *rule){ rule->next = NULL; rule->prev = list->tail; if (list->tail) list->tail->next = rule; else list->head = rule; list->tail = rule;}/* Delete rule from rule list. */static voidroute_map_rule_delete (struct route_map_rule_list *list, struct route_map_rule *rule){ if (rule->cmd->func_free) (*rule->cmd->func_free) (rule->value); if (rule->rule_str) XFREE (MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str); if (rule->next) rule->next->prev = rule->prev; else list->tail = rule->prev; if (rule->prev) rule->prev->next = rule->next; else list->head = rule->next; XFREE (MTYPE_ROUTE_MAP_RULE, rule);}/* strcmp wrapper function which don't crush even argument is NULL. */intrulecmp (char *dst, char *src){ if (dst == NULL) { if (src == NULL) return 0; else return 1; } else { if (src == NULL) return 1; else return strcmp (dst, src); } return 1;}/* Add match statement to route map. */introute_map_add_match (struct route_map_index *index, char *match_name, char *match_arg){ struct route_map_rule *rule; struct route_map_rule *next; struct route_map_rule_cmd *cmd; void *compile; int replaced = 0; /* First lookup rule for add match statement. */ cmd = route_map_lookup_match (match_name); if (cmd == NULL) return RMAP_RULE_MISSING; /* Next call compile function for this match statement. */ if (cmd->func_compile) { compile= (*cmd->func_compile)(match_arg); if (compile == NULL) return RMAP_COMPILE_ERROR; } else compile = NULL; /* If argument is completely same ignore it. */ for (rule = index->match_list.head; rule; rule = next) { next = rule->next; if (rule->cmd == cmd) { route_map_rule_delete (&index->match_list, rule); replaced = 1; } } /* Add new route map match rule. */ rule = route_map_rule_new (); rule->cmd = cmd; rule->value = compile; if (match_arg) rule->rule_str = XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR, match_arg); else rule->rule_str = NULL; /* Add new route match rule to linked list. */ route_map_rule_add (&index->match_list, rule); /* Execute event hook. */ if (route_map_master.event_hook) (*route_map_master.event_hook) (replaced ? RMAP_EVENT_MATCH_REPLACED: RMAP_EVENT_MATCH_ADDED, index->map->name); return 0;}/* Delete specified route match rule. */introute_map_delete_match (struct route_map_index *index, char *match_name, char *match_arg){ struct route_map_rule *rule; struct route_map_rule_cmd *cmd; cmd = route_map_lookup_match (match_name); if (cmd == NULL) return 1; for (rule = index->match_list.head; rule; rule = rule->next) if (rule->cmd == cmd && (rulecmp (rule->rule_str, match_arg) == 0 || match_arg == NULL)) { route_map_rule_delete (&index->match_list, rule); /* Execute event hook. */ if (route_map_master.event_hook) (*route_map_master.event_hook) (RMAP_EVENT_MATCH_DELETED, index->map->name); return 0; } /* Can't find matched rule. */ return 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -