Bug Fix
This commit is contained in:
@@ -4,12 +4,12 @@
|
|||||||
# IPV4: :53
|
# IPV4: :53
|
||||||
# IPV6 [::]:53
|
# IPV6 [::]:53
|
||||||
|
|
||||||
bind [::]:535
|
bind [::]:53
|
||||||
|
|
||||||
# dns cache size
|
# dns cache size
|
||||||
# cache-size [number]
|
# cache-size [number]
|
||||||
# 0: for no cache
|
# 0: for no cache
|
||||||
cache-size 1024
|
cache-size 512
|
||||||
|
|
||||||
# set log level
|
# set log level
|
||||||
# loglevel [level], level=error, warn, info, debug
|
# loglevel [level], level=error, warn, info, debug
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ int config_address(char *value)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(address, 0, sizeof(*address));
|
||||||
len = end - begin;
|
len = end - begin;
|
||||||
memcpy(address->domain, begin, len);
|
memcpy(address->domain, begin, len);
|
||||||
address->domain[len] = 0;
|
address->domain[len] = 0;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ void _dns_cache_delete(struct dns_cache *dns_cache)
|
|||||||
{
|
{
|
||||||
hash_del(&dns_cache->node);
|
hash_del(&dns_cache->node);
|
||||||
list_del_init(&dns_cache->list);
|
list_del_init(&dns_cache->list);
|
||||||
|
dns_cache_head.num--;
|
||||||
free(dns_cache);
|
free(dns_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,12 +93,12 @@ int dns_cache_insert(char *domain, int ttl, dns_type_t qtype, unsigned char *add
|
|||||||
|
|
||||||
pthread_mutex_lock(&dns_cache_head.lock);
|
pthread_mutex_lock(&dns_cache_head.lock);
|
||||||
hash_add(dns_cache_head.cache_hash, &dns_cache->node, key);
|
hash_add(dns_cache_head.cache_hash, &dns_cache->node, key);
|
||||||
list_add(&dns_cache->list, &dns_cache_head.cache_list);
|
list_add_tail(&dns_cache->list, &dns_cache_head.cache_list);
|
||||||
|
|
||||||
dns_cache_head.num++;
|
dns_cache_head.num++;
|
||||||
if (dns_cache_head.num > dns_cache_head.size) {
|
if (dns_cache_head.num > dns_cache_head.size) {
|
||||||
struct dns_cache *del_cache;
|
struct dns_cache *del_cache;
|
||||||
del_cache = _dns_cache_last();
|
del_cache = _dns_cache_first();
|
||||||
dns_cache_release(del_cache);
|
dns_cache_release(del_cache);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||||
@@ -181,8 +182,37 @@ void dns_cache_delete(struct dns_cache *dns_cache)
|
|||||||
void dns_cache_update(struct dns_cache *dns_cache)
|
void dns_cache_update(struct dns_cache *dns_cache)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&dns_cache_head.lock);
|
pthread_mutex_lock(&dns_cache_head.lock);
|
||||||
list_del_init(&dns_cache->list);
|
if (!list_empty(&dns_cache->list)) {
|
||||||
list_add(&dns_cache->list, &dns_cache_head.cache_list);
|
list_del_init(&dns_cache->list);
|
||||||
|
list_add_tail(&dns_cache->list, &dns_cache_head.cache_list);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dns_cache_invalidate(void)
|
||||||
|
{
|
||||||
|
struct dns_cache *dns_cache = NULL;
|
||||||
|
struct dns_cache *tmp;
|
||||||
|
time_t now;
|
||||||
|
int ttl = 0;
|
||||||
|
|
||||||
|
if (dns_cache_head.size <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
pthread_mutex_lock(&dns_cache_head.lock);
|
||||||
|
list_for_each_entry_safe(dns_cache, tmp, &dns_cache_head.cache_list, list)
|
||||||
|
{
|
||||||
|
ttl = dns_cache->insert_time + dns_cache->ttl - now;
|
||||||
|
if (ttl > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_del(&dns_cache->node);
|
||||||
|
list_del_init(&dns_cache->list);
|
||||||
|
dns_cache_release(dns_cache);
|
||||||
|
}
|
||||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ void dns_cache_release(struct dns_cache *dns_cache);
|
|||||||
|
|
||||||
void dns_cache_update(struct dns_cache *dns_cache);
|
void dns_cache_update(struct dns_cache *dns_cache);
|
||||||
|
|
||||||
|
void dns_cache_invalidate(void);
|
||||||
|
|
||||||
int dns_cache_get_ttl(struct dns_cache *dns_cache);
|
int dns_cache_get_ttl(struct dns_cache *dns_cache);
|
||||||
|
|
||||||
void dns_cache_destroy(void);
|
void dns_cache_destroy(void);
|
||||||
|
|||||||
@@ -680,28 +680,8 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _dns_server_art_iter_callback(void *data, const unsigned char *key, uint32_t key_len, void *value)
|
|
||||||
{
|
|
||||||
struct dns_address **address;
|
|
||||||
address = data;
|
|
||||||
*address = value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _dns_server_art_domain_cmp(const art_leaf *n, const unsigned char *prefix, int prefix_len)
|
|
||||||
{
|
|
||||||
// Fail if the prefix length is too short
|
|
||||||
if (n->key_len > (uint32_t)prefix_len) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare the keys
|
|
||||||
return memcmp(n->key, prefix, n->key_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct dns_address *_dns_server_get_address_by_domain(char *domain, int qtype)
|
static struct dns_address *_dns_server_get_address_by_domain(char *domain, int qtype)
|
||||||
{
|
{
|
||||||
struct dns_address *address = NULL;
|
|
||||||
int domain_len;
|
int domain_len;
|
||||||
char domain_key[DNS_MAX_CNAME_LEN];
|
char domain_key[DNS_MAX_CNAME_LEN];
|
||||||
char type = '4';
|
char type = '4';
|
||||||
@@ -721,11 +701,8 @@ static struct dns_address *_dns_server_get_address_by_domain(char *domain, int q
|
|||||||
reverse_string(domain_key + 1, domain, domain_len);
|
reverse_string(domain_key + 1, domain, domain_len);
|
||||||
domain_key[0] = type;
|
domain_key[0] = type;
|
||||||
domain_len++;
|
domain_len++;
|
||||||
if (art_iter_cmp(&dns_conf_address, (unsigned char *)domain_key, domain_len, _dns_server_art_iter_callback, _dns_server_art_domain_cmp, &address) != 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return address;
|
return art_substring(&dns_conf_address, (unsigned char *)domain_key, domain_len);;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
|
static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
|
||||||
@@ -796,6 +773,7 @@ static int _dns_server_process_cache(struct dns_request *request, struct dns_pac
|
|||||||
|
|
||||||
request->rcode = DNS_RC_NOERROR;
|
request->rcode = DNS_RC_NOERROR;
|
||||||
_dns_reply(request);
|
_dns_reply(request);
|
||||||
|
dns_cache_update(dns_cache);
|
||||||
dns_cache_release(dns_cache);
|
dns_cache_release(dns_cache);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -972,11 +950,27 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
|
|||||||
request->has_ping_tcp = 1;
|
request->has_ping_tcp = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _dns_server_period_run_second(void)
|
||||||
|
{
|
||||||
|
static unsigned int sec = 0;
|
||||||
|
sec++;
|
||||||
|
|
||||||
|
if (sec % 2 == 0) {
|
||||||
|
dns_cache_invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _dns_server_period_run(void)
|
void _dns_server_period_run(void)
|
||||||
{
|
{
|
||||||
struct dns_request *request, *tmp;
|
struct dns_request *request, *tmp;
|
||||||
|
static unsigned int msec = 0;
|
||||||
LIST_HEAD(check_list);
|
LIST_HEAD(check_list);
|
||||||
|
|
||||||
|
msec++;
|
||||||
|
if (msec % 10 == 0) {
|
||||||
|
_dns_server_period_run_second();
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long now = get_tick_count();
|
unsigned long now = get_tick_count();
|
||||||
|
|
||||||
pthread_mutex_lock(&server.request_list_lock);
|
pthread_mutex_lock(&server.request_list_lock);
|
||||||
@@ -1153,7 +1147,7 @@ int dns_server_init(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dns_cache_init(1024) != 0) {
|
if (dns_cache_init(dns_conf_cachesize) != 0) {
|
||||||
tlog(TLOG_ERROR, "init cache failed.");
|
tlog(TLOG_ERROR, "init cache failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1229,7 +1223,7 @@ void dns_server_exit(void)
|
|||||||
|
|
||||||
list_for_each_entry_safe(request, tmp, &remove_list, check_list)
|
list_for_each_entry_safe(request, tmp, &remove_list, check_list)
|
||||||
{
|
{
|
||||||
_dns_server_request_release(request);
|
_dns_server_request_remove(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_destroy(&server.request_list_lock);
|
pthread_mutex_destroy(&server.request_list_lock);
|
||||||
|
|||||||
@@ -185,6 +185,16 @@ void* art_delete(art_tree *t, const unsigned char *key, int key_len);
|
|||||||
*/
|
*/
|
||||||
void* art_search(const art_tree *t, const unsigned char *key, int key_len);
|
void* art_search(const art_tree *t, const unsigned char *key, int key_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches substring for a value in the ART tree
|
||||||
|
* @arg t The tree
|
||||||
|
* @arg str The key
|
||||||
|
* @arg str_len The length of the key
|
||||||
|
* @return NULL if the item was not found, otherwise
|
||||||
|
* the value pointer is returned.
|
||||||
|
*/
|
||||||
|
void *art_substring(const art_tree *t, const unsigned char *str, int str_len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the minimum valued leaf
|
* Returns the minimum valued leaf
|
||||||
* @return The minimum leaf or NULL
|
* @return The minimum leaf or NULL
|
||||||
@@ -223,21 +233,6 @@ int art_iter(art_tree *t, art_callback cb, void *data);
|
|||||||
*/
|
*/
|
||||||
int art_iter_prefix(art_tree *t, const unsigned char *prefix, int prefix_len, art_callback cb, void *data);
|
int art_iter_prefix(art_tree *t, const unsigned char *prefix, int prefix_len, art_callback cb, void *data);
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterates through the entries pairs in the map,
|
|
||||||
* invoking a callback for each that matches a given prefix.
|
|
||||||
* The call back gets a key, value for each and returns an integer stop value.
|
|
||||||
* If the callback returns non-zero, then the iteration stops.
|
|
||||||
* @arg t The tree to iterate over
|
|
||||||
* @arg prefix The prefix of keys to read
|
|
||||||
* @arg prefix_len The length of the prefix
|
|
||||||
* @arg cb The callback function to invoke
|
|
||||||
* @arg data Opaque handle passed to the callback
|
|
||||||
* @return 0 on success, or the return of the callback.
|
|
||||||
*/
|
|
||||||
typedef int(*art_key_cmp_callback)(const art_leaf *n, const unsigned char *prefix, int prefix_len);
|
|
||||||
int art_iter_cmp(art_tree *t, const unsigned char *str, int str_len, art_callback cb, art_key_cmp_callback key_cmp, void *data);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
103
src/lib/art.c
103
src/lib/art.c
@@ -912,17 +912,46 @@ int art_iter(art_tree *t, art_callback cb, void *data) {
|
|||||||
return recursive_iter(t->root, cb, data);
|
return recursive_iter(t->root, cb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int art_iter_cmp(art_tree *t, const unsigned char *key, int key_len, art_callback cb, art_key_cmp_callback key_cmp, void *data)
|
/**
|
||||||
{
|
* Checks if a leaf prefix matches
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
|
static int leaf_prefix_matches(const art_leaf *n, const unsigned char *prefix, int prefix_len) {
|
||||||
|
// Fail if the key length is too short
|
||||||
|
if (n->key_len < (uint32_t)prefix_len) return 1;
|
||||||
|
|
||||||
|
// Compare the keys
|
||||||
|
return memcmp(n->key, prefix, prefix_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates through the entries pairs in the map,
|
||||||
|
* invoking a callback for each that matches a given prefix.
|
||||||
|
* The call back gets a key, value for each and returns an integer stop value.
|
||||||
|
* If the callback returns non-zero, then the iteration stops.
|
||||||
|
* @arg t The tree to iterate over
|
||||||
|
* @arg prefix The prefix of keys to read
|
||||||
|
* @arg prefix_len The length of the prefix
|
||||||
|
* @arg cb The callback function to invoke
|
||||||
|
* @arg data Opaque handle passed to the callback
|
||||||
|
* @return 0 on success, or the return of the callback.
|
||||||
|
*/
|
||||||
|
int art_iter_prefix(art_tree *t, const unsigned char *key, int key_len, art_callback cb, void *data) {
|
||||||
art_node **child;
|
art_node **child;
|
||||||
art_node *n = t->root;
|
art_node *n = t->root;
|
||||||
int prefix_len, depth = 0;
|
int prefix_len, depth = 0;
|
||||||
while (n) {
|
while (n) {
|
||||||
|
|
||||||
|
if (IS_LEAF(n)) {
|
||||||
|
n = (art_node*)LEAF_RAW(n);
|
||||||
|
art_leaf *l = (art_leaf*)n;
|
||||||
|
printf("LEAF: %s\n", l->key);
|
||||||
|
}
|
||||||
// Might be a leaf
|
// Might be a leaf
|
||||||
if (IS_LEAF(n)) {
|
if (IS_LEAF(n)) {
|
||||||
n = (art_node*)LEAF_RAW(n);
|
n = (art_node*)LEAF_RAW(n);
|
||||||
// Check if the expanded path matches
|
// Check if the expanded path matches
|
||||||
if (!key_cmp((art_leaf*)n, key, key_len)) {
|
if (!leaf_prefix_matches((art_leaf*)n, key, key_len)) {
|
||||||
art_leaf *l = (art_leaf*)n;
|
art_leaf *l = (art_leaf*)n;
|
||||||
return cb(data, (const unsigned char*)l->key, l->key_len, l->value);
|
return cb(data, (const unsigned char*)l->key, l->key_len, l->value);
|
||||||
}
|
}
|
||||||
@@ -932,7 +961,7 @@ int art_iter_cmp(art_tree *t, const unsigned char *key, int key_len, art_callbac
|
|||||||
// If the depth matches the prefix, we need to handle this node
|
// If the depth matches the prefix, we need to handle this node
|
||||||
if (depth == key_len) {
|
if (depth == key_len) {
|
||||||
art_leaf *l = minimum(n);
|
art_leaf *l = minimum(n);
|
||||||
if (!key_cmp(l, key, key_len))
|
if (!leaf_prefix_matches(l, key, key_len))
|
||||||
return recursive_iter(n, cb, data);
|
return recursive_iter(n, cb, data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -967,30 +996,54 @@ int art_iter_cmp(art_tree *t, const unsigned char *key, int key_len, art_callbac
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static int str_prefix_matches(const art_leaf *n, const unsigned char *str, int str_len) {
|
||||||
* Checks if a leaf prefix matches
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
static int leaf_prefix_matches(const art_leaf *n, const unsigned char *prefix, int prefix_len) {
|
|
||||||
// Fail if the key length is too short
|
// Fail if the key length is too short
|
||||||
if (n->key_len < (uint32_t)prefix_len) return 1;
|
if (n->key_len > (uint32_t)str_len) return 1;
|
||||||
|
|
||||||
// Compare the keys
|
// Compare the keys
|
||||||
return memcmp(n->key, prefix, prefix_len);
|
return memcmp(str, n->key, n->key_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void *art_substring(const art_tree *t, const unsigned char *str, int str_len)
|
||||||
* Iterates through the entries pairs in the map,
|
{
|
||||||
* invoking a callback for each that matches a given prefix.
|
art_node **child;
|
||||||
* The call back gets a key, value for each and returns an integer stop value.
|
art_node *n = t->root;
|
||||||
* If the callback returns non-zero, then the iteration stops.
|
art_leaf *found = NULL;
|
||||||
* @arg t The tree to iterate over
|
|
||||||
* @arg prefix The prefix of keys to read
|
int prefix_len, depth = 0;
|
||||||
* @arg prefix_len The length of the prefix
|
while (n) {
|
||||||
* @arg cb The callback function to invoke
|
// Might be a leaf
|
||||||
* @arg data Opaque handle passed to the callback
|
if (IS_LEAF(n)) {
|
||||||
* @return 0 on success, or the return of the callback.
|
n = (art_node*)LEAF_RAW(n);
|
||||||
*/
|
// Check if the expanded path matches
|
||||||
int art_iter_prefix(art_tree *t, const unsigned char *key, int key_len, art_callback cb, void *data) {
|
if (!str_prefix_matches((art_leaf*)n, str, str_len)) {
|
||||||
return art_iter_cmp(t, key, key_len, cb, leaf_prefix_matches, data);
|
found = (art_leaf*)n;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bail if the prefix does not match
|
||||||
|
if (n->partial_len) {
|
||||||
|
prefix_len = check_prefix(n, str, str_len, depth);
|
||||||
|
if (prefix_len != min(MAX_PREFIX_LEN, n->partial_len))
|
||||||
|
break;
|
||||||
|
depth = depth + n->partial_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
art_leaf *l = maximum(n);
|
||||||
|
if (!str_prefix_matches(l, str, str_len)) {
|
||||||
|
found = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively search
|
||||||
|
child = find_child(n, str[depth]);
|
||||||
|
n = (child) ? *child : NULL;
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found->value;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user