BIND9源码分析之acl 的实现

  BIND配置中一大堆一大堆的acl,什么allow-query, allow-recursion, allow-update还有view的match-clients等等等等。

  acl中的主要存储的就是IP,可以把acl当做是一个IP池,在需要验证的时候就从这个IP池中查找该IP是否存在。那么BIND中如何实现这个非常常用的IP池的呢?

      BIND中的acl用数据结构dns_acl来表示:

struct dns_acl {
	unsigned int		magic;
	isc_mem_t		*mctx;
	isc_refcount_t		refcount;
	dns_iptable_t		*iptable;
#define node_count		iptable->radix->num_added_node
	dns_aclelement_t	*elements;
	isc_boolean_t 		has_negatives;
	unsigned int 		alloc;		/*%< Elements allocated */
	unsigned int 		length;		/*%< Elements initialized */
	char 			*name;		/*%< Temporary use only */
	ISC_LINK(dns_acl_t) 	nextincache;	/*%< Ditto */
};

  其中的iptable本质上就是一个radix tree(中文名叫基数树)。

     radix tree简直就是为IP路由存储和查找而生的(实际上IP路由查找正是radix tree最常用的领域之一)。在存储IP数据,尤其是CIDR的时候,radix退化成一种二叉树,左右子树分别表示IP的二进制表示的1或者0,所以对于IPv4,radix 树的最大高度是32。对于CIDR的存储,只需要存储前缀位就可以了,比如存储130.50.30.40/18,只需要存储前18位即可,后面的14位不用存储,因为在查找ACL的时候,只要对比到第18位就可以确定是否让此IP通过验证。

  BIND9中radix tree的实现比较复杂,可能是处于需要兼容IPv4和IPv6,以及IP地址的先后关系的考虑。

  nginx中的geo模块也用radix tree存储CIDR形式的IP,core/ngx_radix_tree.c的实现还是相当短小精悍的。

原文地址:https://www.cnblogs.com/cobbliu/p/3393513.html