radix.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007, 2008, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /*
00018  * This source was adapted from MRT's RCS Ids:
00019  * Id: radix.h,v 1.6 1999/08/03 03:32:53 masaki Exp
00020  * Id: mrt.h,v 1.57.2.6 1999/12/28 23:41:27 labovit Exp
00021  * Id: defs.h,v 1.5.2.2 2000/01/15 14:19:16 masaki Exp
00022  */
00023 
00024 #include <isc/magic.h>
00025 #include <isc/types.h>
00026 #include <isc/mutex.h>
00027 #include <isc/net.h>
00028 #include <isc/refcount.h>
00029 
00030 #include <string.h>
00031 
00032 #ifndef _RADIX_H
00033 #define _RADIX_H
00034 
00035 #define NETADDR_TO_PREFIX_T(na,pt,bits,is_ecs)  \
00036         do { \
00037                 const void *p = na; \
00038                 memset(&(pt), 0, sizeof(pt)); \
00039                 if (p != NULL) { \
00040                         (pt).family = (na)->family; \
00041                         (pt).bitlen = (bits); \
00042                         if ((pt).family == AF_INET6) { \
00043                                 memmove(&(pt).add.sin6, &(na)->type.in6, \
00044                                        ((bits)+7)/8); \
00045                         } else \
00046                                 memmove(&(pt).add.sin, &(na)->type.in, \
00047                                        ((bits)+7)/8); \
00048                 } else { \
00049                         (pt).family = AF_UNSPEC; \
00050                         (pt).bitlen = 0; \
00051                 } \
00052                 (pt).ecs = is_ecs; \
00053                 isc_refcount_init(&(pt).refcount, 0); \
00054         } while(0)
00055 
00056 typedef struct isc_prefix {
00057         isc_mem_t *mctx;
00058         unsigned int family;    /* AF_INET | AF_INET6, or AF_UNSPEC for "any" */
00059         unsigned int bitlen;    /* 0 for "any" */
00060         isc_boolean_t ecs;      /* ISC_TRUE for an EDNS client subnet address */
00061         isc_refcount_t refcount;
00062         union {
00063                 struct in_addr sin;
00064                 struct in6_addr sin6;
00065         } add;
00066 } isc_prefix_t;
00067 
00068 typedef void (*isc_radix_destroyfunc_t)(void *);
00069 typedef void (*isc_radix_processfunc_t)(isc_prefix_t *, void **);
00070 
00071 #define isc_prefix_tochar(prefix) ((char *)&(prefix)->add.sin)
00072 #define isc_prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin)
00073 
00074 #define BIT_TEST(f, b)  ((f) & (b))
00075 
00076 /*
00077  * We need "first match" when we search the radix tree to preserve
00078  * compatibility with the existing ACL implementation. Radix trees
00079  * naturally lend themselves to "best match". In order to get "first match"
00080  * behavior, we keep track of the order in which entries are added to the
00081  * tree--and when a search is made, we find all matching entries, and
00082  * return the one that was added first.
00083  *
00084  * An IPv4 prefix and an IPv6 prefix may share a radix tree node if they
00085  * have the same length and bit pattern (e.g., 127/8 and 7f::/8).  Also,
00086  * a node that matches a client address may also match an EDNS client
00087  * subnet address.  To disambiguate between these, node_num and data
00088  * are four-element arrays;
00089  *
00090  *   - node_num[0] and data[0] are used for IPv4 client addresses
00091  *   - node_num[1] and data[1] for IPv4 client subnet addresses
00092  *   - node_num[2] and data[2] are used for IPv6 client addresses
00093  *   - node_num[3] and data[3] for IPv6 client subnet addresses
00094  *
00095  * A prefix of 0/0 (aka "any" or "none"), is always stored as IPv4,
00096  * but matches IPv6 addresses too, as well as all client subnet
00097  * addresses.
00098  */
00099 
00100 #define ISC_RADIX_OFF(p) \
00101         ((((p)->family == AF_INET6) ? 1 : 0) + ((p)->ecs ? 2 : 0))
00102 
00103 typedef struct isc_radix_node {
00104         isc_mem_t *mctx;
00105         isc_uint32_t bit;               /* bit length of the prefix */
00106         isc_prefix_t *prefix;           /* who we are in radix tree */
00107         struct isc_radix_node *l, *r;   /* left and right children */
00108         struct isc_radix_node *parent;  /* may be used */
00109         void *data[4];                  /* pointers to IPv4 and IPV6 data */
00110         int node_num[4];                /* which node this was in the tree,
00111                                            or -1 for glue nodes */
00112 } isc_radix_node_t;
00113 
00114 #define RADIX_TREE_MAGIC         ISC_MAGIC('R','d','x','T');
00115 #define RADIX_TREE_VALID(a)      ISC_MAGIC_VALID(a, RADIX_TREE_MAGIC);
00116 
00117 typedef struct isc_radix_tree {
00118         unsigned int magic;
00119         isc_mem_t *mctx;
00120         isc_radix_node_t *head;
00121         isc_uint32_t maxbits;           /* for IP, 32 bit addresses */
00122         int num_active_node;            /* for debugging purposes */
00123         int num_added_node;             /* total number of nodes */
00124 } isc_radix_tree_t;
00125 
00126 isc_result_t
00127 isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
00128                  isc_prefix_t *prefix);
00129 /*%<
00130  * Search 'radix' for the best match to 'prefix'.
00131  * Return the node found in '*target'.
00132  *
00133  * Requires:
00134  * \li  'radix' to be valid.
00135  * \li  'target' is not NULL and "*target" is NULL.
00136  * \li  'prefix' to be valid.
00137  *
00138  * Returns:
00139  * \li  ISC_R_NOTFOUND
00140  * \li  ISC_R_SUCCESS
00141  */
00142 
00143 isc_result_t
00144 isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
00145                  isc_radix_node_t *source, isc_prefix_t *prefix);
00146 /*%<
00147  * Insert 'source' or 'prefix' into the radix tree 'radix'.
00148  * Return the node added in 'target'.
00149  *
00150  * Requires:
00151  * \li  'radix' to be valid.
00152  * \li  'target' is not NULL and "*target" is NULL.
00153  * \li  'prefix' to be valid or 'source' to be non NULL and contain
00154  *      a valid prefix.
00155  *
00156  * Returns:
00157  * \li  ISC_R_NOMEMORY
00158  * \li  ISC_R_SUCCESS
00159  */
00160 
00161 void
00162 isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node);
00163 /*%<
00164  * Remove the node 'node' from the radix tree 'radix'.
00165  *
00166  * Requires:
00167  * \li  'radix' to be valid.
00168  * \li  'node' to be valid.
00169  */
00170 
00171 isc_result_t
00172 isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits);
00173 /*%<
00174  * Create a radix tree with a maximum depth of 'maxbits';
00175  *
00176  * Requires:
00177  * \li  'mctx' to be valid.
00178  * \li  'target' to be non NULL and '*target' to be NULL.
00179  * \li  'maxbits' to be less than or equal to RADIX_MAXBITS.
00180  *
00181  * Returns:
00182  * \li  ISC_R_NOMEMORY
00183  * \li  ISC_R_SUCCESS
00184  */
00185 
00186 void
00187 isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
00188 /*%<
00189  * Destroy a radix tree optionally calling 'func' to clean up node data.
00190  *
00191  * Requires:
00192  * \li  'radix' to be valid.
00193  */
00194 
00195 void
00196 isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func);
00197 /*%<
00198  * Walk a radix tree calling 'func' to process node data.
00199  *
00200  * Requires:
00201  * \li  'radix' to be valid.
00202  * \li  'func' to point to a function.
00203  */
00204 
00205 #define RADIX_MAXBITS 128
00206 #define RADIX_NBIT(x)        (0x80 >> ((x) & 0x7f))
00207 #define RADIX_NBYTE(x)       ((x) >> 3)
00208 
00209 #define RADIX_DATA_GET(node, type) (type *)((node)->data)
00210 #define RADIX_DATA_SET(node, value) ((node)->data = (void *)(value))
00211 
00212 #define RADIX_WALK(Xhead, Xnode) \
00213     do { \
00214         isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; \
00215         isc_radix_node_t **Xsp = Xstack; \
00216         isc_radix_node_t *Xrn = (Xhead); \
00217         while ((Xnode = Xrn)) { \
00218             if (Xnode->prefix)
00219 
00220 #define RADIX_WALK_ALL(Xhead, Xnode) \
00221 do { \
00222         isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; \
00223         isc_radix_node_t **Xsp = Xstack; \
00224         isc_radix_node_t *Xrn = (Xhead); \
00225         while ((Xnode = Xrn)) { \
00226             if (1)
00227 
00228 #define RADIX_WALK_BREAK { \
00229             if (Xsp != Xstack) { \
00230                 Xrn = *(--Xsp); \
00231              } else { \
00232                 Xrn = (radix_node_t *) 0; \
00233             } \
00234             continue; }
00235 
00236 #define RADIX_WALK_END \
00237             if (Xrn->l) { \
00238                 if (Xrn->r) { \
00239                     *Xsp++ = Xrn->r; \
00240                 } \
00241                 Xrn = Xrn->l; \
00242             } else if (Xrn->r) { \
00243                 Xrn = Xrn->r; \
00244             } else if (Xsp != Xstack) { \
00245                 Xrn = *(--Xsp); \
00246             } else { \
00247                 Xrn = (isc_radix_node_t *) 0; \
00248             } \
00249         } \
00250     } while (0)
00251 
00252 #endif /* _RADIX_H */

Generated on Tue Apr 28 17:41:04 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha