⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filter.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Route filtering function. * Copyright (C) 1998, 1999 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2, or (at your * option) any later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING.  If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <zebra.h>#include "prefix.h"#include "filter.h"#include "memory.h"#include "command.h"#include "sockunion.h"#include "buffer.h"struct filter_cisco{  /* Cisco access-list */  int extended;  struct in_addr addr;  struct in_addr addr_mask;  struct in_addr mask;  struct in_addr mask_mask;};struct filter_zebra{  /* If this filter is "exact" match then this flag is set. */  int exact;  /* Prefix information. */  struct prefix prefix;};/* Filter element of access list */struct filter{  /* For doubly linked list. */  struct filter *next;  struct filter *prev;  /* Filter type information. */  enum filter_type type;  /* Cisco access-list */  int cisco;  union    {      struct filter_cisco cfilter;      struct filter_zebra zfilter;    } u;};/* List of access_list. */struct access_list_list{  struct access_list *head;  struct access_list *tail;};/* Master structure of access_list. */struct access_master{  /* List of access_list which name is number. */  struct access_list_list num;  /* List of access_list which name is string. */  struct access_list_list str;  /* Hook function which is executed when new access_list is added. */  void (*add_hook) ();  /* Hook function which is executed when access_list is deleted. */  void (*delete_hook) ();};/* Static structure for IPv4 access_list's master. */static struct access_master access_master_ipv4 = {   {NULL, NULL},  {NULL, NULL},  NULL,  NULL,};#ifdef HAVE_IPV6/* Static structure for IPv6 access_list's master. */static struct access_master access_master_ipv6 = {   {NULL, NULL},  {NULL, NULL},  NULL,  NULL,};#endif /* HAVE_IPV6 */struct access_master *access_master_get (afi_t afi){  if (afi == AFI_IP)    return &access_master_ipv4;#ifdef HAVE_IPV6  else if (afi == AFI_IP6)    return &access_master_ipv6;#endif /* HAVE_IPV6 */  return NULL;}/* Allocate new filter structure. */struct filter *filter_new (){  return (struct filter *) XCALLOC (MTYPE_ACCESS_FILTER,				    sizeof (struct filter));}voidfilter_free (struct filter *filter){  XFREE (MTYPE_ACCESS_FILTER, filter);}/* Return string of filter_type. */static char *filter_type_str (struct filter *filter){  switch (filter->type)    {    case FILTER_PERMIT:      return "permit";      break;    case FILTER_DENY:      return "deny";      break;    case FILTER_DYNAMIC:      return "dynamic";      break;    default:      return "";      break;    }}/* If filter match to the prefix then return 1. */static intfilter_match_cisco (struct filter *mfilter, struct prefix *p){  struct filter_cisco *filter;  struct in_addr mask;  u_int32_t check_addr;  u_int32_t check_mask;  filter = &mfilter->u.cfilter;  check_addr = p->u.prefix4.s_addr & ~filter->addr_mask.s_addr;  if (filter->extended)    {      masklen2ip (p->prefixlen, &mask);      check_mask = mask.s_addr & ~filter->mask_mask.s_addr;      if (memcmp (&check_addr, &filter->addr.s_addr, 4) == 0          && memcmp (&check_mask, &filter->mask.s_addr, 4) == 0)	return 1;    }  else if (memcmp (&check_addr, &filter->addr.s_addr, 4) == 0)    return 1;  return 0;}/* If filter match to the prefix then return 1. */static intfilter_match_zebra (struct filter *mfilter, struct prefix *p){  struct filter_zebra *filter;  filter = &mfilter->u.zfilter;  if (filter->prefix.family == p->family)    {      if (filter->exact)	{	  if (filter->prefix.prefixlen == p->prefixlen)	    return prefix_match (&filter->prefix, p);	  else	    return 0;	}      else	return prefix_match (&filter->prefix, p);    }  else    return 0;}/* Allocate new access list structure. */struct access_list *access_list_new (){  return (struct access_list *) XCALLOC (MTYPE_ACCESS_LIST,					 sizeof (struct access_list));}/* Free allocated access_list. */voidaccess_list_free (struct access_list *access){  XFREE (MTYPE_ACCESS_LIST, access);}/* Delete access_list from access_master and free it. */voidaccess_list_delete (struct access_list *access){  struct filter *filter;  struct filter *next;  struct access_list_list *list;  struct access_master *master;  for (filter = access->head; filter; filter = next)    {      next = filter->next;      filter_free (filter);    }  master = access->master;  if (access->type == ACCESS_TYPE_NUMBER)    list = &master->num;  else    list = &master->str;  if (access->next)    access->next->prev = access->prev;  else    list->tail = access->prev;  if (access->prev)    access->prev->next = access->next;  else    list->head = access->next;  if (access->name)    XFREE (MTYPE_ACCESS_LIST_STR, access->name);  if (access->remark)    XFREE (MTYPE_TMP, access->remark);  access_list_free (access);}/* Insert new access list to list of access_list.  Each acceess_list   is sorted by the name. */struct access_list *access_list_insert (afi_t afi, char *name){  int i;  long number;  struct access_list *access;  struct access_list *point;  struct access_list_list *alist;  struct access_master *master;  master = access_master_get (afi);  if (master == NULL)    return NULL;  /* Allocate new access_list and copy given name. */  access = access_list_new ();  access->name = XSTRDUP (MTYPE_ACCESS_LIST_STR, name);  access->master = master;  /* If name is made by all digit character.  We treat it as     number. */  for (number = 0, i = 0; i < strlen (name); i++)    {      if (isdigit ((int) name[i]))	number = (number * 10) + (name[i] - '0');      else	break;    }  /* In case of name is all digit character */  if (i == strlen (name))    {      access->type = ACCESS_TYPE_NUMBER;      /* Set access_list to number list. */      alist = &master->num;      for (point = alist->head; point; point = point->next)	if (atol (point->name) >= number)	  break;    }  else    {      access->type = ACCESS_TYPE_STRING;      /* Set access_list to string list. */      alist = &master->str;        /* Set point to insertion point. */      for (point = alist->head; point; point = point->next)	if (strcmp (point->name, name) >= 0)	  break;    }  /* In case of this is the first element of master. */  if (alist->head == NULL)    {      alist->head = alist->tail = access;      return access;    }  /* In case of insertion is made at the tail of access_list. */  if (point == NULL)    {      access->prev = alist->tail;      alist->tail->next = access;      alist->tail = access;      return access;    }  /* In case of insertion is made at the head of access_list. */  if (point == alist->head)    {      access->next = alist->head;      alist->head->prev = access;      alist->head = access;      return access;    }  /* Insertion is made at middle of the access_list. */  access->next = point;  access->prev = point->prev;  if (point->prev)    point->prev->next = access;  point->prev = access;  return access;}/* Lookup access_list from list of access_list by name. */struct access_list *access_list_lookup (afi_t afi, char *name){  struct access_list *access;  struct access_master *master;  if (name == NULL)    return NULL;  master = access_master_get (afi);  if (master == NULL)    return NULL;  for (access = master->num.head; access; access = access->next)    if (strcmp (access->name, name) == 0)      return access;  for (access = master->str.head; access; access = access->next)    if (strcmp (access->name, name) == 0)      return access;  return NULL;}/* Get access list from list of access_list.  If there isn't matched   access_list create new one and return it. */struct access_list *access_list_get (afi_t afi, char *name){  struct access_list *access;  access = access_list_lookup (afi, name);  if (access == NULL)    access = access_list_insert (afi, name);  return access;}/* Apply access list to object (which should be struct prefix *). */enum filter_typeaccess_list_apply (struct access_list *access, void *object){  struct filter *filter;  struct prefix *p;  p = (struct prefix *) object;  if (access == NULL)    return FILTER_DENY;  for (filter = access->head; filter; filter = filter->next)    {      if (filter->cisco)	{	  if (filter_match_cisco (filter, p))	    return filter->type;	}      else	{	  if (filter_match_zebra (filter, p))	    return filter->type;	}    }  return FILTER_DENY;}/* Add hook function. */voidaccess_list_add_hook (void (*func) (struct access_list *access)){  access_master_ipv4.add_hook = func;#ifdef HAVE_IPV6  access_master_ipv6.add_hook = func;#endif /* HAVE_IPV6 */}/* Delete hook function. */voidaccess_list_delete_hook (void (*func) (struct access_list *access)){  access_master_ipv4.delete_hook = func;#ifdef HAVE_IPV6  access_master_ipv6.delete_hook = func;#endif /* HAVE_IPV6 */}/* Add new filter to the end of specified access_list. */voidaccess_list_filter_add (struct access_list *access, struct filter *filter){  filter->next = NULL;  filter->prev = access->tail;  if (access->tail)    access->tail->next = filter;  else    access->head = filter;  access->tail = filter;  /* Run hook function. */  if (access->master->add_hook)    (*access->master->add_hook) (access);}/* If access_list has no filter then return 1. */static intaccess_list_empty (struct access_list *access){  if (access->head == NULL && access->tail == NULL)    return 1;  else    return 0;}/* Delete filter from specified access_list.  If there is hook   function execute it. */voidaccess_list_filter_delete (struct access_list *access, struct filter *filter){  struct access_master *master;  master = access->master;  if (filter->next)    filter->next->prev = filter->prev;  else    access->tail = filter->prev;  if (filter->prev)    filter->prev->next = filter->next;  else    access->head = filter->next;  filter_free (filter);  /* If access_list becomes empty delete it from access_master. */  if (access_list_empty (access))    access_list_delete (access);  /* Run hook function. */  if (master->delete_hook)    (*master->delete_hook) (access);}/*  deny    Specify packets to reject  permit  Specify packets to forward  dynamic ?*//*  Hostname or A.B.C.D  Address to match  any                  Any source host  host                 A single host address*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -