Upgrade unbound library

These files were pulled from the 1.6.3 release tarball.

This new version builds against OpenSSL version 1.1 which will be
the default in the new Debian Stable which is due to be released
RealSoonNow (tm).
This commit is contained in:
Erik de Castro Lopo 2017-06-16 20:16:05 +10:00
parent e3da0ca828
commit a85b5759f3
241 changed files with 33336 additions and 12049 deletions

View file

@ -52,7 +52,7 @@
/** setup new special type */
static void
alloc_setup_special(alloc_special_t* t)
alloc_setup_special(alloc_special_type* t)
{
memset(t, 0, sizeof(*t));
lock_rw_init(&t->entry.lock);
@ -64,12 +64,13 @@ alloc_setup_special(alloc_special_t* t)
* @param alloc: the structure to fill up.
*/
static void
prealloc(struct alloc_cache* alloc)
prealloc_setup(struct alloc_cache* alloc)
{
alloc_special_t* p;
alloc_special_type* p;
int i;
for(i=0; i<ALLOC_SPECIAL_MAX; i++) {
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t)))) {
if(!(p = (alloc_special_type*)malloc(
sizeof(alloc_special_type)))) {
log_err("prealloc: out of memory");
return;
}
@ -128,7 +129,7 @@ alloc_init(struct alloc_cache* alloc, struct alloc_cache* super,
void
alloc_clear(struct alloc_cache* alloc)
{
alloc_special_t* p, *np;
alloc_special_type* p, *np;
struct regional* r, *nr;
if(!alloc)
return;
@ -187,10 +188,10 @@ alloc_get_id(struct alloc_cache* alloc)
return id;
}
alloc_special_t*
alloc_special_type*
alloc_special_obtain(struct alloc_cache* alloc)
{
alloc_special_t* p;
alloc_special_type* p;
log_assert(alloc);
/* see if in local cache */
if(alloc->quar) {
@ -216,8 +217,8 @@ alloc_special_obtain(struct alloc_cache* alloc)
}
}
/* allocate new */
prealloc(alloc);
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t)))) {
prealloc_setup(alloc);
if(!(p = (alloc_special_type*)malloc(sizeof(alloc_special_type)))) {
log_err("alloc_special_obtain: out of memory");
return NULL;
}
@ -228,10 +229,10 @@ alloc_special_obtain(struct alloc_cache* alloc)
/** push mem and some more items to the super */
static void
pushintosuper(struct alloc_cache* alloc, alloc_special_t* mem)
pushintosuper(struct alloc_cache* alloc, alloc_special_type* mem)
{
int i;
alloc_special_t *p = alloc->quar;
alloc_special_type *p = alloc->quar;
log_assert(p);
log_assert(alloc && alloc->super &&
alloc->num_quar >= ALLOC_SPECIAL_MAX);
@ -253,7 +254,7 @@ pushintosuper(struct alloc_cache* alloc, alloc_special_t* mem)
}
void
alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem)
alloc_special_release(struct alloc_cache* alloc, alloc_special_type* mem)
{
log_assert(alloc);
if(!mem)
@ -286,12 +287,12 @@ alloc_stats(struct alloc_cache* alloc)
size_t alloc_get_mem(struct alloc_cache* alloc)
{
alloc_special_t* p;
alloc_special_type* p;
size_t s = sizeof(*alloc);
if(!alloc->super) {
lock_quick_lock(&alloc->lock); /* superalloc needs locking */
}
s += sizeof(alloc_special_t) * alloc->num_quar;
s += sizeof(alloc_special_type) * alloc->num_quar;
for(p = alloc->quar; p; p = alloc_special_next(p)) {
s += lock_get_mem(&p->entry.lock);
}

View file

@ -53,11 +53,11 @@ struct ub_packed_rrset_key;
struct regional;
/** The special type, packed rrset. Not allowed to be used for other memory */
typedef struct ub_packed_rrset_key alloc_special_t;
typedef struct ub_packed_rrset_key alloc_special_type;
/** clean the special type. Pass pointer. */
#define alloc_special_clean(x) (x)->id = 0;
/** access next pointer. (in available spot). Pass pointer. */
#define alloc_special_next(x) ((alloc_special_t*)((x)->entry.overflow_next))
#define alloc_special_next(x) ((alloc_special_type*)((x)->entry.overflow_next))
/** set next pointer. (in available spot). Pass pointers. */
#define alloc_set_special_next(x, y) \
((x)->entry.overflow_next) = (struct lruhash_entry*)(y);
@ -71,11 +71,11 @@ typedef struct ub_packed_rrset_key alloc_special_t;
*/
struct alloc_cache {
/** lock, only used for the super. */
lock_quick_t lock;
lock_quick_type lock;
/** global allocator above this one. NULL for none (malloc/free) */
struct alloc_cache* super;
/** singly linked lists of special type. These are free for use. */
alloc_special_t* quar;
alloc_special_type* quar;
/** number of items in quarantine. */
size_t num_quar;
/** thread number for id creation */
@ -116,20 +116,20 @@ void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super,
void alloc_clear(struct alloc_cache* alloc);
/**
* Get a new special_t element.
* Get a new special_type element.
* @param alloc: where to alloc it.
* @return: memory block. Will not return NULL (instead fatal_exit).
* The block is zeroed.
*/
alloc_special_t* alloc_special_obtain(struct alloc_cache* alloc);
alloc_special_type* alloc_special_obtain(struct alloc_cache* alloc);
/**
* Return special_t back to pool.
* Return special_type back to pool.
* The block is cleaned up (zeroed) which also invalidates the ID inside.
* @param alloc: where to alloc it.
* @param mem: block to free.
*/
void alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem);
void alloc_special_release(struct alloc_cache* alloc, alloc_special_type* mem);
/**
* Set ID number of special type to a fresh new ID number.

143
external/unbound/util/as112.c vendored Normal file
View file

@ -0,0 +1,143 @@
/*
* util/as112.c - list of local zones.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file provides a list of lan zones.
*/
#include "util/as112.h"
static const char* as112_zone_array[] = {
"10.in-addr.arpa.",
"16.172.in-addr.arpa.",
"17.172.in-addr.arpa.",
"18.172.in-addr.arpa.",
"19.172.in-addr.arpa.",
"20.172.in-addr.arpa.",
"21.172.in-addr.arpa.",
"22.172.in-addr.arpa.",
"23.172.in-addr.arpa.",
"24.172.in-addr.arpa.",
"25.172.in-addr.arpa.",
"26.172.in-addr.arpa.",
"27.172.in-addr.arpa.",
"28.172.in-addr.arpa.",
"29.172.in-addr.arpa.",
"30.172.in-addr.arpa.",
"31.172.in-addr.arpa.",
"168.192.in-addr.arpa.",
"0.in-addr.arpa.",
"64.100.in-addr.arpa.",
"65.100.in-addr.arpa.",
"66.100.in-addr.arpa.",
"67.100.in-addr.arpa.",
"68.100.in-addr.arpa.",
"69.100.in-addr.arpa.",
"70.100.in-addr.arpa.",
"71.100.in-addr.arpa.",
"72.100.in-addr.arpa.",
"73.100.in-addr.arpa.",
"74.100.in-addr.arpa.",
"75.100.in-addr.arpa.",
"76.100.in-addr.arpa.",
"77.100.in-addr.arpa.",
"78.100.in-addr.arpa.",
"79.100.in-addr.arpa.",
"80.100.in-addr.arpa.",
"81.100.in-addr.arpa.",
"82.100.in-addr.arpa.",
"83.100.in-addr.arpa.",
"84.100.in-addr.arpa.",
"85.100.in-addr.arpa.",
"86.100.in-addr.arpa.",
"87.100.in-addr.arpa.",
"88.100.in-addr.arpa.",
"89.100.in-addr.arpa.",
"90.100.in-addr.arpa.",
"91.100.in-addr.arpa.",
"92.100.in-addr.arpa.",
"93.100.in-addr.arpa.",
"94.100.in-addr.arpa.",
"95.100.in-addr.arpa.",
"96.100.in-addr.arpa.",
"97.100.in-addr.arpa.",
"98.100.in-addr.arpa.",
"99.100.in-addr.arpa.",
"100.100.in-addr.arpa.",
"101.100.in-addr.arpa.",
"102.100.in-addr.arpa.",
"103.100.in-addr.arpa.",
"104.100.in-addr.arpa.",
"105.100.in-addr.arpa.",
"106.100.in-addr.arpa.",
"107.100.in-addr.arpa.",
"108.100.in-addr.arpa.",
"109.100.in-addr.arpa.",
"110.100.in-addr.arpa.",
"111.100.in-addr.arpa.",
"112.100.in-addr.arpa.",
"113.100.in-addr.arpa.",
"114.100.in-addr.arpa.",
"115.100.in-addr.arpa.",
"116.100.in-addr.arpa.",
"117.100.in-addr.arpa.",
"118.100.in-addr.arpa.",
"119.100.in-addr.arpa.",
"120.100.in-addr.arpa.",
"121.100.in-addr.arpa.",
"122.100.in-addr.arpa.",
"123.100.in-addr.arpa.",
"124.100.in-addr.arpa.",
"125.100.in-addr.arpa.",
"126.100.in-addr.arpa.",
"127.100.in-addr.arpa.",
"254.169.in-addr.arpa.",
"2.0.192.in-addr.arpa.",
"100.51.198.in-addr.arpa.",
"113.0.203.in-addr.arpa.",
"255.255.255.255.in-addr.arpa.",
"0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.",
"d.f.ip6.arpa.",
"8.e.f.ip6.arpa.",
"9.e.f.ip6.arpa.",
"a.e.f.ip6.arpa.",
"b.e.f.ip6.arpa.",
"8.b.d.0.1.0.0.2.ip6.arpa.",
0
};
const char** as112_zones = as112_zone_array;

57
external/unbound/util/as112.h vendored Normal file
View file

@ -0,0 +1,57 @@
/*
* util/as112.c - list of local zones.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file provides a list of lan zones
*/
#ifndef UTIL_AS112_H
#define UTIL_AS112_H
/**
* Array of text-format domain names of the AS112 zones.
* The array ends with NULL. "AS112" is a service on the internet that
* that this array is named after. The names in this list (or some of them)
* are null-routed by this service to avoid load on central servers caused by
* mistaken lookups for local content on the global internet.
*
* This is the list of names that unbound should not normally be sending
* on towards the internet, because they are local-use.
*/
extern const char** as112_zones;
#endif

View file

@ -62,6 +62,9 @@
#ifdef HAVE_GLOB_H
# include <glob.h>
#endif
#ifdef CLIENT_SUBNET
#include "edns-subnet/edns-subnet.h"
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@ -98,13 +101,17 @@ config_create(void)
cfg->do_udp = 1;
cfg->do_tcp = 1;
cfg->tcp_upstream = 0;
cfg->tcp_mss = 0;
cfg->outgoing_tcp_mss = 0;
cfg->ssl_service_key = NULL;
cfg->ssl_service_pem = NULL;
cfg->ssl_port = 853;
cfg->ssl_upstream = 0;
cfg->use_syslog = 1;
cfg->log_identity = NULL; /* changed later with argv[0] */
cfg->log_time_ascii = 0;
cfg->log_queries = 0;
cfg->log_replies = 0;
#ifndef USE_WINSOCK
# ifdef USE_MINI_EVENT
/* select max 1024 sockets */
@ -155,18 +162,28 @@ config_create(void)
cfg->donotqueryaddrs = NULL;
cfg->donotquery_localhost = 1;
cfg->root_hints = NULL;
cfg->use_systemd = 0;
cfg->do_daemonize = 1;
cfg->if_automatic = 0;
cfg->so_rcvbuf = 0;
cfg->so_sndbuf = 0;
cfg->so_reuseport = 0;
cfg->ip_transparent = 0;
cfg->ip_freebind = 0;
cfg->num_ifs = 0;
cfg->ifs = NULL;
cfg->num_out_ifs = 0;
cfg->out_ifs = NULL;
cfg->stubs = NULL;
cfg->forwards = NULL;
#ifdef CLIENT_SUBNET
cfg->client_subnet = NULL;
cfg->client_subnet_opcode = LDNS_EDNS_CLIENT_SUBNET;
cfg->client_subnet_always_forward = 0;
cfg->max_client_subnet_ipv4 = 24;
cfg->max_client_subnet_ipv6 = 56;
#endif
cfg->views = NULL;
cfg->acls = NULL;
cfg->harden_short_bufsize = 0;
cfg->harden_large_queries = 0;
@ -182,6 +199,7 @@ config_create(void)
cfg->unwanted_threshold = 0;
cfg->hide_identity = 0;
cfg->hide_version = 0;
cfg->hide_trustanchor = 0;
cfg->identity = NULL;
cfg->version = NULL;
cfg->auto_trust_anchor_file_list = NULL;
@ -199,6 +217,7 @@ config_create(void)
cfg->val_log_squelch = 0;
cfg->val_permissive_mode = 0;
cfg->ignore_cd = 0;
cfg->serve_expired = 0;
cfg->add_holddown = 30*24*3600;
cfg->del_holddown = 30*24*3600;
cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */
@ -209,7 +228,9 @@ config_create(void)
cfg->local_zones = NULL;
cfg->local_zones_nodefault = NULL;
cfg->local_data = NULL;
cfg->local_zone_overrides = NULL;
cfg->unblock_lan_zones = 0;
cfg->insecure_lan_zones = 0;
cfg->python_script = NULL;
cfg->remote_control_enable = 0;
cfg->control_ifs = NULL;
@ -227,20 +248,37 @@ config_create(void)
if(!(cfg->control_cert_file = strdup(RUN_DIR"/unbound_control.pem")))
goto error_exit;
#ifdef CLIENT_SUBNET
if(!(cfg->module_conf = strdup("subnetcache validator iterator"))) goto error_exit;
#else
if(!(cfg->module_conf = strdup("validator iterator"))) goto error_exit;
#endif
if(!(cfg->val_nsec3_key_iterations =
strdup("1024 150 2048 500 4096 2500"))) goto error_exit;
#if defined(DNSTAP_SOCKET_PATH)
if(!(cfg->dnstap_socket_path = strdup(DNSTAP_SOCKET_PATH)))
goto error_exit;
#endif
cfg->disable_dnssec_lame_check = 0;
cfg->ip_ratelimit = 0;
cfg->ratelimit = 0;
cfg->ip_ratelimit_slabs = 4;
cfg->ratelimit_slabs = 4;
cfg->ip_ratelimit_size = 4*1024*1024;
cfg->ratelimit_size = 4*1024*1024;
cfg->ratelimit_for_domain = NULL;
cfg->ratelimit_below_domain = NULL;
cfg->ip_ratelimit_factor = 10;
cfg->ratelimit_factor = 10;
cfg->qname_minimisation = 0;
cfg->qname_minimisation_strict = 0;
cfg->shm_enable = 0;
cfg->shm_key = 11777;
cfg->dnscrypt = 0;
cfg->dnscrypt_port = 0;
cfg->dnscrypt_provider = NULL;
cfg->dnscrypt_provider_cert = NULL;
cfg->dnscrypt_secret_key = NULL;
return cfg;
error_exit:
config_delete(cfg);
@ -361,18 +399,24 @@ int config_set_option(struct config_file* cfg, const char* opt,
log_set_time_asc(cfg->log_time_ascii); }
else S_SIZET_NONZERO("max-udp-size:", max_udp_size)
else S_YNO("use-syslog:", use_syslog)
else S_STR("log-identity:", log_identity)
else S_YNO("extended-statistics:", stat_extended)
else S_YNO("statistics-cumulative:", stat_cumulative)
else S_YNO("shm-enable:", shm_enable)
else S_NUMBER_OR_ZERO("shm-key:", shm_key)
else S_YNO("do-ip4:", do_ip4)
else S_YNO("do-ip6:", do_ip6)
else S_YNO("do-udp:", do_udp)
else S_YNO("do-tcp:", do_tcp)
else S_YNO("tcp-upstream:", tcp_upstream)
else S_NUMBER_NONZERO("tcp-mss:", tcp_mss)
else S_NUMBER_NONZERO("outgoing-tcp-mss:", outgoing_tcp_mss)
else S_YNO("ssl-upstream:", ssl_upstream)
else S_STR("ssl-service-key:", ssl_service_key)
else S_STR("ssl-service-pem:", ssl_service_pem)
else S_NUMBER_NONZERO("ssl-port:", ssl_port)
else S_YNO("interface-automatic:", if_automatic)
else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize)
else S_NUMBER_NONZERO("port:", port)
else S_NUMBER_NONZERO("outgoing-range:", outgoing_num_ports)
@ -388,6 +432,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_MEMSIZE("so-sndbuf:", so_sndbuf)
else S_YNO("so-reuseport:", so_reuseport)
else S_YNO("ip-transparent:", ip_transparent)
else S_YNO("ip-freebind:", ip_freebind)
else S_MEMSIZE("rrset-cache-size:", rrset_cache_size)
else S_POW2("rrset-cache-slabs:", rrset_cache_slabs)
else S_YNO("prefetch:", prefetch)
@ -412,6 +457,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("pidfile:", pidfile)
else S_YNO("hide-identity:", hide_identity)
else S_YNO("hide-version:", hide_version)
else S_YNO("hide-trustanchor:", hide_trustanchor)
else S_STR("identity:", identity)
else S_STR("version:", version)
else S_STRLIST("root-hints:", root_hints)
@ -442,8 +488,10 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_NUMBER_OR_ZERO("val-log-level:", val_log_level)
else S_YNO("val-log-squelch:", val_log_squelch)
else S_YNO("log-queries:", log_queries)
else S_YNO("log-replies:", log_replies)
else S_YNO("val-permissive-mode:", val_permissive_mode)
else S_YNO("ignore-cd-flag:", ignore_cd)
else S_YNO("serve-expired:", serve_expired)
else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations)
else S_UNSIGNED_OR_ZERO("add-holddown:", add_holddown)
else S_UNSIGNED_OR_ZERO("del-holddown:", del_holddown)
@ -458,6 +506,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("rrset-roundrobin:", rrset_roundrobin)
else S_STRLIST("local-data:", local_data)
else S_YNO("unblock-lan-zones:", unblock_lan_zones)
else S_YNO("insecure-lan-zones:", insecure_lan_zones)
else S_YNO("control-enable:", remote_control_enable)
else S_STRLIST("control-interface:", control_ifs)
else S_NUMBER_NONZERO("control-port:", control_port)
@ -467,17 +516,34 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("control-cert-file:", control_cert_file)
else S_STR("module-config:", module_conf)
else S_STR("python-script:", python_script)
else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
#ifdef CLIENT_SUBNET
/* Can't set max subnet prefix here, since that value is used when
* generating the address tree. */
/* No client-subnet-always-forward here, module registration depends on
* this option. */
#endif
else if(strcmp(opt, "ip-ratelimit:") == 0) {
IS_NUMBER_OR_ZERO; cfg->ip_ratelimit = atoi(val);
infra_ip_ratelimit=cfg->ip_ratelimit;
}
else if(strcmp(opt, "ratelimit:") == 0) {
IS_NUMBER_OR_ZERO; cfg->ratelimit = atoi(val);
infra_dp_ratelimit=cfg->ratelimit;
}
else S_MEMSIZE("ip-ratelimit-size:", ip_ratelimit_size)
else S_MEMSIZE("ratelimit-size:", ratelimit_size)
else S_POW2("ip-ratelimit-slabs:", ip_ratelimit_slabs)
else S_POW2("ratelimit-slabs:", ratelimit_slabs)
else S_NUMBER_OR_ZERO("ip-ratelimit-factor:", ip_ratelimit_factor)
else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor)
else S_YNO("qname-minimisation:", qname_minimisation)
else S_YNO("qname-minimisation-strict:", qname_minimisation_strict)
else if(strcmp(opt, "define-tag:") ==0) {
return config_add_tag(cfg, val);
/* val_sig_skew_min and max are copied into val_env during init,
* so this does not update val_env with set_option */
else if(strcmp(opt, "val-sig-skew-min:") == 0)
} else if(strcmp(opt, "val-sig-skew-min:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->val_sig_skew_min = (int32_t)atoi(val); }
else if(strcmp(opt, "val-sig-skew-max:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->val_sig_skew_max = (int32_t)atoi(val); }
@ -496,9 +562,13 @@ int config_set_option(struct config_file* cfg, const char* opt,
/* unknown or unsupported (from the set_option interface):
* interface, outgoing-interface, access-control,
* stub-zone, name, stub-addr, stub-host, stub-prime
* forward-first, stub-first,
* forward-zone, name, forward-addr, forward-host,
* ratelimit-for-domain, ratelimit-below-domain */
* forward-first, stub-first, forward-ssl-upstream,
* stub-ssl-upstream, forward-zone,
* name, forward-addr, forward-host,
* ratelimit-for-domain, ratelimit-below-domain,
* local-zone-tag, access-control-view
* send-client-subnet client-subnet-always-forward
* max-client-subnet-ipv4 max-client-subnet-ipv6 */
return 0;
}
return 1;
@ -622,9 +692,31 @@ config_collate_cat(struct config_strlist* list)
/** compare and print list option */
#define O_LS2(opt, name, lst) if(strcmp(opt, name)==0) { \
struct config_str2list* p = cfg->lst; \
for(p = cfg->lst; p; p = p->next) \
snprintf(buf, len, "%s %s\n", p->str, p->str2); \
for(p = cfg->lst; p; p = p->next) { \
snprintf(buf, len, "%s %s", p->str, p->str2); \
func(buf, arg); \
} \
}
/** compare and print list option */
#define O_LS3(opt, name, lst) if(strcmp(opt, name)==0) { \
struct config_str3list* p = cfg->lst; \
for(p = cfg->lst; p; p = p->next) { \
snprintf(buf, len, "%s %s %s", p->str, p->str2, p->str3); \
func(buf, arg); \
} \
}
/** compare and print taglist option */
#define O_LTG(opt, name, lst) if(strcmp(opt, name)==0) { \
char* tmpstr = NULL; \
struct config_strbytelist *p = cfg->lst; \
for(p = cfg->lst; p; p = p->next) {\
tmpstr = config_taglist2str(cfg, p->str2, p->str2len); \
if(tmpstr) {\
snprintf(buf, len, "%s %s", p->str, tmpstr); \
func(buf, arg); \
free(tmpstr); \
} \
} \
}
int
@ -638,7 +730,10 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "statistics-interval", stat_interval)
else O_YNO(opt, "statistics-cumulative", stat_cumulative)
else O_YNO(opt, "extended-statistics", stat_extended)
else O_YNO(opt, "shm-enable", shm_enable)
else O_DEC(opt, "shm-key", shm_key)
else O_YNO(opt, "use-syslog", use_syslog)
else O_STR(opt, "log-identity", log_identity)
else O_YNO(opt, "log-time-ascii", log_time_ascii)
else O_DEC(opt, "num-threads", num_threads)
else O_IFC(opt, "interface", num_ifs, ifs)
@ -658,6 +753,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_MEM(opt, "so-sndbuf", so_sndbuf)
else O_YNO(opt, "so-reuseport", so_reuseport)
else O_YNO(opt, "ip-transparent", ip_transparent)
else O_YNO(opt, "ip-freebind", ip_freebind)
else O_MEM(opt, "rrset-cache-size", rrset_cache_size)
else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs)
else O_YNO(opt, "prefetch-key", prefetch_key)
@ -675,19 +771,24 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "do-udp", do_udp)
else O_YNO(opt, "do-tcp", do_tcp)
else O_YNO(opt, "tcp-upstream", tcp_upstream)
else O_DEC(opt, "tcp-mss", tcp_mss)
else O_DEC(opt, "outgoing-tcp-mss", outgoing_tcp_mss)
else O_YNO(opt, "ssl-upstream", ssl_upstream)
else O_STR(opt, "ssl-service-key", ssl_service_key)
else O_STR(opt, "ssl-service-pem", ssl_service_pem)
else O_DEC(opt, "ssl-port", ssl_port)
else O_YNO(opt, "use-systemd", use_systemd)
else O_YNO(opt, "do-daemonize", do_daemonize)
else O_STR(opt, "chroot", chrootdir)
else O_STR(opt, "username", username)
else O_STR(opt, "directory", directory)
else O_STR(opt, "logfile", logfile)
else O_YNO(opt, "log-queries", log_queries)
else O_YNO(opt, "log-replies", log_replies)
else O_STR(opt, "pidfile", pidfile)
else O_YNO(opt, "hide-identity", hide_identity)
else O_YNO(opt, "hide-version", hide_version)
else O_YNO(opt, "hide-trustanchor", hide_trustanchor)
else O_STR(opt, "identity", identity)
else O_STR(opt, "version", version)
else O_STR(opt, "target-fetch-policy", target_fetch_policy)
@ -709,6 +810,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "val-log-level", val_log_level)
else O_YNO(opt, "val-permissive-mode", val_permissive_mode)
else O_YNO(opt, "ignore-cd-flag", ignore_cd)
else O_YNO(opt, "serve-expired", serve_expired)
else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
else O_UNS(opt, "add-holddown", add_holddown)
else O_UNS(opt, "del-holddown", del_holddown)
@ -738,18 +840,40 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_UNS(opt, "val-override-date", val_date_override)
else O_YNO(opt, "minimal-responses", minimal_responses)
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
#ifdef CLIENT_SUBNET
else O_LST(opt, "send-client-subnet", client_subnet)
else O_DEC(opt, "max-client-subnet-ipv4", max_client_subnet_ipv4)
else O_DEC(opt, "max-client-subnet-ipv6", max_client_subnet_ipv6)
else O_YNO(opt, "client-subnet-always-forward:",
client_subnet_always_forward)
#endif
else O_YNO(opt, "unblock-lan-zones", unblock_lan_zones)
else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
else O_DEC(opt, "max-udp-size", max_udp_size)
else O_STR(opt, "python-script", python_script)
else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
else O_DEC(opt, "ip-ratelimit", ip_ratelimit)
else O_DEC(opt, "ratelimit", ratelimit)
else O_MEM(opt, "ip-ratelimit-size", ip_ratelimit_size)
else O_MEM(opt, "ratelimit-size", ratelimit_size)
else O_DEC(opt, "ip-ratelimit-slabs", ip_ratelimit_slabs)
else O_DEC(opt, "ratelimit-slabs", ratelimit_slabs)
else O_LS2(opt, "ratelimit-for-domain", ratelimit_for_domain)
else O_LS2(opt, "ratelimit-below-domain", ratelimit_below_domain)
else O_DEC(opt, "ip-ratelimit-factor", ip_ratelimit_factor)
else O_DEC(opt, "ratelimit-factor", ratelimit_factor)
else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max)
else O_YNO(opt, "qname-minimisation", qname_minimisation)
else O_YNO(opt, "qname-minimisation-strict", qname_minimisation_strict)
else O_IFC(opt, "define-tag", num_tags, tagname)
else O_LTG(opt, "local-zone-tag", local_zone_tags)
else O_LTG(opt, "access-control-tag", acl_tags)
else O_LTG(opt, "response-ip-tag", respip_tags)
else O_LS3(opt, "local-zone-override", local_zone_overrides)
else O_LS3(opt, "access-control-tag-action", acl_tag_actions)
else O_LS3(opt, "access-control-tag-data", acl_tag_datas)
else O_LS2(opt, "access-control-view", acl_view)
/* not here:
* outgoing-permit, outgoing-avoid - have list of ports
* local-zone - zones and nodefault variables
@ -854,6 +978,8 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot)
ub_c_parse();
fclose(in);
if(!cfg->dnscrypt) cfg->dnscrypt_port = 0;
if(cfg_parser->errors != 0) {
fprintf(stderr, "read %s failed: %d errors in configuration file\n",
fname, cfg_parser->errors);
@ -864,6 +990,18 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot)
return 1;
}
struct config_stub* cfg_stub_find(struct config_stub*** pp, const char* nm)
{
struct config_stub* p = *(*pp);
while(p) {
if(strcmp(p->name, nm) == 0)
return p;
(*pp) = &p->next;
p = p->next;
}
return NULL;
}
void
config_delstrlist(struct config_strlist* p)
{
@ -889,15 +1027,83 @@ config_deldblstrlist(struct config_str2list* p)
}
}
void
config_deltrplstrlist(struct config_str3list* p)
{
struct config_str3list *np;
while(p) {
np = p->next;
free(p->str);
free(p->str2);
free(p->str3);
free(p);
p = np;
}
}
void
config_delstub(struct config_stub* p)
{
if(!p) return;
free(p->name);
config_delstrlist(p->hosts);
config_delstrlist(p->addrs);
free(p);
}
void
config_delstubs(struct config_stub* p)
{
struct config_stub* np;
while(p) {
np = p->next;
free(p->name);
config_delstrlist(p->hosts);
config_delstrlist(p->addrs);
config_delstub(p);
p = np;
}
}
void
config_delview(struct config_view* p)
{
if(!p) return;
free(p->name);
config_deldblstrlist(p->local_zones);
config_delstrlist(p->local_zones_nodefault);
config_delstrlist(p->local_data);
free(p);
}
void
config_delviews(struct config_view* p)
{
struct config_view* np;
while(p) {
np = p->next;
config_delview(p);
p = np;
}
}
/** delete string array */
static void
config_del_strarray(char** array, int num)
{
int i;
if(!array)
return;
for(i=0; i<num; i++) {
free(array[i]);
}
free(array);
}
void
config_del_strbytelist(struct config_strbytelist* p)
{
struct config_strbytelist* np;
while(p) {
np = p->next;
free(p->str);
free(p->str2);
free(p);
p = np;
}
@ -915,22 +1121,17 @@ config_delete(struct config_file* cfg)
free(cfg->target_fetch_policy);
free(cfg->ssl_service_key);
free(cfg->ssl_service_pem);
if(cfg->ifs) {
int i;
for(i=0; i<cfg->num_ifs; i++)
free(cfg->ifs[i]);
free(cfg->ifs);
}
if(cfg->out_ifs) {
int i;
for(i=0; i<cfg->num_out_ifs; i++)
free(cfg->out_ifs[i]);
free(cfg->out_ifs);
}
free(cfg->log_identity);
config_del_strarray(cfg->ifs, cfg->num_ifs);
config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
config_delstubs(cfg->stubs);
config_delstubs(cfg->forwards);
config_delviews(cfg->views);
config_delstrlist(cfg->donotqueryaddrs);
config_delstrlist(cfg->root_hints);
#ifdef CLIENT_SUBNET
config_delstrlist(cfg->client_subnet);
#endif
free(cfg->identity);
free(cfg->version);
free(cfg->module_conf);
@ -950,6 +1151,13 @@ config_delete(struct config_file* cfg)
config_deldblstrlist(cfg->local_zones);
config_delstrlist(cfg->local_zones_nodefault);
config_delstrlist(cfg->local_data);
config_deltrplstrlist(cfg->local_zone_overrides);
config_del_strarray(cfg->tagname, cfg->num_tags);
config_del_strbytelist(cfg->local_zone_tags);
config_del_strbytelist(cfg->acl_tags);
config_del_strbytelist(cfg->respip_tags);
config_deltrplstrlist(cfg->acl_tag_actions);
config_deltrplstrlist(cfg->acl_tag_datas);
config_delstrlist(cfg->control_ifs);
free(cfg->server_key_file);
free(cfg->server_cert_file);
@ -1107,6 +1315,23 @@ int cfg_strlist_append(struct config_strlist_head* list, char* item)
return 1;
}
int
cfg_region_strlist_insert(struct regional* region,
struct config_strlist** head, char* item)
{
struct config_strlist *s;
if(!item || !head)
return 0;
s = (struct config_strlist*)regional_alloc_zero(region,
sizeof(struct config_strlist));
if(!s)
return 0;
s->str = item;
s->next = *head;
*head = s;
return 1;
}
int
cfg_strlist_insert(struct config_strlist** head, char* item)
{
@ -1138,6 +1363,42 @@ cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
return 1;
}
int
cfg_str3list_insert(struct config_str3list** head, char* item, char* i2,
char* i3)
{
struct config_str3list *s;
if(!item || !i2 || !i3 || !head)
return 0;
s = (struct config_str3list*)calloc(1, sizeof(struct config_str3list));
if(!s)
return 0;
s->str = item;
s->str2 = i2;
s->str3 = i3;
s->next = *head;
*head = s;
return 1;
}
int
cfg_strbytelist_insert(struct config_strbytelist** head, char* item,
uint8_t* i2, size_t i2len)
{
struct config_strbytelist* s;
if(!item || !i2 || !head)
return 0;
s = (struct config_strbytelist*)calloc(1, sizeof(*s));
if(!s)
return 0;
s->str = item;
s->str2 = i2;
s->str2len = i2len;
s->next = *head;
*head = s;
return 1;
}
time_t
cfg_convert_timeval(const char* str)
{
@ -1242,6 +1503,123 @@ cfg_parse_memsize(const char* str, size_t* res)
return 1;
}
int
find_tag_id(struct config_file* cfg, const char* tag)
{
int i;
for(i=0; i<cfg->num_tags; i++) {
if(strcmp(cfg->tagname[i], tag) == 0)
return i;
}
return -1;
}
int
config_add_tag(struct config_file* cfg, const char* tag)
{
char** newarray;
char* newtag;
if(find_tag_id(cfg, tag) != -1)
return 1; /* nothing to do */
newarray = (char**)malloc(sizeof(char*)*(cfg->num_tags+1));
if(!newarray)
return 0;
newtag = strdup(tag);
if(!newtag) {
free(newarray);
return 0;
}
if(cfg->tagname) {
memcpy(newarray, cfg->tagname, sizeof(char*)*cfg->num_tags);
free(cfg->tagname);
}
newarray[cfg->num_tags++] = newtag;
cfg->tagname = newarray;
return 1;
}
/** set a bit in a bit array */
static void
cfg_set_bit(uint8_t* bitlist, size_t len, int id)
{
int pos = id/8;
log_assert((size_t)pos < len);
(void)len;
bitlist[pos] |= 1<<(id%8);
}
uint8_t* config_parse_taglist(struct config_file* cfg, char* str,
size_t* listlen)
{
uint8_t* taglist = NULL;
size_t len = 0;
char* p, *s;
/* allocate */
if(cfg->num_tags == 0) {
log_err("parse taglist, but no tags defined");
return 0;
}
len = (size_t)(cfg->num_tags+7)/8;
taglist = calloc(1, len);
if(!taglist) {
log_err("out of memory");
return 0;
}
/* parse */
s = str;
while((p=strsep(&s, " \t\n")) != NULL) {
if(*p) {
int id = find_tag_id(cfg, p);
/* set this bit in the bitlist */
if(id == -1) {
log_err("unknown tag: %s", p);
free(taglist);
return 0;
}
cfg_set_bit(taglist, len, id);
}
}
*listlen = len;
return taglist;
}
char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
size_t taglen)
{
char buf[10240];
size_t i, j, len = 0;
buf[0] = 0;
for(i=0; i<taglen; i++) {
if(taglist[i] == 0)
continue;
for(j=0; j<8; j++) {
if((taglist[i] & (1<<j)) != 0) {
size_t id = i*8 + j;
snprintf(buf+len, sizeof(buf)-len, "%s%s",
(len==0?"":" "), cfg->tagname[id]);
len += strlen(buf+len);
}
}
}
return strdup(buf);
}
int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
size_t list2len)
{
size_t i;
if(!list1 || !list2)
return 0;
for(i=0; i<list1len && i<list2len; i++) {
if((list1[i] & list2[i]) != 0)
return 1;
}
return 0;
}
void
config_apply(struct config_file* config)
{

View file

@ -42,11 +42,15 @@
#ifndef UTIL_CONFIG_FILE_H
#define UTIL_CONFIG_FILE_H
struct config_stub;
struct config_view;
struct config_strlist;
struct config_str2list;
struct config_str3list;
struct config_strbytelist;
struct module_qstate;
struct sock_list;
struct ub_packed_rrset_key;
struct regional;
/**
* The configuration options.
@ -72,12 +76,18 @@ struct config_file {
int do_ip4;
/** do ip6 query support. */
int do_ip6;
/** prefer ip6 upstream queries. */
int prefer_ip6;
/** do udp query support. */
int do_udp;
/** do tcp query support. */
int do_tcp;
/** tcp upstream queries (no UDP upstream queries) */
int tcp_upstream;
/** maximum segment size of tcp socket which queries are answered */
int tcp_mss;
/** maximum segment size of tcp socket for outgoing queries */
int outgoing_tcp_mss;
/** private key file for dnstcp-ssl service (enabled if not NULL) */
char* ssl_service_key;
@ -138,6 +148,8 @@ struct config_file {
int so_reuseport;
/** IP_TRANSPARENT socket option requested on port 53 sockets */
int ip_transparent;
/** IP_FREEBIND socket option request on port 53 sockets */
int ip_freebind;
/** number of interfaces to open. If 0 default all interfaces. */
int num_ifs;
@ -156,8 +168,22 @@ struct config_file {
struct config_stub* stubs;
/** the forward zone definitions, linked list */
struct config_stub* forwards;
/** the views definitions, linked list */
struct config_view* views;
/** list of donotquery addresses, linked list */
struct config_strlist* donotqueryaddrs;
#ifdef CLIENT_SUBNET
/** list of servers we send edns-client-subnet option to and
* accept option from, linked list */
struct config_strlist* client_subnet;
/** opcode assigned by IANA for edns0-client-subnet option */
uint16_t client_subnet_opcode;
/** Do not check whitelist if incoming query contains an ECS record */
int client_subnet_always_forward;
/** Subnet length we are willing to give up privacy for */
uint8_t max_client_subnet_ipv4;
uint8_t max_client_subnet_ipv6;
#endif
/** list of access control entries, linked list */
struct config_str2list* acls;
/** use default localhost donotqueryaddr entries */
@ -215,11 +241,17 @@ struct config_file {
int log_time_ascii;
/** log queries with one line per query */
int log_queries;
/** log replies with one line per reply */
int log_replies;
/** log identity to report */
char* log_identity;
/** do not report identity (id.server, hostname.bind) */
int hide_identity;
/** do not report version (version.server, version.bind) */
int hide_version;
/** do not report trustanchor (trustanchor.unbound) */
int hide_trustanchor;
/** identity, hostname is returned if "". */
char* identity;
/** version, package version returned if "". */
@ -261,6 +293,8 @@ struct config_file {
int val_permissive_mode;
/** ignore the CD flag in incoming queries and refuse them bogus data */
int ignore_cd;
/** serve expired entries and prefetch them */
int serve_expired;
/** nsec3 maximum iterations per key size, string */
char* val_nsec3_key_iterations;
/** autotrust add holddown time, in seconds */
@ -285,8 +319,32 @@ struct config_file {
struct config_strlist* local_zones_nodefault;
/** local data RRs configured */
struct config_strlist* local_data;
/** unblock lan zones (reverse lookups for 10/8 and so on) */
/** local zone override types per netblock */
struct config_str3list* local_zone_overrides;
/** unblock lan zones (reverse lookups for AS112 zones) */
int unblock_lan_zones;
/** insecure lan zones (don't validate AS112 zones) */
int insecure_lan_zones;
/** list of zonename, tagbitlist */
struct config_strbytelist* local_zone_tags;
/** list of aclname, tagbitlist */
struct config_strbytelist* acl_tags;
/** list of aclname, tagname, localzonetype */
struct config_str3list* acl_tag_actions;
/** list of aclname, tagname, redirectdata */
struct config_str3list* acl_tag_datas;
/** list of aclname, view*/
struct config_str2list* acl_view;
/** list of IP-netblock, tagbitlist */
struct config_strbytelist* respip_tags;
/** list of response-driven access control entries, linked list */
struct config_str2list* respip_actions;
/** RRs configured for response-driven access controls */
struct config_str2list* respip_data;
/** tag list, array with tagname[i] is malloced string */
char** tagname;
/** number of items in the taglist */
int num_tags;
/** remote control section. enable toggle. */
int remote_control_enable;
@ -308,6 +366,9 @@ struct config_file {
/** Python script file */
char* python_script;
/** Use systemd socket activation. */
int use_systemd;
/** daemonize, i.e. fork into the background. */
int do_daemonize;
@ -352,7 +413,19 @@ struct config_file {
/** true to log dnstap FORWARDER_RESPONSE message events */
int dnstap_log_forwarder_response_messages;
/** ratelimit 0 is off, otherwise qps (unless overridden) */
/** true to disable DNSSEC lameness check in iterator */
int disable_dnssec_lame_check;
/** ratelimit for ip addresses. 0 is off, otherwise qps (unless overridden) */
int ip_ratelimit;
/** number of slabs for ip_ratelimit cache */
size_t ip_ratelimit_slabs;
/** memory size in bytes for ip_ratelimit cache */
size_t ip_ratelimit_size;
/** ip_ratelimit factor, 0 blocks all, 10 allows 1/10 of traffic */
int ip_ratelimit_factor;
/** ratelimit for domains. 0 is off, otherwise qps (unless overridden) */
int ratelimit;
/** number of slabs for ratelimit cache */
size_t ratelimit_slabs;
@ -366,6 +439,25 @@ struct config_file {
int ratelimit_factor;
/** minimise outgoing QNAME and hide original QTYPE if possible */
int qname_minimisation;
/** minimise QNAME in strict mode, minimise according to RFC.
* Do not apply fallback */
int qname_minimisation_strict;
/** SHM data - true if shm is enabled */
int shm_enable;
/** SHM data - key for the shm */
int shm_key;
/** DNSCrypt */
/** true to enable dnscrypt */
int dnscrypt;
/** port on which to provide dnscrypt service */
int dnscrypt_port;
/** provider name 2.dnscrypt-cert.example.com */
char* dnscrypt_provider;
/** dnscrypt secret keys 1.key */
struct config_strlist* dnscrypt_secret_key;
/** dnscrypt provider certs 1.cert */
struct config_strlist* dnscrypt_provider_cert;
};
/** from cfg username, after daemonise setup performed */
@ -391,6 +483,31 @@ struct config_stub {
int isprime;
/** if forward-first is set (failover to without if fails) */
int isfirst;
/** use SSL for queries to this stub */
int ssl_upstream;
};
/**
* View config options
*/
struct config_view {
/** next in list */
struct config_view* next;
/** view name */
char* name;
/** local zones */
struct config_str2list* local_zones;
/** local data RRs */
struct config_strlist* local_data;
/** local zones nodefault list */
struct config_strlist* local_zones_nodefault;
/** Fallback to global local_zones when there is no match in the view
* view specific tree. 1 for yes, 0 for no */
int isfirst;
/** predefined actions for particular IP address responses */
struct config_str2list* respip_actions;
/** data complementing the 'redirect' response IP actions */
struct config_str2list* respip_data;
};
/**
@ -415,6 +532,34 @@ struct config_str2list {
char* str2;
};
/**
* List of three strings for config options
*/
struct config_str3list {
/** next item in list */
struct config_str3list* next;
/** first string */
char* str;
/** second string */
char* str2;
/** third string */
char* str3;
};
/**
* List of string, bytestring for config options
*/
struct config_strbytelist {
/** next item in list */
struct config_strbytelist* next;
/** first string */
char* str;
/** second bytestring */
uint8_t* str2;
size_t str2len;
};
/** List head for strlist processing, used for append operation. */
struct config_strlist_head {
/** first in list of text items */
@ -544,6 +689,10 @@ int cfg_strlist_append(struct config_strlist_head* list, char* item);
*/
int cfg_strlist_insert(struct config_strlist** head, char* item);
/** insert with region for allocation. */
int cfg_region_strlist_insert(struct regional* region,
struct config_strlist** head, char* item);
/**
* Insert string into str2list.
* @param head: pointer to str2list head variable.
@ -553,6 +702,39 @@ int cfg_strlist_insert(struct config_strlist** head, char* item);
*/
int cfg_str2list_insert(struct config_str2list** head, char* item, char* i2);
/**
* Insert string into str3list.
* @param head: pointer to str3list head variable.
* @param item: new item. malloced by caller. If NULL the insertion fails.
* @param i2: 2nd string, malloced by caller. If NULL the insertion fails.
* @param i3: 3rd string, malloced by caller. If NULL the insertion fails.
* @return: true on success.
*/
int cfg_str3list_insert(struct config_str3list** head, char* item, char* i2,
char* i3);
/**
* Insert string into strbytelist.
* @param head: pointer to strbytelist head variable.
* @param item: new item. malloced by caller. If NULL the insertion fails.
* @param i2: 2nd string, malloced by caller. If NULL the insertion fails.
* @param i2len: length of the i2 bytestring.
* @return: true on success.
*/
int cfg_strbytelist_insert(struct config_strbytelist** head, char* item,
uint8_t* i2, size_t i2len);
/**
* Find stub in config list, also returns prevptr (for deletion).
* @param pp: call routine with pointer to a pointer to the start of the list,
* if the stub is found, on exit, the value contains a pointer to the
* next pointer that points to the found element (or to the list start
* pointer if it is the first element).
* @param nm: name of stub to find.
* @return: pointer to config_stub if found, or NULL if not found.
*/
struct config_stub* cfg_stub_find(struct config_stub*** pp, const char* nm);
/**
* Delete items in config string list.
* @param list: list.
@ -565,12 +747,39 @@ void config_delstrlist(struct config_strlist* list);
*/
void config_deldblstrlist(struct config_str2list* list);
/**
* Delete items in config triple string list.
* @param list: list.
*/
void config_deltrplstrlist(struct config_str3list* list);
/** delete stringbytelist */
void config_del_strbytelist(struct config_strbytelist* list);
/**
* Delete a stub item
* @param p: stub item
*/
void config_delstub(struct config_stub* p);
/**
* Delete items in config stub list.
* @param list: list.
*/
void config_delstubs(struct config_stub* list);
/**
* Delete a view item
* @param p: view item
*/
void config_delview(struct config_view* p);
/**
* Delete items in config view list.
* @param list: list.
*/
void config_delviews(struct config_view* list);
/**
* Convert 14digit to time value
* @param str: string of 14 digits
@ -601,6 +810,54 @@ int cfg_count_numbers(const char* str);
*/
int cfg_parse_memsize(const char* str, size_t* res);
/**
* Add a tag name to the config. It is added at the end with a new ID value.
* @param cfg: the config structure.
* @param tag: string (which is copied) with the name.
* @return: false on alloc failure.
*/
int config_add_tag(struct config_file* cfg, const char* tag);
/**
* Find tag ID in the tag list.
* @param cfg: the config structure.
* @param tag: string with tag name to search for.
* @return: 0..(num_tags-1) with tag ID, or -1 if tagname is not found.
*/
int find_tag_id(struct config_file* cfg, const char* tag);
/**
* parse taglist from string into bytestring with bitlist.
* @param cfg: the config structure (with tagnames)
* @param str: the string to parse. Parse puts 0 bytes in string.
* @param listlen: returns length of in bytes.
* @return malloced bytes with a bitlist of the tags. or NULL on parse error
* or malloc failure.
*/
uint8_t* config_parse_taglist(struct config_file* cfg, char* str,
size_t* listlen);
/**
* convert tag bitlist to a malloced string with tag names. For debug output.
* @param cfg: the config structure (with tagnames)
* @param taglist: the tag bitlist.
* @param len: length of the tag bitlist.
* @return malloced string or NULL.
*/
char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
size_t len);
/**
* see if two taglists intersect (have tags in common).
* @param list1: first tag bitlist.
* @param list1len: length in bytes of first list.
* @param list2: second tag bitlist.
* @param list2len: length in bytes of second list.
* @return true if there are tags in common, 0 if not.
*/
int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
size_t list2len);
/**
* Parse local-zone directive into two strings and register it in the config.
* @param cfg: to put it in.
@ -746,4 +1003,7 @@ char* w_lookup_reg_str(const char* key, const char* name);
void w_config_adjust_directory(struct config_file* cfg);
#endif /* UB_ON_WINDOWS */
/** debug option for unit tests. */
extern int fake_dsa, fake_sha1;
#endif /* UTIL_CONFIG_FILE_H */

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,12 @@
* See LICENSE for the license.
*
*/
/* because flex keeps having sign-unsigned compare problems that are unfixed*/
#if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2))))
#pragma GCC diagnostic ignored "-Wsign-compare"
#endif
#include <ctype.h>
#include <string.h>
#include <strings.h>
@ -63,7 +69,7 @@ static void config_start_include(const char* filename)
ub_c_error_msg("too many include files");
return;
}
if(strlen(filename) == 0) {
if(*filename == '\0') {
ub_c_error_msg("empty include file name");
return;
}
@ -206,6 +212,7 @@ SQANY [^\'\n\r\\]|\\.
LEXOUT(("comment(%s) ", yytext)); /* ignore */ }
server{COLON} { YDVAR(0, VAR_SERVER) }
qname-minimisation{COLON} { YDVAR(1, VAR_QNAME_MINIMISATION) }
qname-minimisation-strict{COLON} { YDVAR(1, VAR_QNAME_MINIMISATION_STRICT) }
num-threads{COLON} { YDVAR(1, VAR_NUM_THREADS) }
verbosity{COLON} { YDVAR(1, VAR_VERBOSITY) }
port{COLON} { YDVAR(1, VAR_PORT) }
@ -216,13 +223,17 @@ outgoing-num-tcp{COLON} { YDVAR(1, VAR_OUTGOING_NUM_TCP) }
incoming-num-tcp{COLON} { YDVAR(1, VAR_INCOMING_NUM_TCP) }
do-ip4{COLON} { YDVAR(1, VAR_DO_IP4) }
do-ip6{COLON} { YDVAR(1, VAR_DO_IP6) }
prefer-ip6{COLON} { YDVAR(1, VAR_PREFER_IP6) }
do-udp{COLON} { YDVAR(1, VAR_DO_UDP) }
do-tcp{COLON} { YDVAR(1, VAR_DO_TCP) }
tcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) }
tcp-mss{COLON} { YDVAR(1, VAR_TCP_MSS) }
outgoing-tcp-mss{COLON} { YDVAR(1, VAR_OUTGOING_TCP_MSS) }
ssl-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) }
ssl-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) }
ssl-service-pem{COLON} { YDVAR(1, VAR_SSL_SERVICE_PEM) }
ssl-port{COLON} { YDVAR(1, VAR_SSL_PORT) }
use-systemd{COLON} { YDVAR(1, VAR_USE_SYSTEMD) }
do-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) }
interface{COLON} { YDVAR(1, VAR_INTERFACE) }
ip-address{COLON} { YDVAR(1, VAR_INTERFACE) }
@ -232,6 +243,7 @@ so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) }
so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) }
so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) }
ip-transparent{COLON} { YDVAR(1, VAR_IP_TRANSPARENT) }
ip-freebind{COLON} { YDVAR(1, VAR_IP_FREEBIND) }
chroot{COLON} { YDVAR(1, VAR_CHROOT) }
username{COLON} { YDVAR(1, VAR_USERNAME) }
directory{COLON} { YDVAR(1, VAR_DIRECTORY) }
@ -277,15 +289,25 @@ stub-addr{COLON} { YDVAR(1, VAR_STUB_ADDR) }
stub-host{COLON} { YDVAR(1, VAR_STUB_HOST) }
stub-prime{COLON} { YDVAR(1, VAR_STUB_PRIME) }
stub-first{COLON} { YDVAR(1, VAR_STUB_FIRST) }
stub-ssl-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) }
forward-zone{COLON} { YDVAR(0, VAR_FORWARD_ZONE) }
forward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) }
forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) }
forward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) }
forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
view{COLON} { YDVAR(0, VAR_VIEW) }
view-first{COLON} { YDVAR(1, VAR_VIEW_FIRST) }
do-not-query-address{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) }
do-not-query-localhost{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) }
access-control{COLON} { YDVAR(2, VAR_ACCESS_CONTROL) }
send-client-subnet{COLON} { YDVAR(1, VAR_SEND_CLIENT_SUBNET) }
client-subnet-always-forward{COLON} { YDVAR(1, VAR_CLIENT_SUBNET_ALWAYS_FORWARD) }
client-subnet-opcode{COLON} { YDVAR(1, VAR_CLIENT_SUBNET_OPCODE) }
max-client-subnet-ipv4{COLON} { YDVAR(1, VAR_MAX_CLIENT_SUBNET_IPV4) }
max-client-subnet-ipv6{COLON} { YDVAR(1, VAR_MAX_CLIENT_SUBNET_IPV6) }
hide-identity{COLON} { YDVAR(1, VAR_HIDE_IDENTITY) }
hide-version{COLON} { YDVAR(1, VAR_HIDE_VERSION) }
hide-trustanchor{COLON} { YDVAR(1, VAR_HIDE_TRUSTANCHOR) }
identity{COLON} { YDVAR(1, VAR_IDENTITY) }
version{COLON} { YDVAR(1, VAR_VERSION) }
module-config{COLON} { YDVAR(1, VAR_MODULE_CONF) }
@ -302,6 +324,9 @@ val-bogus-ttl{COLON} { YDVAR(1, VAR_BOGUS_TTL) }
val-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) }
val-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) }
ignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) }
serve-expired{COLON} { YDVAR(1, VAR_SERVE_EXPIRED) }
fake-dsa{COLON} { YDVAR(1, VAR_FAKE_DSA) }
fake-sha1{COLON} { YDVAR(1, VAR_FAKE_SHA1) }
val-log-level{COLON} { YDVAR(1, VAR_VAL_LOG_LEVEL) }
key-cache-size{COLON} { YDVAR(1, VAR_KEY_CACHE_SIZE) }
key-cache-slabs{COLON} { YDVAR(1, VAR_KEY_CACHE_SLABS) }
@ -313,15 +338,20 @@ del-holddown{COLON} { YDVAR(1, VAR_DEL_HOLDDOWN) }
keep-missing{COLON} { YDVAR(1, VAR_KEEP_MISSING) }
permit-small-holddown{COLON} { YDVAR(1, VAR_PERMIT_SMALL_HOLDDOWN) }
use-syslog{COLON} { YDVAR(1, VAR_USE_SYSLOG) }
log-identity{COLON} { YDVAR(1, VAR_LOG_IDENTITY) }
log-time-ascii{COLON} { YDVAR(1, VAR_LOG_TIME_ASCII) }
log-queries{COLON} { YDVAR(1, VAR_LOG_QUERIES) }
log-replies{COLON} { YDVAR(1, VAR_LOG_REPLIES) }
local-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) }
local-data{COLON} { YDVAR(1, VAR_LOCAL_DATA) }
local-data-ptr{COLON} { YDVAR(1, VAR_LOCAL_DATA_PTR) }
unblock-lan-zones{COLON} { YDVAR(1, VAR_UNBLOCK_LAN_ZONES) }
insecure-lan-zones{COLON} { YDVAR(1, VAR_INSECURE_LAN_ZONES) }
statistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) }
statistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) }
extended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) }
shm-enable{COLON} { YDVAR(1, VAR_SHM_ENABLE) }
shm-key{COLON} { YDVAR(1, VAR_SHM_KEY) }
remote-control{COLON} { YDVAR(0, VAR_REMOTE_CONTROL) }
control-enable{COLON} { YDVAR(1, VAR_CONTROL_ENABLE) }
control-interface{COLON} { YDVAR(1, VAR_CONTROL_INTERFACE) }
@ -339,6 +369,13 @@ rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
max-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) }
dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) }
dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) }
define-tag{COLON} { YDVAR(1, VAR_DEFINE_TAG) }
local-zone-tag{COLON} { YDVAR(2, VAR_LOCAL_ZONE_TAG) }
access-control-tag{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_TAG) }
access-control-tag-action{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_ACTION) }
access-control-tag-data{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_DATA) }
access-control-view{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_VIEW) }
local-zone-override{COLON} { YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) }
dnstap{COLON} { YDVAR(0, VAR_DNSTAP) }
dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) }
dnstap-socket-path{COLON} { YDVAR(1, VAR_DNSTAP_SOCKET_PATH) }
@ -358,12 +395,26 @@ dnstap-log-forwarder-query-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
dnstap-log-forwarder-response-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) }
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
ip-ratelimit-slabs{COLON} { YDVAR(1, VAR_IP_RATELIMIT_SLABS) }
ratelimit-slabs{COLON} { YDVAR(1, VAR_RATELIMIT_SLABS) }
ip-ratelimit-size{COLON} { YDVAR(1, VAR_IP_RATELIMIT_SIZE) }
ratelimit-size{COLON} { YDVAR(1, VAR_RATELIMIT_SIZE) }
ratelimit-for-domain{COLON} { YDVAR(2, VAR_RATELIMIT_FOR_DOMAIN) }
ratelimit-below-domain{COLON} { YDVAR(2, VAR_RATELIMIT_BELOW_DOMAIN) }
ip-ratelimit-factor{COLON} { YDVAR(1, VAR_IP_RATELIMIT_FACTOR) }
ratelimit-factor{COLON} { YDVAR(1, VAR_RATELIMIT_FACTOR) }
response-ip-tag{COLON} { YDVAR(2, VAR_RESPONSE_IP_TAG) }
response-ip{COLON} { YDVAR(2, VAR_RESPONSE_IP) }
response-ip-data{COLON} { YDVAR(2, VAR_RESPONSE_IP_DATA) }
dnscrypt{COLON} { YDVAR(0, VAR_DNSCRYPT) }
dnscrypt-enable{COLON} { YDVAR(1, VAR_DNSCRYPT_ENABLE) }
dnscrypt-port{COLON} { YDVAR(1, VAR_DNSCRYPT_PORT) }
dnscrypt-provider{COLON} { YDVAR(1, VAR_DNSCRYPT_PROVIDER) }
dnscrypt-secret-key{COLON} { YDVAR(1, VAR_DNSCRYPT_SECRET_KEY) }
dnscrypt-provider-cert{COLON} { YDVAR(1, VAR_DNSCRYPT_PROVIDER_CERT) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
/* Quoted strings. Strip leading and ending quotes */

File diff suppressed because it is too large Load diff

View file

@ -1,19 +1,19 @@
/* A Bison parser, made by GNU Bison 2.7. */
/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
@ -26,13 +26,13 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_YY_UTIL_CONFIGPARSER_H_INCLUDED
# define YY_YY_UTIL_CONFIGPARSER_H_INCLUDED
/* Enabling traces. */
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
@ -40,173 +40,217 @@
extern int yydebug;
#endif
/* Tokens. */
/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
SPACE = 258,
LETTER = 259,
NEWLINE = 260,
COMMENT = 261,
COLON = 262,
ANY = 263,
ZONESTR = 264,
STRING_ARG = 265,
VAR_SERVER = 266,
VAR_VERBOSITY = 267,
VAR_NUM_THREADS = 268,
VAR_PORT = 269,
VAR_OUTGOING_RANGE = 270,
VAR_INTERFACE = 271,
VAR_DO_IP4 = 272,
VAR_DO_IP6 = 273,
VAR_DO_UDP = 274,
VAR_DO_TCP = 275,
VAR_CHROOT = 276,
VAR_USERNAME = 277,
VAR_DIRECTORY = 278,
VAR_LOGFILE = 279,
VAR_PIDFILE = 280,
VAR_MSG_CACHE_SIZE = 281,
VAR_MSG_CACHE_SLABS = 282,
VAR_NUM_QUERIES_PER_THREAD = 283,
VAR_RRSET_CACHE_SIZE = 284,
VAR_RRSET_CACHE_SLABS = 285,
VAR_OUTGOING_NUM_TCP = 286,
VAR_INFRA_HOST_TTL = 287,
VAR_INFRA_LAME_TTL = 288,
VAR_INFRA_CACHE_SLABS = 289,
VAR_INFRA_CACHE_NUMHOSTS = 290,
VAR_INFRA_CACHE_LAME_SIZE = 291,
VAR_NAME = 292,
VAR_STUB_ZONE = 293,
VAR_STUB_HOST = 294,
VAR_STUB_ADDR = 295,
VAR_TARGET_FETCH_POLICY = 296,
VAR_HARDEN_SHORT_BUFSIZE = 297,
VAR_HARDEN_LARGE_QUERIES = 298,
VAR_FORWARD_ZONE = 299,
VAR_FORWARD_HOST = 300,
VAR_FORWARD_ADDR = 301,
VAR_DO_NOT_QUERY_ADDRESS = 302,
VAR_HIDE_IDENTITY = 303,
VAR_HIDE_VERSION = 304,
VAR_IDENTITY = 305,
VAR_VERSION = 306,
VAR_HARDEN_GLUE = 307,
VAR_MODULE_CONF = 308,
VAR_TRUST_ANCHOR_FILE = 309,
VAR_TRUST_ANCHOR = 310,
VAR_VAL_OVERRIDE_DATE = 311,
VAR_BOGUS_TTL = 312,
VAR_VAL_CLEAN_ADDITIONAL = 313,
VAR_VAL_PERMISSIVE_MODE = 314,
VAR_INCOMING_NUM_TCP = 315,
VAR_MSG_BUFFER_SIZE = 316,
VAR_KEY_CACHE_SIZE = 317,
VAR_KEY_CACHE_SLABS = 318,
VAR_TRUSTED_KEYS_FILE = 319,
VAR_VAL_NSEC3_KEYSIZE_ITERATIONS = 320,
VAR_USE_SYSLOG = 321,
VAR_OUTGOING_INTERFACE = 322,
VAR_ROOT_HINTS = 323,
VAR_DO_NOT_QUERY_LOCALHOST = 324,
VAR_CACHE_MAX_TTL = 325,
VAR_HARDEN_DNSSEC_STRIPPED = 326,
VAR_ACCESS_CONTROL = 327,
VAR_LOCAL_ZONE = 328,
VAR_LOCAL_DATA = 329,
VAR_INTERFACE_AUTOMATIC = 330,
VAR_STATISTICS_INTERVAL = 331,
VAR_DO_DAEMONIZE = 332,
VAR_USE_CAPS_FOR_ID = 333,
VAR_STATISTICS_CUMULATIVE = 334,
VAR_OUTGOING_PORT_PERMIT = 335,
VAR_OUTGOING_PORT_AVOID = 336,
VAR_DLV_ANCHOR_FILE = 337,
VAR_DLV_ANCHOR = 338,
VAR_NEG_CACHE_SIZE = 339,
VAR_HARDEN_REFERRAL_PATH = 340,
VAR_PRIVATE_ADDRESS = 341,
VAR_PRIVATE_DOMAIN = 342,
VAR_REMOTE_CONTROL = 343,
VAR_CONTROL_ENABLE = 344,
VAR_CONTROL_INTERFACE = 345,
VAR_CONTROL_PORT = 346,
VAR_SERVER_KEY_FILE = 347,
VAR_SERVER_CERT_FILE = 348,
VAR_CONTROL_KEY_FILE = 349,
VAR_CONTROL_CERT_FILE = 350,
VAR_CONTROL_USE_CERT = 351,
VAR_EXTENDED_STATISTICS = 352,
VAR_LOCAL_DATA_PTR = 353,
VAR_JOSTLE_TIMEOUT = 354,
VAR_STUB_PRIME = 355,
VAR_UNWANTED_REPLY_THRESHOLD = 356,
VAR_LOG_TIME_ASCII = 357,
VAR_DOMAIN_INSECURE = 358,
VAR_PYTHON = 359,
VAR_PYTHON_SCRIPT = 360,
VAR_VAL_SIG_SKEW_MIN = 361,
VAR_VAL_SIG_SKEW_MAX = 362,
VAR_CACHE_MIN_TTL = 363,
VAR_VAL_LOG_LEVEL = 364,
VAR_AUTO_TRUST_ANCHOR_FILE = 365,
VAR_KEEP_MISSING = 366,
VAR_ADD_HOLDDOWN = 367,
VAR_DEL_HOLDDOWN = 368,
VAR_SO_RCVBUF = 369,
VAR_EDNS_BUFFER_SIZE = 370,
VAR_PREFETCH = 371,
VAR_PREFETCH_KEY = 372,
VAR_SO_SNDBUF = 373,
VAR_SO_REUSEPORT = 374,
VAR_HARDEN_BELOW_NXDOMAIN = 375,
VAR_IGNORE_CD_FLAG = 376,
VAR_LOG_QUERIES = 377,
VAR_TCP_UPSTREAM = 378,
VAR_SSL_UPSTREAM = 379,
VAR_SSL_SERVICE_KEY = 380,
VAR_SSL_SERVICE_PEM = 381,
VAR_SSL_PORT = 382,
VAR_FORWARD_FIRST = 383,
VAR_STUB_FIRST = 384,
VAR_MINIMAL_RESPONSES = 385,
VAR_RRSET_ROUNDROBIN = 386,
VAR_MAX_UDP_SIZE = 387,
VAR_DELAY_CLOSE = 388,
VAR_UNBLOCK_LAN_ZONES = 389,
VAR_INFRA_CACHE_MIN_RTT = 390,
VAR_DNS64_PREFIX = 391,
VAR_DNS64_SYNTHALL = 392,
VAR_DNSTAP = 393,
VAR_DNSTAP_ENABLE = 394,
VAR_DNSTAP_SOCKET_PATH = 395,
VAR_DNSTAP_SEND_IDENTITY = 396,
VAR_DNSTAP_SEND_VERSION = 397,
VAR_DNSTAP_IDENTITY = 398,
VAR_DNSTAP_VERSION = 399,
VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES = 400,
VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES = 401,
VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES = 402,
VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES = 403,
VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES = 404,
VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES = 405,
VAR_HARDEN_ALGO_DOWNGRADE = 406,
VAR_IP_TRANSPARENT = 407,
VAR_RATELIMIT = 408,
VAR_RATELIMIT_SLABS = 409,
VAR_RATELIMIT_SIZE = 410,
VAR_RATELIMIT_FOR_DOMAIN = 411,
VAR_RATELIMIT_BELOW_DOMAIN = 412,
VAR_RATELIMIT_FACTOR = 413,
VAR_CAPS_WHITELIST = 414,
VAR_CACHE_MAX_NEGATIVE_TTL = 415,
VAR_PERMIT_SMALL_HOLDDOWN = 416,
VAR_QNAME_MINIMISATION = 417
};
enum yytokentype
{
SPACE = 258,
LETTER = 259,
NEWLINE = 260,
COMMENT = 261,
COLON = 262,
ANY = 263,
ZONESTR = 264,
STRING_ARG = 265,
VAR_SERVER = 266,
VAR_VERBOSITY = 267,
VAR_NUM_THREADS = 268,
VAR_PORT = 269,
VAR_OUTGOING_RANGE = 270,
VAR_INTERFACE = 271,
VAR_DO_IP4 = 272,
VAR_DO_IP6 = 273,
VAR_PREFER_IP6 = 274,
VAR_DO_UDP = 275,
VAR_DO_TCP = 276,
VAR_TCP_MSS = 277,
VAR_OUTGOING_TCP_MSS = 278,
VAR_CHROOT = 279,
VAR_USERNAME = 280,
VAR_DIRECTORY = 281,
VAR_LOGFILE = 282,
VAR_PIDFILE = 283,
VAR_MSG_CACHE_SIZE = 284,
VAR_MSG_CACHE_SLABS = 285,
VAR_NUM_QUERIES_PER_THREAD = 286,
VAR_RRSET_CACHE_SIZE = 287,
VAR_RRSET_CACHE_SLABS = 288,
VAR_OUTGOING_NUM_TCP = 289,
VAR_INFRA_HOST_TTL = 290,
VAR_INFRA_LAME_TTL = 291,
VAR_INFRA_CACHE_SLABS = 292,
VAR_INFRA_CACHE_NUMHOSTS = 293,
VAR_INFRA_CACHE_LAME_SIZE = 294,
VAR_NAME = 295,
VAR_STUB_ZONE = 296,
VAR_STUB_HOST = 297,
VAR_STUB_ADDR = 298,
VAR_TARGET_FETCH_POLICY = 299,
VAR_HARDEN_SHORT_BUFSIZE = 300,
VAR_HARDEN_LARGE_QUERIES = 301,
VAR_FORWARD_ZONE = 302,
VAR_FORWARD_HOST = 303,
VAR_FORWARD_ADDR = 304,
VAR_DO_NOT_QUERY_ADDRESS = 305,
VAR_HIDE_IDENTITY = 306,
VAR_HIDE_VERSION = 307,
VAR_IDENTITY = 308,
VAR_VERSION = 309,
VAR_HARDEN_GLUE = 310,
VAR_MODULE_CONF = 311,
VAR_TRUST_ANCHOR_FILE = 312,
VAR_TRUST_ANCHOR = 313,
VAR_VAL_OVERRIDE_DATE = 314,
VAR_BOGUS_TTL = 315,
VAR_VAL_CLEAN_ADDITIONAL = 316,
VAR_VAL_PERMISSIVE_MODE = 317,
VAR_INCOMING_NUM_TCP = 318,
VAR_MSG_BUFFER_SIZE = 319,
VAR_KEY_CACHE_SIZE = 320,
VAR_KEY_CACHE_SLABS = 321,
VAR_TRUSTED_KEYS_FILE = 322,
VAR_VAL_NSEC3_KEYSIZE_ITERATIONS = 323,
VAR_USE_SYSLOG = 324,
VAR_OUTGOING_INTERFACE = 325,
VAR_ROOT_HINTS = 326,
VAR_DO_NOT_QUERY_LOCALHOST = 327,
VAR_CACHE_MAX_TTL = 328,
VAR_HARDEN_DNSSEC_STRIPPED = 329,
VAR_ACCESS_CONTROL = 330,
VAR_LOCAL_ZONE = 331,
VAR_LOCAL_DATA = 332,
VAR_INTERFACE_AUTOMATIC = 333,
VAR_STATISTICS_INTERVAL = 334,
VAR_DO_DAEMONIZE = 335,
VAR_USE_CAPS_FOR_ID = 336,
VAR_STATISTICS_CUMULATIVE = 337,
VAR_OUTGOING_PORT_PERMIT = 338,
VAR_OUTGOING_PORT_AVOID = 339,
VAR_DLV_ANCHOR_FILE = 340,
VAR_DLV_ANCHOR = 341,
VAR_NEG_CACHE_SIZE = 342,
VAR_HARDEN_REFERRAL_PATH = 343,
VAR_PRIVATE_ADDRESS = 344,
VAR_PRIVATE_DOMAIN = 345,
VAR_REMOTE_CONTROL = 346,
VAR_CONTROL_ENABLE = 347,
VAR_CONTROL_INTERFACE = 348,
VAR_CONTROL_PORT = 349,
VAR_SERVER_KEY_FILE = 350,
VAR_SERVER_CERT_FILE = 351,
VAR_CONTROL_KEY_FILE = 352,
VAR_CONTROL_CERT_FILE = 353,
VAR_CONTROL_USE_CERT = 354,
VAR_EXTENDED_STATISTICS = 355,
VAR_LOCAL_DATA_PTR = 356,
VAR_JOSTLE_TIMEOUT = 357,
VAR_STUB_PRIME = 358,
VAR_UNWANTED_REPLY_THRESHOLD = 359,
VAR_LOG_TIME_ASCII = 360,
VAR_DOMAIN_INSECURE = 361,
VAR_PYTHON = 362,
VAR_PYTHON_SCRIPT = 363,
VAR_VAL_SIG_SKEW_MIN = 364,
VAR_VAL_SIG_SKEW_MAX = 365,
VAR_CACHE_MIN_TTL = 366,
VAR_VAL_LOG_LEVEL = 367,
VAR_AUTO_TRUST_ANCHOR_FILE = 368,
VAR_KEEP_MISSING = 369,
VAR_ADD_HOLDDOWN = 370,
VAR_DEL_HOLDDOWN = 371,
VAR_SO_RCVBUF = 372,
VAR_EDNS_BUFFER_SIZE = 373,
VAR_PREFETCH = 374,
VAR_PREFETCH_KEY = 375,
VAR_SO_SNDBUF = 376,
VAR_SO_REUSEPORT = 377,
VAR_HARDEN_BELOW_NXDOMAIN = 378,
VAR_IGNORE_CD_FLAG = 379,
VAR_LOG_QUERIES = 380,
VAR_LOG_REPLIES = 381,
VAR_TCP_UPSTREAM = 382,
VAR_SSL_UPSTREAM = 383,
VAR_SSL_SERVICE_KEY = 384,
VAR_SSL_SERVICE_PEM = 385,
VAR_SSL_PORT = 386,
VAR_FORWARD_FIRST = 387,
VAR_STUB_SSL_UPSTREAM = 388,
VAR_FORWARD_SSL_UPSTREAM = 389,
VAR_STUB_FIRST = 390,
VAR_MINIMAL_RESPONSES = 391,
VAR_RRSET_ROUNDROBIN = 392,
VAR_MAX_UDP_SIZE = 393,
VAR_DELAY_CLOSE = 394,
VAR_UNBLOCK_LAN_ZONES = 395,
VAR_INSECURE_LAN_ZONES = 396,
VAR_INFRA_CACHE_MIN_RTT = 397,
VAR_DNS64_PREFIX = 398,
VAR_DNS64_SYNTHALL = 399,
VAR_DNSTAP = 400,
VAR_DNSTAP_ENABLE = 401,
VAR_DNSTAP_SOCKET_PATH = 402,
VAR_DNSTAP_SEND_IDENTITY = 403,
VAR_DNSTAP_SEND_VERSION = 404,
VAR_DNSTAP_IDENTITY = 405,
VAR_DNSTAP_VERSION = 406,
VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES = 407,
VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES = 408,
VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES = 409,
VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES = 410,
VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES = 411,
VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES = 412,
VAR_RESPONSE_IP_TAG = 413,
VAR_RESPONSE_IP = 414,
VAR_RESPONSE_IP_DATA = 415,
VAR_HARDEN_ALGO_DOWNGRADE = 416,
VAR_IP_TRANSPARENT = 417,
VAR_DISABLE_DNSSEC_LAME_CHECK = 418,
VAR_IP_RATELIMIT = 419,
VAR_IP_RATELIMIT_SLABS = 420,
VAR_IP_RATELIMIT_SIZE = 421,
VAR_RATELIMIT = 422,
VAR_RATELIMIT_SLABS = 423,
VAR_RATELIMIT_SIZE = 424,
VAR_RATELIMIT_FOR_DOMAIN = 425,
VAR_RATELIMIT_BELOW_DOMAIN = 426,
VAR_IP_RATELIMIT_FACTOR = 427,
VAR_RATELIMIT_FACTOR = 428,
VAR_SEND_CLIENT_SUBNET = 429,
VAR_CLIENT_SUBNET_ALWAYS_FORWARD = 430,
VAR_CLIENT_SUBNET_OPCODE = 431,
VAR_MAX_CLIENT_SUBNET_IPV4 = 432,
VAR_MAX_CLIENT_SUBNET_IPV6 = 433,
VAR_CAPS_WHITELIST = 434,
VAR_CACHE_MAX_NEGATIVE_TTL = 435,
VAR_PERMIT_SMALL_HOLDDOWN = 436,
VAR_QNAME_MINIMISATION = 437,
VAR_QNAME_MINIMISATION_STRICT = 438,
VAR_IP_FREEBIND = 439,
VAR_DEFINE_TAG = 440,
VAR_LOCAL_ZONE_TAG = 441,
VAR_ACCESS_CONTROL_TAG = 442,
VAR_LOCAL_ZONE_OVERRIDE = 443,
VAR_ACCESS_CONTROL_TAG_ACTION = 444,
VAR_ACCESS_CONTROL_TAG_DATA = 445,
VAR_VIEW = 446,
VAR_ACCESS_CONTROL_VIEW = 447,
VAR_VIEW_FIRST = 448,
VAR_SERVE_EXPIRED = 449,
VAR_FAKE_DSA = 450,
VAR_FAKE_SHA1 = 451,
VAR_LOG_IDENTITY = 452,
VAR_HIDE_TRUSTANCHOR = 453,
VAR_USE_SYSTEMD = 454,
VAR_SHM_ENABLE = 455,
VAR_SHM_KEY = 456,
VAR_DNSCRYPT = 457,
VAR_DNSCRYPT_ENABLE = 458,
VAR_DNSCRYPT_PORT = 459,
VAR_DNSCRYPT_PROVIDER = 460,
VAR_DNSCRYPT_SECRET_KEY = 461,
VAR_DNSCRYPT_PROVIDER_CERT = 462
};
#endif
/* Tokens. */
#define SPACE 258
@ -225,184 +269,216 @@ extern int yydebug;
#define VAR_INTERFACE 271
#define VAR_DO_IP4 272
#define VAR_DO_IP6 273
#define VAR_DO_UDP 274
#define VAR_DO_TCP 275
#define VAR_CHROOT 276
#define VAR_USERNAME 277
#define VAR_DIRECTORY 278
#define VAR_LOGFILE 279
#define VAR_PIDFILE 280
#define VAR_MSG_CACHE_SIZE 281
#define VAR_MSG_CACHE_SLABS 282
#define VAR_NUM_QUERIES_PER_THREAD 283
#define VAR_RRSET_CACHE_SIZE 284
#define VAR_RRSET_CACHE_SLABS 285
#define VAR_OUTGOING_NUM_TCP 286
#define VAR_INFRA_HOST_TTL 287
#define VAR_INFRA_LAME_TTL 288
#define VAR_INFRA_CACHE_SLABS 289
#define VAR_INFRA_CACHE_NUMHOSTS 290
#define VAR_INFRA_CACHE_LAME_SIZE 291
#define VAR_NAME 292
#define VAR_STUB_ZONE 293
#define VAR_STUB_HOST 294
#define VAR_STUB_ADDR 295
#define VAR_TARGET_FETCH_POLICY 296
#define VAR_HARDEN_SHORT_BUFSIZE 297
#define VAR_HARDEN_LARGE_QUERIES 298
#define VAR_FORWARD_ZONE 299
#define VAR_FORWARD_HOST 300
#define VAR_FORWARD_ADDR 301
#define VAR_DO_NOT_QUERY_ADDRESS 302
#define VAR_HIDE_IDENTITY 303
#define VAR_HIDE_VERSION 304
#define VAR_IDENTITY 305
#define VAR_VERSION 306
#define VAR_HARDEN_GLUE 307
#define VAR_MODULE_CONF 308
#define VAR_TRUST_ANCHOR_FILE 309
#define VAR_TRUST_ANCHOR 310
#define VAR_VAL_OVERRIDE_DATE 311
#define VAR_BOGUS_TTL 312
#define VAR_VAL_CLEAN_ADDITIONAL 313
#define VAR_VAL_PERMISSIVE_MODE 314
#define VAR_INCOMING_NUM_TCP 315
#define VAR_MSG_BUFFER_SIZE 316
#define VAR_KEY_CACHE_SIZE 317
#define VAR_KEY_CACHE_SLABS 318
#define VAR_TRUSTED_KEYS_FILE 319
#define VAR_VAL_NSEC3_KEYSIZE_ITERATIONS 320
#define VAR_USE_SYSLOG 321
#define VAR_OUTGOING_INTERFACE 322
#define VAR_ROOT_HINTS 323
#define VAR_DO_NOT_QUERY_LOCALHOST 324
#define VAR_CACHE_MAX_TTL 325
#define VAR_HARDEN_DNSSEC_STRIPPED 326
#define VAR_ACCESS_CONTROL 327
#define VAR_LOCAL_ZONE 328
#define VAR_LOCAL_DATA 329
#define VAR_INTERFACE_AUTOMATIC 330
#define VAR_STATISTICS_INTERVAL 331
#define VAR_DO_DAEMONIZE 332
#define VAR_USE_CAPS_FOR_ID 333
#define VAR_STATISTICS_CUMULATIVE 334
#define VAR_OUTGOING_PORT_PERMIT 335
#define VAR_OUTGOING_PORT_AVOID 336
#define VAR_DLV_ANCHOR_FILE 337
#define VAR_DLV_ANCHOR 338
#define VAR_NEG_CACHE_SIZE 339
#define VAR_HARDEN_REFERRAL_PATH 340
#define VAR_PRIVATE_ADDRESS 341
#define VAR_PRIVATE_DOMAIN 342
#define VAR_REMOTE_CONTROL 343
#define VAR_CONTROL_ENABLE 344
#define VAR_CONTROL_INTERFACE 345
#define VAR_CONTROL_PORT 346
#define VAR_SERVER_KEY_FILE 347
#define VAR_SERVER_CERT_FILE 348
#define VAR_CONTROL_KEY_FILE 349
#define VAR_CONTROL_CERT_FILE 350
#define VAR_CONTROL_USE_CERT 351
#define VAR_EXTENDED_STATISTICS 352
#define VAR_LOCAL_DATA_PTR 353
#define VAR_JOSTLE_TIMEOUT 354
#define VAR_STUB_PRIME 355
#define VAR_UNWANTED_REPLY_THRESHOLD 356
#define VAR_LOG_TIME_ASCII 357
#define VAR_DOMAIN_INSECURE 358
#define VAR_PYTHON 359
#define VAR_PYTHON_SCRIPT 360
#define VAR_VAL_SIG_SKEW_MIN 361
#define VAR_VAL_SIG_SKEW_MAX 362
#define VAR_CACHE_MIN_TTL 363
#define VAR_VAL_LOG_LEVEL 364
#define VAR_AUTO_TRUST_ANCHOR_FILE 365
#define VAR_KEEP_MISSING 366
#define VAR_ADD_HOLDDOWN 367
#define VAR_DEL_HOLDDOWN 368
#define VAR_SO_RCVBUF 369
#define VAR_EDNS_BUFFER_SIZE 370
#define VAR_PREFETCH 371
#define VAR_PREFETCH_KEY 372
#define VAR_SO_SNDBUF 373
#define VAR_SO_REUSEPORT 374
#define VAR_HARDEN_BELOW_NXDOMAIN 375
#define VAR_IGNORE_CD_FLAG 376
#define VAR_LOG_QUERIES 377
#define VAR_TCP_UPSTREAM 378
#define VAR_SSL_UPSTREAM 379
#define VAR_SSL_SERVICE_KEY 380
#define VAR_SSL_SERVICE_PEM 381
#define VAR_SSL_PORT 382
#define VAR_FORWARD_FIRST 383
#define VAR_STUB_FIRST 384
#define VAR_MINIMAL_RESPONSES 385
#define VAR_RRSET_ROUNDROBIN 386
#define VAR_MAX_UDP_SIZE 387
#define VAR_DELAY_CLOSE 388
#define VAR_UNBLOCK_LAN_ZONES 389
#define VAR_INFRA_CACHE_MIN_RTT 390
#define VAR_DNS64_PREFIX 391
#define VAR_DNS64_SYNTHALL 392
#define VAR_DNSTAP 393
#define VAR_DNSTAP_ENABLE 394
#define VAR_DNSTAP_SOCKET_PATH 395
#define VAR_DNSTAP_SEND_IDENTITY 396
#define VAR_DNSTAP_SEND_VERSION 397
#define VAR_DNSTAP_IDENTITY 398
#define VAR_DNSTAP_VERSION 399
#define VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES 400
#define VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES 401
#define VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES 402
#define VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES 403
#define VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES 404
#define VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES 405
#define VAR_HARDEN_ALGO_DOWNGRADE 406
#define VAR_IP_TRANSPARENT 407
#define VAR_RATELIMIT 408
#define VAR_RATELIMIT_SLABS 409
#define VAR_RATELIMIT_SIZE 410
#define VAR_RATELIMIT_FOR_DOMAIN 411
#define VAR_RATELIMIT_BELOW_DOMAIN 412
#define VAR_RATELIMIT_FACTOR 413
#define VAR_CAPS_WHITELIST 414
#define VAR_CACHE_MAX_NEGATIVE_TTL 415
#define VAR_PERMIT_SMALL_HOLDDOWN 416
#define VAR_QNAME_MINIMISATION 417
#define VAR_PREFER_IP6 274
#define VAR_DO_UDP 275
#define VAR_DO_TCP 276
#define VAR_TCP_MSS 277
#define VAR_OUTGOING_TCP_MSS 278
#define VAR_CHROOT 279
#define VAR_USERNAME 280
#define VAR_DIRECTORY 281
#define VAR_LOGFILE 282
#define VAR_PIDFILE 283
#define VAR_MSG_CACHE_SIZE 284
#define VAR_MSG_CACHE_SLABS 285
#define VAR_NUM_QUERIES_PER_THREAD 286
#define VAR_RRSET_CACHE_SIZE 287
#define VAR_RRSET_CACHE_SLABS 288
#define VAR_OUTGOING_NUM_TCP 289
#define VAR_INFRA_HOST_TTL 290
#define VAR_INFRA_LAME_TTL 291
#define VAR_INFRA_CACHE_SLABS 292
#define VAR_INFRA_CACHE_NUMHOSTS 293
#define VAR_INFRA_CACHE_LAME_SIZE 294
#define VAR_NAME 295
#define VAR_STUB_ZONE 296
#define VAR_STUB_HOST 297
#define VAR_STUB_ADDR 298
#define VAR_TARGET_FETCH_POLICY 299
#define VAR_HARDEN_SHORT_BUFSIZE 300
#define VAR_HARDEN_LARGE_QUERIES 301
#define VAR_FORWARD_ZONE 302
#define VAR_FORWARD_HOST 303
#define VAR_FORWARD_ADDR 304
#define VAR_DO_NOT_QUERY_ADDRESS 305
#define VAR_HIDE_IDENTITY 306
#define VAR_HIDE_VERSION 307
#define VAR_IDENTITY 308
#define VAR_VERSION 309
#define VAR_HARDEN_GLUE 310
#define VAR_MODULE_CONF 311
#define VAR_TRUST_ANCHOR_FILE 312
#define VAR_TRUST_ANCHOR 313
#define VAR_VAL_OVERRIDE_DATE 314
#define VAR_BOGUS_TTL 315
#define VAR_VAL_CLEAN_ADDITIONAL 316
#define VAR_VAL_PERMISSIVE_MODE 317
#define VAR_INCOMING_NUM_TCP 318
#define VAR_MSG_BUFFER_SIZE 319
#define VAR_KEY_CACHE_SIZE 320
#define VAR_KEY_CACHE_SLABS 321
#define VAR_TRUSTED_KEYS_FILE 322
#define VAR_VAL_NSEC3_KEYSIZE_ITERATIONS 323
#define VAR_USE_SYSLOG 324
#define VAR_OUTGOING_INTERFACE 325
#define VAR_ROOT_HINTS 326
#define VAR_DO_NOT_QUERY_LOCALHOST 327
#define VAR_CACHE_MAX_TTL 328
#define VAR_HARDEN_DNSSEC_STRIPPED 329
#define VAR_ACCESS_CONTROL 330
#define VAR_LOCAL_ZONE 331
#define VAR_LOCAL_DATA 332
#define VAR_INTERFACE_AUTOMATIC 333
#define VAR_STATISTICS_INTERVAL 334
#define VAR_DO_DAEMONIZE 335
#define VAR_USE_CAPS_FOR_ID 336
#define VAR_STATISTICS_CUMULATIVE 337
#define VAR_OUTGOING_PORT_PERMIT 338
#define VAR_OUTGOING_PORT_AVOID 339
#define VAR_DLV_ANCHOR_FILE 340
#define VAR_DLV_ANCHOR 341
#define VAR_NEG_CACHE_SIZE 342
#define VAR_HARDEN_REFERRAL_PATH 343
#define VAR_PRIVATE_ADDRESS 344
#define VAR_PRIVATE_DOMAIN 345
#define VAR_REMOTE_CONTROL 346
#define VAR_CONTROL_ENABLE 347
#define VAR_CONTROL_INTERFACE 348
#define VAR_CONTROL_PORT 349
#define VAR_SERVER_KEY_FILE 350
#define VAR_SERVER_CERT_FILE 351
#define VAR_CONTROL_KEY_FILE 352
#define VAR_CONTROL_CERT_FILE 353
#define VAR_CONTROL_USE_CERT 354
#define VAR_EXTENDED_STATISTICS 355
#define VAR_LOCAL_DATA_PTR 356
#define VAR_JOSTLE_TIMEOUT 357
#define VAR_STUB_PRIME 358
#define VAR_UNWANTED_REPLY_THRESHOLD 359
#define VAR_LOG_TIME_ASCII 360
#define VAR_DOMAIN_INSECURE 361
#define VAR_PYTHON 362
#define VAR_PYTHON_SCRIPT 363
#define VAR_VAL_SIG_SKEW_MIN 364
#define VAR_VAL_SIG_SKEW_MAX 365
#define VAR_CACHE_MIN_TTL 366
#define VAR_VAL_LOG_LEVEL 367
#define VAR_AUTO_TRUST_ANCHOR_FILE 368
#define VAR_KEEP_MISSING 369
#define VAR_ADD_HOLDDOWN 370
#define VAR_DEL_HOLDDOWN 371
#define VAR_SO_RCVBUF 372
#define VAR_EDNS_BUFFER_SIZE 373
#define VAR_PREFETCH 374
#define VAR_PREFETCH_KEY 375
#define VAR_SO_SNDBUF 376
#define VAR_SO_REUSEPORT 377
#define VAR_HARDEN_BELOW_NXDOMAIN 378
#define VAR_IGNORE_CD_FLAG 379
#define VAR_LOG_QUERIES 380
#define VAR_LOG_REPLIES 381
#define VAR_TCP_UPSTREAM 382
#define VAR_SSL_UPSTREAM 383
#define VAR_SSL_SERVICE_KEY 384
#define VAR_SSL_SERVICE_PEM 385
#define VAR_SSL_PORT 386
#define VAR_FORWARD_FIRST 387
#define VAR_STUB_SSL_UPSTREAM 388
#define VAR_FORWARD_SSL_UPSTREAM 389
#define VAR_STUB_FIRST 390
#define VAR_MINIMAL_RESPONSES 391
#define VAR_RRSET_ROUNDROBIN 392
#define VAR_MAX_UDP_SIZE 393
#define VAR_DELAY_CLOSE 394
#define VAR_UNBLOCK_LAN_ZONES 395
#define VAR_INSECURE_LAN_ZONES 396
#define VAR_INFRA_CACHE_MIN_RTT 397
#define VAR_DNS64_PREFIX 398
#define VAR_DNS64_SYNTHALL 399
#define VAR_DNSTAP 400
#define VAR_DNSTAP_ENABLE 401
#define VAR_DNSTAP_SOCKET_PATH 402
#define VAR_DNSTAP_SEND_IDENTITY 403
#define VAR_DNSTAP_SEND_VERSION 404
#define VAR_DNSTAP_IDENTITY 405
#define VAR_DNSTAP_VERSION 406
#define VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES 407
#define VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES 408
#define VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES 409
#define VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES 410
#define VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES 411
#define VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES 412
#define VAR_RESPONSE_IP_TAG 413
#define VAR_RESPONSE_IP 414
#define VAR_RESPONSE_IP_DATA 415
#define VAR_HARDEN_ALGO_DOWNGRADE 416
#define VAR_IP_TRANSPARENT 417
#define VAR_DISABLE_DNSSEC_LAME_CHECK 418
#define VAR_IP_RATELIMIT 419
#define VAR_IP_RATELIMIT_SLABS 420
#define VAR_IP_RATELIMIT_SIZE 421
#define VAR_RATELIMIT 422
#define VAR_RATELIMIT_SLABS 423
#define VAR_RATELIMIT_SIZE 424
#define VAR_RATELIMIT_FOR_DOMAIN 425
#define VAR_RATELIMIT_BELOW_DOMAIN 426
#define VAR_IP_RATELIMIT_FACTOR 427
#define VAR_RATELIMIT_FACTOR 428
#define VAR_SEND_CLIENT_SUBNET 429
#define VAR_CLIENT_SUBNET_ALWAYS_FORWARD 430
#define VAR_CLIENT_SUBNET_OPCODE 431
#define VAR_MAX_CLIENT_SUBNET_IPV4 432
#define VAR_MAX_CLIENT_SUBNET_IPV6 433
#define VAR_CAPS_WHITELIST 434
#define VAR_CACHE_MAX_NEGATIVE_TTL 435
#define VAR_PERMIT_SMALL_HOLDDOWN 436
#define VAR_QNAME_MINIMISATION 437
#define VAR_QNAME_MINIMISATION_STRICT 438
#define VAR_IP_FREEBIND 439
#define VAR_DEFINE_TAG 440
#define VAR_LOCAL_ZONE_TAG 441
#define VAR_ACCESS_CONTROL_TAG 442
#define VAR_LOCAL_ZONE_OVERRIDE 443
#define VAR_ACCESS_CONTROL_TAG_ACTION 444
#define VAR_ACCESS_CONTROL_TAG_DATA 445
#define VAR_VIEW 446
#define VAR_ACCESS_CONTROL_VIEW 447
#define VAR_VIEW_FIRST 448
#define VAR_SERVE_EXPIRED 449
#define VAR_FAKE_DSA 450
#define VAR_FAKE_SHA1 451
#define VAR_LOG_IDENTITY 452
#define VAR_HIDE_TRUSTANCHOR 453
#define VAR_USE_SYSTEMD 454
#define VAR_SHM_ENABLE 455
#define VAR_SHM_KEY 456
#define VAR_DNSCRYPT 457
#define VAR_DNSCRYPT_ENABLE 458
#define VAR_DNSCRYPT_PORT 459
#define VAR_DNSCRYPT_PROVIDER 460
#define VAR_DNSCRYPT_SECRET_KEY 461
#define VAR_DNSCRYPT_PROVIDER_CERT 462
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
union YYSTYPE
{
/* Line 2058 of yacc.c */
#line 64 "./util/configparser.y"
#line 66 "util/configparser.y" /* yacc.c:1909 */
char* str;
#line 472 "util/configparser.h" /* yacc.c:1909 */
};
/* Line 2058 of yacc.c */
#line 386 "util/configparser.h"
} YYSTYPE;
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE yylval;
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
#else
int yyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int yyparse (void);
#else
int yyparse ();
#endif
#endif /* ! YYPARSE_PARAM */
#endif /* !YY_YY_UTIL_CONFIGPARSER_H_INCLUDED */

View file

@ -51,6 +51,8 @@
int ub_c_lex(void);
void ub_c_error(const char *message);
static void validate_respip_action(const char* action);
/* these need to be global, otherwise they cannot be used inside yacc */
extern struct config_parser_state* cfg_parser;
@ -69,7 +71,8 @@ extern struct config_parser_state* cfg_parser;
%token <str> STRING_ARG
%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
%token VAR_OUTGOING_RANGE VAR_INTERFACE
%token VAR_DO_IP4 VAR_DO_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_DO_IP4 VAR_DO_IP6 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS
%token VAR_CHROOT VAR_USERNAME VAR_DIRECTORY VAR_LOGFILE VAR_PIDFILE
%token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD
%token VAR_RRSET_CACHE_SIZE VAR_RRSET_CACHE_SLABS VAR_OUTGOING_NUM_TCP
@ -103,10 +106,13 @@ extern struct config_parser_state* cfg_parser;
%token VAR_AUTO_TRUST_ANCHOR_FILE VAR_KEEP_MISSING VAR_ADD_HOLDDOWN
%token VAR_DEL_HOLDDOWN VAR_SO_RCVBUF VAR_EDNS_BUFFER_SIZE VAR_PREFETCH
%token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_SO_REUSEPORT VAR_HARDEN_BELOW_NXDOMAIN
%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_LOG_REPLIES
%token VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
%token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE VAR_UNBLOCK_LAN_ZONES
%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
%token VAR_INFRA_CACHE_MIN_RTT
%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL
%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH
@ -118,17 +124,34 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
%token VAR_DISABLE_DNSSEC_LAME_CHECK
%token VAR_IP_RATELIMIT VAR_IP_RATELIMIT_SLABS VAR_IP_RATELIMIT_SIZE
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN VAR_RATELIMIT_FACTOR
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN
%token VAR_IP_RATELIMIT_FACTOR VAR_RATELIMIT_FACTOR
%token VAR_SEND_CLIENT_SUBNET VAR_CLIENT_SUBNET_ALWAYS_FORWARD
%token VAR_CLIENT_SUBNET_OPCODE
%token VAR_MAX_CLIENT_SUBNET_IPV4 VAR_MAX_CLIENT_SUBNET_IPV6
%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN
%token VAR_QNAME_MINIMISATION
%token VAR_QNAME_MINIMISATION VAR_QNAME_MINIMISATION_STRICT VAR_IP_FREEBIND
%token VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG VAR_ACCESS_CONTROL_TAG
%token VAR_LOCAL_ZONE_OVERRIDE VAR_ACCESS_CONTROL_TAG_ACTION
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_FAKE_DSA VAR_FAKE_SHA1
%token VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR
%token VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
%token VAR_DNSCRYPT VAR_DNSCRYPT_ENABLE VAR_DNSCRYPT_PORT VAR_DNSCRYPT_PROVIDER
%token VAR_DNSCRYPT_SECRET_KEY VAR_DNSCRYPT_PROVIDER_CERT
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
toplevelvar: serverstart contents_server | stubstart contents_stub |
forwardstart contents_forward | pythonstart contents_py |
rcstart contents_rc | dtstart contents_dt
rcstart contents_rc | dtstart contents_dt | viewstart
contents_view |
dnscstart contents_dnsc
;
/* server: declaration */
@ -141,7 +164,9 @@ contents_server: contents_server content_server
| ;
content_server: server_num_threads | server_verbosity | server_port |
server_outgoing_range | server_do_ip4 |
server_do_ip6 | server_do_udp | server_do_tcp |
server_do_ip6 | server_prefer_ip6 |
server_do_udp | server_do_tcp |
server_tcp_mss | server_outgoing_tcp_mss |
server_interface | server_chroot | server_username |
server_directory | server_logfile | server_pidfile |
server_msg_cache_size | server_msg_cache_slabs |
@ -177,17 +202,33 @@ content_server: server_num_threads | server_verbosity | server_port |
server_del_holddown | server_keep_missing | server_so_rcvbuf |
server_edns_buffer_size | server_prefetch | server_prefetch_key |
server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag |
server_log_queries | server_tcp_upstream | server_ssl_upstream |
server_log_queries | server_log_replies | server_tcp_upstream | server_ssl_upstream |
server_ssl_service_key | server_ssl_service_pem | server_ssl_port |
server_minimal_responses | server_rrset_roundrobin | server_max_udp_size |
server_so_reuseport | server_delay_close | server_unblock_lan_zones |
server_so_reuseport | server_delay_close |
server_unblock_lan_zones | server_insecure_lan_zones |
server_dns64_prefix | server_dns64_synthall |
server_infra_cache_min_rtt | server_harden_algo_downgrade |
server_ip_transparent | server_ratelimit | server_ratelimit_slabs |
server_ratelimit_size | server_ratelimit_for_domain |
server_ip_transparent | server_ip_ratelimit | server_ratelimit |
server_ip_ratelimit_slabs | server_ratelimit_slabs |
server_ip_ratelimit_size | server_ratelimit_size |
server_ratelimit_for_domain |
server_ratelimit_below_domain | server_ratelimit_factor |
server_ip_ratelimit_factor | server_send_client_subnet |
server_client_subnet_always_forward |
server_client_subnet_opcode |
server_max_client_subnet_ipv4 | server_max_client_subnet_ipv6 |
server_caps_whitelist | server_cache_max_negative_ttl |
server_permit_small_holddown | server_qname_minimisation
server_permit_small_holddown | server_qname_minimisation |
server_ip_freebind | server_define_tag | server_local_zone_tag |
server_disable_dnssec_lame_check | server_access_control_tag |
server_local_zone_override | server_access_control_tag_action |
server_access_control_tag_data | server_access_control_view |
server_qname_minimisation_strict | server_serve_expired |
server_fake_dsa | server_log_identity | server_use_systemd |
server_response_ip_tag | server_response_ip | server_response_ip_data |
server_shm_enable | server_shm_key | server_fake_sha1 |
server_hide_trustanchor
;
stubstart: VAR_STUB_ZONE
{
@ -203,7 +244,8 @@ stubstart: VAR_STUB_ZONE
;
contents_stub: contents_stub content_stub
| ;
content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first
content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first |
stub_ssl_upstream
;
forwardstart: VAR_FORWARD_ZONE
{
@ -219,7 +261,27 @@ forwardstart: VAR_FORWARD_ZONE
;
contents_forward: contents_forward content_forward
| ;
content_forward: forward_name | forward_host | forward_addr | forward_first
content_forward: forward_name | forward_host | forward_addr | forward_first |
forward_ssl_upstream
;
viewstart: VAR_VIEW
{
struct config_view* s;
OUTYY(("\nP(view:)\n"));
s = (struct config_view*)calloc(1, sizeof(struct config_view));
if(s) {
s->next = cfg_parser->cfg->views;
if(s->next && !s->next->name)
yyerror("view without name");
cfg_parser->cfg->views = s;
} else
yyerror("out of memory");
}
;
contents_view: contents_view content_view
| ;
content_view: view_name | view_local_zone | view_local_data | view_first |
view_response_ip | view_response_ip_data | view_local_data_ptr
;
server_num_threads: VAR_NUM_THREADS STRING_ARG
{
@ -268,6 +330,26 @@ server_extended_statistics: VAR_EXTENDED_STATISTICS STRING_ARG
free($2);
}
;
server_shm_enable: VAR_SHM_ENABLE STRING_ARG
{
OUTYY(("P(server_shm_enable:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->shm_enable = (strcmp($2, "yes")==0);
free($2);
}
;
server_shm_key: VAR_SHM_KEY STRING_ARG
{
OUTYY(("P(server_shm_key:%s)\n", $2));
if(strcmp($2, "") == 0 || strcmp($2, "0") == 0)
cfg_parser->cfg->shm_key = 0;
else if(atoi($2) == 0)
yyerror("number expected");
else cfg_parser->cfg->shm_key = atoi($2);
free($2);
}
;
server_port: VAR_PORT STRING_ARG
{
OUTYY(("P(server_port:%s)\n", $2));
@ -277,6 +359,78 @@ server_port: VAR_PORT STRING_ARG
free($2);
}
;
server_send_client_subnet: VAR_SEND_CLIENT_SUBNET STRING_ARG
{
#ifdef CLIENT_SUBNET
OUTYY(("P(server_send_client_subnet:%s)\n", $2));
if(!cfg_strlist_insert(&cfg_parser->cfg->client_subnet, $2))
fatal_exit("out of memory adding client-subnet");
#else
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
#endif
}
;
server_client_subnet_always_forward:
VAR_CLIENT_SUBNET_ALWAYS_FORWARD STRING_ARG
{
#ifdef CLIENT_SUBNET
OUTYY(("P(server_client_subnet_always_forward:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else
cfg_parser->cfg->client_subnet_always_forward =
(strcmp($2, "yes")==0);
#else
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
#endif
free($2);
}
;
server_client_subnet_opcode: VAR_CLIENT_SUBNET_OPCODE STRING_ARG
{
#ifdef CLIENT_SUBNET
OUTYY(("P(client_subnet_opcode:%s)\n", $2));
OUTYY(("P(Depricated option, ignoring)\n"));
#else
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
#endif
free($2);
}
;
server_max_client_subnet_ipv4: VAR_MAX_CLIENT_SUBNET_IPV4 STRING_ARG
{
#ifdef CLIENT_SUBNET
OUTYY(("P(max_client_subnet_ipv4:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("IPv4 subnet length expected");
else if (atoi($2) > 32)
cfg_parser->cfg->max_client_subnet_ipv4 = 32;
else if (atoi($2) < 0)
cfg_parser->cfg->max_client_subnet_ipv4 = 0;
else cfg_parser->cfg->max_client_subnet_ipv4 = (uint8_t)atoi($2);
#else
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
#endif
free($2);
}
;
server_max_client_subnet_ipv6: VAR_MAX_CLIENT_SUBNET_IPV6 STRING_ARG
{
#ifdef CLIENT_SUBNET
OUTYY(("P(max_client_subnet_ipv6:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("Ipv6 subnet length expected");
else if (atoi($2) > 128)
cfg_parser->cfg->max_client_subnet_ipv6 = 128;
else if (atoi($2) < 0)
cfg_parser->cfg->max_client_subnet_ipv6 = 0;
else cfg_parser->cfg->max_client_subnet_ipv6 = (uint8_t)atoi($2);
#else
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
#endif
free($2);
}
;
server_interface: VAR_INTERFACE STRING_ARG
{
OUTYY(("P(server_interface:%s)\n", $2));
@ -395,6 +549,33 @@ server_do_tcp: VAR_DO_TCP STRING_ARG
free($2);
}
;
server_prefer_ip6: VAR_PREFER_IP6 STRING_ARG
{
OUTYY(("P(server_prefer_ip6:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->prefer_ip6 = (strcmp($2, "yes")==0);
free($2);
}
;
server_tcp_mss: VAR_TCP_MSS STRING_ARG
{
OUTYY(("P(server_tcp_mss:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else cfg_parser->cfg->tcp_mss = atoi($2);
free($2);
}
;
server_outgoing_tcp_mss: VAR_OUTGOING_TCP_MSS STRING_ARG
{
OUTYY(("P(server_outgoing_tcp_mss:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else cfg_parser->cfg->outgoing_tcp_mss = atoi($2);
free($2);
}
;
server_tcp_upstream: VAR_TCP_UPSTREAM STRING_ARG
{
OUTYY(("P(server_tcp_upstream:%s)\n", $2));
@ -436,6 +617,15 @@ server_ssl_port: VAR_SSL_PORT STRING_ARG
free($2);
}
;
server_use_systemd: VAR_USE_SYSTEMD STRING_ARG
{
OUTYY(("P(server_use_systemd:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->use_systemd = (strcmp($2, "yes")==0);
free($2);
}
;
server_do_daemonize: VAR_DO_DAEMONIZE STRING_ARG
{
OUTYY(("P(server_do_daemonize:%s)\n", $2));
@ -477,6 +667,15 @@ server_log_queries: VAR_LOG_QUERIES STRING_ARG
free($2);
}
;
server_log_replies: VAR_LOG_REPLIES STRING_ARG
{
OUTYY(("P(server_log_replies:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->log_replies = (strcmp($2, "yes")==0);
free($2);
}
;
server_chroot: VAR_CHROOT STRING_ARG
{
OUTYY(("P(server_chroot:%s)\n", $2));
@ -496,6 +695,25 @@ server_directory: VAR_DIRECTORY STRING_ARG
OUTYY(("P(server_directory:%s)\n", $2));
free(cfg_parser->cfg->directory);
cfg_parser->cfg->directory = $2;
/* change there right away for includes relative to this */
if($2[0]) {
char* d;
#ifdef UB_ON_WINDOWS
w_config_adjust_directory(cfg_parser->cfg);
#endif
d = cfg_parser->cfg->directory;
/* adjust directory if we have already chroot,
* like, we reread after sighup */
if(cfg_parser->chroot && cfg_parser->chroot[0] &&
strncmp(d, cfg_parser->chroot, strlen(
cfg_parser->chroot)) == 0)
d += strlen(cfg_parser->chroot);
if(d[0]) {
if(chdir(d))
log_err("cannot chdir to directory: %s (%s)",
d, strerror(errno));
}
}
}
;
server_logfile: VAR_LOGFILE STRING_ARG
@ -590,6 +808,15 @@ server_hide_version: VAR_HIDE_VERSION STRING_ARG
free($2);
}
;
server_hide_trustanchor: VAR_HIDE_TRUSTANCHOR STRING_ARG
{
OUTYY(("P(server_hide_trustanchor:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->hide_trustanchor = (strcmp($2, "yes")==0);
free($2);
}
;
server_identity: VAR_IDENTITY STRING_ARG
{
OUTYY(("P(server_identity:%s)\n", $2));
@ -640,6 +867,16 @@ server_ip_transparent: VAR_IP_TRANSPARENT STRING_ARG
free($2);
}
;
server_ip_freebind: VAR_IP_FREEBIND STRING_ARG
{
OUTYY(("P(server_ip_freebind:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->ip_freebind =
(strcmp($2, "yes")==0);
free($2);
}
;
server_edns_buffer_size: VAR_EDNS_BUFFER_SIZE STRING_ARG
{
OUTYY(("P(server_edns_buffer_size:%s)\n", $2));
@ -722,6 +959,16 @@ server_unblock_lan_zones: VAR_UNBLOCK_LAN_ZONES STRING_ARG
free($2);
}
;
server_insecure_lan_zones: VAR_INSECURE_LAN_ZONES STRING_ARG
{
OUTYY(("P(server_insecure_lan_zones:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->insecure_lan_zones =
(strcmp($2, "yes")==0);
free($2);
}
;
server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING_ARG
{
OUTYY(("P(server_rrset_cache_size:%s)\n", $2));
@ -978,7 +1225,7 @@ server_module_conf: VAR_MODULE_CONF STRING_ARG
server_val_override_date: VAR_VAL_OVERRIDE_DATE STRING_ARG
{
OUTYY(("P(server_val_override_date:%s)\n", $2));
if(strlen($2) == 0 || strcmp($2, "0") == 0) {
if(*$2 == '\0' || strcmp($2, "0") == 0) {
cfg_parser->cfg->val_date_override = 0;
} else if(strlen($2) == 14) {
cfg_parser->cfg->val_date_override =
@ -996,7 +1243,7 @@ server_val_override_date: VAR_VAL_OVERRIDE_DATE STRING_ARG
server_val_sig_skew_min: VAR_VAL_SIG_SKEW_MIN STRING_ARG
{
OUTYY(("P(server_val_sig_skew_min:%s)\n", $2));
if(strlen($2) == 0 || strcmp($2, "0") == 0) {
if(*$2 == '\0' || strcmp($2, "0") == 0) {
cfg_parser->cfg->val_sig_skew_min = 0;
} else {
cfg_parser->cfg->val_sig_skew_min = atoi($2);
@ -1009,7 +1256,7 @@ server_val_sig_skew_min: VAR_VAL_SIG_SKEW_MIN STRING_ARG
server_val_sig_skew_max: VAR_VAL_SIG_SKEW_MAX STRING_ARG
{
OUTYY(("P(server_val_sig_skew_max:%s)\n", $2));
if(strlen($2) == 0 || strcmp($2, "0") == 0) {
if(*$2 == '\0' || strcmp($2, "0") == 0) {
cfg_parser->cfg->val_sig_skew_max = 0;
} else {
cfg_parser->cfg->val_sig_skew_max = atoi($2);
@ -1084,6 +1331,41 @@ server_ignore_cd_flag: VAR_IGNORE_CD_FLAG STRING_ARG
free($2);
}
;
server_serve_expired: VAR_SERVE_EXPIRED STRING_ARG
{
OUTYY(("P(server_serve_expired:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->serve_expired = (strcmp($2, "yes")==0);
free($2);
}
;
server_fake_dsa: VAR_FAKE_DSA STRING_ARG
{
OUTYY(("P(server_fake_dsa:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
#ifdef HAVE_SSL
else fake_dsa = (strcmp($2, "yes")==0);
if(fake_dsa)
log_warn("test option fake_dsa is enabled");
#endif
free($2);
}
;
server_fake_sha1: VAR_FAKE_SHA1 STRING_ARG
{
OUTYY(("P(server_fake_sha1:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
#ifdef HAVE_SSL
else fake_sha1 = (strcmp($2, "yes")==0);
if(fake_sha1)
log_warn("test option fake_sha1 is enabled");
#endif
free($2);
}
;
server_val_log_level: VAR_VAL_LOG_LEVEL STRING_ARG
{
OUTYY(("P(server_val_log_level:%s)\n", $2));
@ -1171,12 +1453,16 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
if(strcmp($3, "static")!=0 && strcmp($3, "deny")!=0 &&
strcmp($3, "refuse")!=0 && strcmp($3, "redirect")!=0 &&
strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0
&& strcmp($3, "typetransparent")!=0 &&
strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0)
&& strcmp($3, "typetransparent")!=0
&& strcmp($3, "always_transparent")!=0
&& strcmp($3, "always_refuse")!=0
&& strcmp($3, "always_nxdomain")!=0
&& strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0)
yyerror("local-zone type: expected static, deny, "
"refuse, redirect, transparent, "
"typetransparent, inform, inform_deny "
"or nodefault");
"typetransparent, inform, inform_deny, "
"always_transparent, always_refuse, "
"always_nxdomain or nodefault");
else if(strcmp($3, "nodefault")==0) {
if(!cfg_strlist_insert(&cfg_parser->cfg->
local_zones_nodefault, $2))
@ -1254,6 +1540,134 @@ server_dns64_synthall: VAR_DNS64_SYNTHALL STRING_ARG
free($2);
}
;
server_define_tag: VAR_DEFINE_TAG STRING_ARG
{
char* p, *s = $2;
OUTYY(("P(server_define_tag:%s)\n", $2));
while((p=strsep(&s, " \t\n")) != NULL) {
if(*p) {
if(!config_add_tag(cfg_parser->cfg, p))
yyerror("could not define-tag, "
"out of memory");
}
}
free($2);
}
;
server_local_zone_tag: VAR_LOCAL_ZONE_TAG STRING_ARG STRING_ARG
{
size_t len = 0;
uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3,
&len);
free($3);
OUTYY(("P(server_local_zone_tag:%s)\n", $2));
if(!bitlist)
yyerror("could not parse tags, (define-tag them first)");
if(bitlist) {
if(!cfg_strbytelist_insert(
&cfg_parser->cfg->local_zone_tags,
$2, bitlist, len)) {
yyerror("out of memory");
free($2);
}
}
}
;
server_access_control_tag: VAR_ACCESS_CONTROL_TAG STRING_ARG STRING_ARG
{
size_t len = 0;
uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3,
&len);
free($3);
OUTYY(("P(server_access_control_tag:%s)\n", $2));
if(!bitlist)
yyerror("could not parse tags, (define-tag them first)");
if(bitlist) {
if(!cfg_strbytelist_insert(
&cfg_parser->cfg->acl_tags,
$2, bitlist, len)) {
yyerror("out of memory");
free($2);
}
}
}
;
server_access_control_tag_action: VAR_ACCESS_CONTROL_TAG_ACTION STRING_ARG STRING_ARG STRING_ARG
{
OUTYY(("P(server_access_control_tag_action:%s %s %s)\n", $2, $3, $4));
if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_actions,
$2, $3, $4)) {
yyerror("out of memory");
free($2);
free($3);
free($4);
}
}
;
server_access_control_tag_data: VAR_ACCESS_CONTROL_TAG_DATA STRING_ARG STRING_ARG STRING_ARG
{
OUTYY(("P(server_access_control_tag_data:%s %s %s)\n", $2, $3, $4));
if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_datas,
$2, $3, $4)) {
yyerror("out of memory");
free($2);
free($3);
free($4);
}
}
;
server_local_zone_override: VAR_LOCAL_ZONE_OVERRIDE STRING_ARG STRING_ARG STRING_ARG
{
OUTYY(("P(server_local_zone_override:%s %s %s)\n", $2, $3, $4));
if(!cfg_str3list_insert(&cfg_parser->cfg->local_zone_overrides,
$2, $3, $4)) {
yyerror("out of memory");
free($2);
free($3);
free($4);
}
}
;
server_access_control_view: VAR_ACCESS_CONTROL_VIEW STRING_ARG STRING_ARG
{
OUTYY(("P(server_access_control_view:%s %s)\n", $2, $3));
if(!cfg_str2list_insert(&cfg_parser->cfg->acl_view,
$2, $3)) {
yyerror("out of memory");
free($2);
free($3);
}
}
;
server_response_ip_tag: VAR_RESPONSE_IP_TAG STRING_ARG STRING_ARG
{
size_t len = 0;
uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3,
&len);
free($3);
OUTYY(("P(response_ip_tag:%s)\n", $2));
if(!bitlist)
yyerror("could not parse tags, (define-tag them first)");
if(bitlist) {
if(!cfg_strbytelist_insert(
&cfg_parser->cfg->respip_tags,
$2, bitlist, len)) {
yyerror("out of memory");
free($2);
}
}
}
;
server_ip_ratelimit: VAR_IP_RATELIMIT STRING_ARG
{
OUTYY(("P(server_ip_ratelimit:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else cfg_parser->cfg->ip_ratelimit = atoi($2);
free($2);
}
;
server_ratelimit: VAR_RATELIMIT STRING_ARG
{
OUTYY(("P(server_ratelimit:%s)\n", $2));
@ -1263,6 +1677,14 @@ server_ratelimit: VAR_RATELIMIT STRING_ARG
free($2);
}
;
server_ip_ratelimit_size: VAR_IP_RATELIMIT_SIZE STRING_ARG
{
OUTYY(("P(server_ip_ratelimit_size:%s)\n", $2));
if(!cfg_parse_memsize($2, &cfg_parser->cfg->ip_ratelimit_size))
yyerror("memory size expected");
free($2);
}
;
server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG
{
OUTYY(("P(server_ratelimit_size:%s)\n", $2));
@ -1271,6 +1693,19 @@ server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG
free($2);
}
;
server_ip_ratelimit_slabs: VAR_IP_RATELIMIT_SLABS STRING_ARG
{
OUTYY(("P(server_ip_ratelimit_slabs:%s)\n", $2));
if(atoi($2) == 0)
yyerror("number expected");
else {
cfg_parser->cfg->ip_ratelimit_slabs = atoi($2);
if(!is_pow2(cfg_parser->cfg->ip_ratelimit_slabs))
yyerror("must be a power of 2");
}
free($2);
}
;
server_ratelimit_slabs: VAR_RATELIMIT_SLABS STRING_ARG
{
OUTYY(("P(server_ratelimit_slabs:%s)\n", $2));
@ -1310,6 +1745,15 @@ server_ratelimit_below_domain: VAR_RATELIMIT_BELOW_DOMAIN STRING_ARG STRING_ARG
}
}
;
server_ip_ratelimit_factor: VAR_IP_RATELIMIT_FACTOR STRING_ARG
{
OUTYY(("P(server_ip_ratelimit_factor:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else cfg_parser->cfg->ip_ratelimit_factor = atoi($2);
free($2);
}
;
server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG
{
OUTYY(("P(server_ratelimit_factor:%s)\n", $2));
@ -1329,6 +1773,16 @@ server_qname_minimisation: VAR_QNAME_MINIMISATION STRING_ARG
free($2);
}
;
server_qname_minimisation_strict: VAR_QNAME_MINIMISATION_STRICT STRING_ARG
{
OUTYY(("P(server_qname_minimisation_strict:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->qname_minimisation_strict =
(strcmp($2, "yes")==0);
free($2);
}
;
stub_name: VAR_NAME STRING_ARG
{
OUTYY(("P(name:%s)\n", $2));
@ -1362,6 +1816,16 @@ stub_first: VAR_STUB_FIRST STRING_ARG
free($2);
}
;
stub_ssl_upstream: VAR_STUB_SSL_UPSTREAM STRING_ARG
{
OUTYY(("P(stub-ssl-upstream:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->stubs->ssl_upstream =
(strcmp($2, "yes")==0);
free($2);
}
;
stub_prime: VAR_STUB_PRIME STRING_ARG
{
OUTYY(("P(stub-prime:%s)\n", $2));
@ -1405,6 +1869,106 @@ forward_first: VAR_FORWARD_FIRST STRING_ARG
free($2);
}
;
forward_ssl_upstream: VAR_FORWARD_SSL_UPSTREAM STRING_ARG
{
OUTYY(("P(forward-ssl-upstream:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->forwards->ssl_upstream =
(strcmp($2, "yes")==0);
free($2);
}
;
view_name: VAR_NAME STRING_ARG
{
OUTYY(("P(name:%s)\n", $2));
if(cfg_parser->cfg->views->name)
yyerror("view name override, there must be one "
"name for one view");
free(cfg_parser->cfg->views->name);
cfg_parser->cfg->views->name = $2;
}
;
view_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
{
OUTYY(("P(view_local_zone:%s %s)\n", $2, $3));
if(strcmp($3, "static")!=0 && strcmp($3, "deny")!=0 &&
strcmp($3, "refuse")!=0 && strcmp($3, "redirect")!=0 &&
strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0
&& strcmp($3, "typetransparent")!=0
&& strcmp($3, "always_transparent")!=0
&& strcmp($3, "always_refuse")!=0
&& strcmp($3, "always_nxdomain")!=0
&& strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0)
yyerror("local-zone type: expected static, deny, "
"refuse, redirect, transparent, "
"typetransparent, inform, inform_deny, "
"always_transparent, always_refuse, "
"always_nxdomain or nodefault");
else if(strcmp($3, "nodefault")==0) {
if(!cfg_strlist_insert(&cfg_parser->cfg->views->
local_zones_nodefault, $2))
fatal_exit("out of memory adding local-zone");
free($3);
} else {
if(!cfg_str2list_insert(
&cfg_parser->cfg->views->local_zones,
$2, $3))
fatal_exit("out of memory adding local-zone");
}
}
;
view_response_ip: VAR_RESPONSE_IP STRING_ARG STRING_ARG
{
OUTYY(("P(view_response_ip:%s %s)\n", $2, $3));
validate_respip_action($3);
if(!cfg_str2list_insert(
&cfg_parser->cfg->views->respip_actions, $2, $3))
fatal_exit("out of memory adding per-view "
"response-ip action");
}
;
view_response_ip_data: VAR_RESPONSE_IP_DATA STRING_ARG STRING_ARG
{
OUTYY(("P(view_response_ip_data:%s)\n", $2));
if(!cfg_str2list_insert(
&cfg_parser->cfg->views->respip_data, $2, $3))
fatal_exit("out of memory adding response-ip-data");
}
;
view_local_data: VAR_LOCAL_DATA STRING_ARG
{
OUTYY(("P(view_local_data:%s)\n", $2));
if(!cfg_strlist_insert(&cfg_parser->cfg->views->local_data, $2)) {
fatal_exit("out of memory adding local-data");
free($2);
}
}
;
view_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG
{
char* ptr;
OUTYY(("P(view_local_data_ptr:%s)\n", $2));
ptr = cfg_ptr_reverse($2);
free($2);
if(ptr) {
if(!cfg_strlist_insert(&cfg_parser->cfg->views->
local_data, ptr))
fatal_exit("out of memory adding local-data");
} else {
yyerror("local-data-ptr could not be reversed");
}
}
;
view_first: VAR_VIEW_FIRST STRING_ARG
{
OUTYY(("P(view-first:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->views->isfirst=(strcmp($2, "yes")==0);
free($2);
}
;
rcstart: VAR_REMOTE_CONTROL
{
OUTYY(("\nP(remote-control:)\n"));
@ -1611,6 +2175,108 @@ py_script: VAR_PYTHON_SCRIPT STRING_ARG
free(cfg_parser->cfg->python_script);
cfg_parser->cfg->python_script = $2;
}
server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
{
OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2));
if (strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->disable_dnssec_lame_check =
(strcmp($2, "yes")==0);
free($2);
}
;
server_log_identity: VAR_LOG_IDENTITY STRING_ARG
{
OUTYY(("P(server_log_identity:%s)\n", $2));
free(cfg_parser->cfg->log_identity);
cfg_parser->cfg->log_identity = $2;
}
;
server_response_ip: VAR_RESPONSE_IP STRING_ARG STRING_ARG
{
OUTYY(("P(server_response_ip:%s %s)\n", $2, $3));
validate_respip_action($3);
if(!cfg_str2list_insert(&cfg_parser->cfg->respip_actions,
$2, $3))
fatal_exit("out of memory adding response-ip");
}
;
server_response_ip_data: VAR_RESPONSE_IP_DATA STRING_ARG STRING_ARG
{
OUTYY(("P(server_response_ip_data:%s)\n", $2));
if(!cfg_str2list_insert(&cfg_parser->cfg->respip_data,
$2, $3))
fatal_exit("out of memory adding response-ip-data");
}
;
dnscstart: VAR_DNSCRYPT
{
OUTYY(("\nP(dnscrypt:)\n"));
OUTYY(("\nP(dnscrypt:)\n"));
}
;
contents_dnsc: contents_dnsc content_dnsc
| ;
content_dnsc:
dnsc_dnscrypt_enable | dnsc_dnscrypt_port | dnsc_dnscrypt_provider |
dnsc_dnscrypt_secret_key | dnsc_dnscrypt_provider_cert
;
dnsc_dnscrypt_enable: VAR_DNSCRYPT_ENABLE STRING_ARG
{
OUTYY(("P(dnsc_dnscrypt_enable:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->dnscrypt = (strcmp($2, "yes")==0);
}
;
dnsc_dnscrypt_port: VAR_DNSCRYPT_PORT STRING_ARG
{
OUTYY(("P(dnsc_dnscrypt_port:%s)\n", $2));
if(atoi($2) == 0)
yyerror("port number expected");
else cfg_parser->cfg->dnscrypt_port = atoi($2);
free($2);
}
;
dnsc_dnscrypt_provider: VAR_DNSCRYPT_PROVIDER STRING_ARG
{
OUTYY(("P(dnsc_dnscrypt_provider:%s)\n", $2));
free(cfg_parser->cfg->dnscrypt_provider);
cfg_parser->cfg->dnscrypt_provider = $2;
}
;
dnsc_dnscrypt_provider_cert: VAR_DNSCRYPT_PROVIDER_CERT STRING_ARG
{
OUTYY(("P(dnsc_dnscrypt_provider_cert:%s)\n", $2));
if(!cfg_strlist_insert(&cfg_parser->cfg->dnscrypt_provider_cert, $2))
fatal_exit("out of memory adding dnscrypt-provider-cert");
}
;
dnsc_dnscrypt_secret_key: VAR_DNSCRYPT_SECRET_KEY STRING_ARG
{
OUTYY(("P(dnsc_dnscrypt_secret_key:%s)\n", $2));
if(!cfg_strlist_insert(&cfg_parser->cfg->dnscrypt_secret_key, $2))
fatal_exit("out of memory adding dnscrypt-secret-key");
}
;
%%
/* parse helper routines could be here */
static void
validate_respip_action(const char* action)
{
if(strcmp(action, "deny")!=0 &&
strcmp(action, "redirect")!=0 &&
strcmp(action, "inform")!=0 &&
strcmp(action, "inform_deny")!=0 &&
strcmp(action, "always_transparent")!=0 &&
strcmp(action, "always_refuse")!=0 &&
strcmp(action, "always_nxdomain")!=0)
{
yyerror("response-ip action: expected deny, redirect, "
"inform, inform_deny, always_transparent, "
"always_refuse or always_nxdomain");
}
}

View file

@ -256,11 +256,13 @@ dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
log_assert(len1 == len2 && len1 != 0);
/* compare labels */
while(len1--) {
if(tolower((unsigned char)*d1++) != tolower((unsigned char)*d2++)) {
if(tolower((unsigned char)d1[-1]) < tolower((unsigned char)d2[-1]))
if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
return -1;
return 1;
}
d1++;
d2++;
}
len1 = *d1++;
len2 = *d2++;
@ -268,8 +270,8 @@ dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
return 0;
}
hashvalue_t
dname_query_hash(uint8_t* dname, hashvalue_t h)
hashvalue_type
dname_query_hash(uint8_t* dname, hashvalue_type h)
{
uint8_t labuf[LDNS_MAX_LABELLEN+1];
uint8_t lablen;
@ -281,8 +283,10 @@ dname_query_hash(uint8_t* dname, hashvalue_t h)
log_assert(lablen <= LDNS_MAX_LABELLEN);
labuf[0] = lablen;
i=0;
while(lablen--)
labuf[++i] = (uint8_t)tolower((unsigned char)*dname++);
while(lablen--) {
labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
dname++;
}
h = hashlittle(labuf, labuf[0] + 1, h);
lablen = *dname++;
}
@ -290,8 +294,8 @@ dname_query_hash(uint8_t* dname, hashvalue_t h)
return h;
}
hashvalue_t
dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_t h)
hashvalue_type
dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)
{
uint8_t labuf[LDNS_MAX_LABELLEN+1];
uint8_t lablen;
@ -309,8 +313,10 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_t h)
log_assert(lablen <= LDNS_MAX_LABELLEN);
labuf[0] = lablen;
i=0;
while(lablen--)
labuf[++i] = (uint8_t)tolower((unsigned char)*dname++);
while(lablen--) {
labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
dname++;
}
h = hashlittle(labuf, labuf[0] + 1, h);
lablen = *dname++;
}

View file

@ -127,7 +127,7 @@ int dname_pkt_compare(struct sldns_buffer* pkt, uint8_t* d1, uint8_t* d2);
* @param h: initial hash value.
* @return: result hash value.
*/
hashvalue_t dname_query_hash(uint8_t* dname, hashvalue_t h);
hashvalue_type dname_query_hash(uint8_t* dname, hashvalue_type h);
/**
* Hash dname, label by label, lowercasing, into hashvalue.
@ -139,7 +139,8 @@ hashvalue_t dname_query_hash(uint8_t* dname, hashvalue_t h);
* @return: result hash value.
* Result is the same as dname_query_hash, even if compression is used.
*/
hashvalue_t dname_pkt_hash(struct sldns_buffer* pkt, uint8_t* dname, hashvalue_t h);
hashvalue_type dname_pkt_hash(struct sldns_buffer* pkt, uint8_t* dname,
hashvalue_type h);
/**
* Copy over a valid dname and decompress it.

View file

@ -48,6 +48,7 @@
#include "util/regional.h"
#include "util/net_help.h"
#include "sldns/sbuffer.h"
#include "services/localzone.h"
/** return code that means the function ran out of memory. negative so it does
* not conflict with DNS rcodes. */
@ -458,6 +459,10 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
owner_labs = dname_count_labels(key->rk.dname);
owner_pos = sldns_buffer_position(pkt);
/* For an rrset with a fixed TTL, use the rrset's TTL as given */
if((key->rk.flags & PACKED_RRSET_FIXEDTTL) != 0)
timenow = 0;
if(do_data) {
const sldns_rr_descriptor* c = type_rdata_compressable(key);
for(i=0; i<data->count; i++) {
@ -534,7 +539,11 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
{
int r;
size_t i, setstart;
*num_rrs = 0;
/* we now allow this function to be called multiple times for the
* same section, incrementally updating num_rrs. The caller is
* responsible for initializing it (which is the case in the current
* implementation). */
if(s != LDNS_SECTION_ADDITIONAL) {
if(s == LDNS_SECTION_ANSWER && qtype == LDNS_RR_TYPE_ANY)
dnssec = 1; /* include all types in ANY answer */
@ -581,17 +590,20 @@ static int
insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
sldns_buffer* buffer, struct regional* region)
{
uint8_t* qname = qinfo->local_alias ?
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
size_t qname_len = qinfo->local_alias ?
qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len;
if(sldns_buffer_remaining(buffer) <
qinfo->qname_len+sizeof(uint16_t)*2)
return RETVAL_TRUNC; /* buffer too small */
/* the query is the first name inserted into the tree */
if(!compress_tree_store(qinfo->qname,
dname_count_labels(qinfo->qname),
if(!compress_tree_store(qname, dname_count_labels(qname),
sldns_buffer_position(buffer), region, NULL, tree))
return RETVAL_OUTMEM;
if(sldns_buffer_current(buffer) == qinfo->qname)
sldns_buffer_skip(buffer, (ssize_t)qinfo->qname_len);
else sldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len);
if(sldns_buffer_current(buffer) == qname)
sldns_buffer_skip(buffer, (ssize_t)qname_len);
else sldns_buffer_write(buffer, qname, qname_len);
sldns_buffer_write_u16(buffer, qinfo->qtype);
sldns_buffer_write_u16(buffer, qinfo->qclass);
return RETVAL_OK;
@ -662,6 +674,33 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
* for different roundrobins for sequential id client senders. */
rr_offset = RRSET_ROUNDROBIN?ntohs(id):0;
/* "prepend" any local alias records in the answer section if this
* response is supposed to be authoritative. Currently it should
* be a single CNAME record (sanity-checked in worker_handle_request())
* but it can be extended if and when we support more variations of
* aliases. */
if(qinfo->local_alias && (flags & BIT_AA)) {
struct reply_info arep;
time_t timezero = 0; /* to use the 'authoritative' TTL */
memset(&arep, 0, sizeof(arep));
arep.flags = rep->flags;
arep.an_numrrsets = 1;
arep.rrset_count = 1;
arep.rrsets = &qinfo->local_alias->rrset;
if((r=insert_section(&arep, 1, &ancount, buffer, 0,
timezero, region, &tree, LDNS_SECTION_ANSWER,
qinfo->qtype, dnssec, rr_offset)) != RETVAL_OK) {
if(r == RETVAL_TRUNC) {
/* create truncated message */
sldns_buffer_write_u16_at(buffer, 6, ancount);
LDNS_TC_SET(sldns_buffer_begin(buffer));
sldns_buffer_flip(buffer);
return 1;
}
return 0;
}
}
/* insert answer section */
if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
@ -717,16 +756,23 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
uint16_t
calc_edns_field_size(struct edns_data* edns)
{
size_t rdatalen = 0;
struct edns_option* opt;
if(!edns || !edns->edns_present)
return 0;
/* domain root '.' + type + class + ttl + rdatalen(=0) */
return 1 + 2 + 2 + 4 + 2;
for(opt = edns->opt_list; opt; opt = opt->next) {
rdatalen += 4 + opt->opt_len;
}
/* domain root '.' + type + class + ttl + rdatalen */
return 1 + 2 + 2 + 4 + 2 + rdatalen;
}
void
attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
{
size_t len;
size_t rdatapos;
struct edns_option* opt;
if(!edns || !edns->edns_present)
return;
/* inc additional count */
@ -742,7 +788,18 @@ attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
sldns_buffer_write_u8(pkt, edns->ext_rcode); /* ttl */
sldns_buffer_write_u8(pkt, edns->edns_version);
sldns_buffer_write_u16(pkt, edns->bits);
rdatapos = sldns_buffer_position(pkt);
sldns_buffer_write_u16(pkt, 0); /* rdatalen */
/* write rdata */
for(opt=edns->opt_list; opt; opt=opt->next) {
sldns_buffer_write_u16(pkt, opt->opt_code);
sldns_buffer_write_u16(pkt, opt->opt_len);
if(opt->opt_len != 0)
sldns_buffer_write(pkt, opt->opt_data, opt->opt_len);
}
if(edns->opt_list)
sldns_buffer_write_u16_at(pkt, rdatapos,
sldns_buffer_position(pkt)-rdatapos-2);
sldns_buffer_flip(pkt);
}
@ -764,6 +821,15 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
}
if(secure && (dnssec || (qflags&BIT_AD)))
flags |= BIT_AD;
/* restore AA bit if we have a local alias and the response can be
* authoritative. Also clear AD bit if set as the local data is the
* primary answer. */
if(qinf->local_alias &&
(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR ||
FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN)) {
flags |= BIT_AA;
flags &= ~BIT_AD;
}
log_assert(flags & BIT_QR); /* QR bit must be on in our replies */
if(udpsize < LDNS_HEADER_SIZE)
return 0;
@ -789,13 +855,17 @@ void
qinfo_query_encode(sldns_buffer* pkt, struct query_info* qinfo)
{
uint16_t flags = 0; /* QUERY, NOERROR */
const uint8_t* qname = qinfo->local_alias ?
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
size_t qname_len = qinfo->local_alias ?
qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len;
sldns_buffer_clear(pkt);
log_assert(sldns_buffer_remaining(pkt) >= 12+255+4/*max query*/);
sldns_buffer_skip(pkt, 2); /* id done later */
sldns_buffer_write_u16(pkt, flags);
sldns_buffer_write_u16(pkt, 1); /* query count */
sldns_buffer_write(pkt, "\000\000\000\000\000\000", 6); /* counts */
sldns_buffer_write(pkt, qinfo->qname, qinfo->qname_len);
sldns_buffer_write(pkt, qname, qname_len);
sldns_buffer_write_u16(pkt, qinfo->qtype);
sldns_buffer_write_u16(pkt, qinfo->qclass);
sldns_buffer_flip(pkt);
@ -820,9 +890,14 @@ error_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
sldns_buffer_write(buf, &flags, sizeof(uint16_t));
sldns_buffer_write(buf, &flags, sizeof(uint16_t));
if(qinfo) {
if(sldns_buffer_current(buf) == qinfo->qname)
sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
const uint8_t* qname = qinfo->local_alias ?
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
size_t qname_len = qinfo->local_alias ?
qinfo->local_alias->rrset->rk.dname_len :
qinfo->qname_len;
if(sldns_buffer_current(buf) == qname)
sldns_buffer_skip(buf, (ssize_t)qname_len);
else sldns_buffer_write(buf, qname, qname_len);
sldns_buffer_write_u16(buf, qinfo->qtype);
sldns_buffer_write_u16(buf, qinfo->qclass);
}

View file

@ -38,6 +38,7 @@
*/
#include "config.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "util/data/dname.h"
#include "util/data/packed_rrset.h"
#include "util/storage/lookup3.h"
@ -70,7 +71,7 @@ smart_compare(sldns_buffer* pkt, uint8_t* dnow,
*/
static struct rrset_parse*
new_rrset(struct msg_parse* msg, uint8_t* dname, size_t dnamelen,
uint16_t type, uint16_t dclass, hashvalue_t hash,
uint16_t type, uint16_t dclass, hashvalue_type hash,
uint32_t rrset_flags, sldns_pkt_section section,
struct regional* region)
{
@ -158,13 +159,13 @@ pkt_rrset_flags(sldns_buffer* pkt, uint16_t type, sldns_pkt_section sec)
return f;
}
hashvalue_t
hashvalue_type
pkt_hash_rrset(sldns_buffer* pkt, uint8_t* dname, uint16_t type,
uint16_t dclass, uint32_t rrset_flags)
{
/* note this MUST be identical to rrset_key_hash in packed_rrset.c */
/* this routine handles compressed names */
hashvalue_t h = 0xab;
hashvalue_type h = 0xab;
h = dname_pkt_hash(pkt, dname, h);
h = hashlittle(&type, sizeof(type), h); /* host order */
h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */
@ -173,25 +174,25 @@ pkt_hash_rrset(sldns_buffer* pkt, uint8_t* dname, uint16_t type,
}
/** create partial dname hash for rrset hash */
static hashvalue_t
static hashvalue_type
pkt_hash_rrset_first(sldns_buffer* pkt, uint8_t* dname)
{
/* works together with pkt_hash_rrset_rest */
/* note this MUST be identical to rrset_key_hash in packed_rrset.c */
/* this routine handles compressed names */
hashvalue_t h = 0xab;
hashvalue_type h = 0xab;
h = dname_pkt_hash(pkt, dname, h);
return h;
}
/** create a rrset hash from a partial dname hash */
static hashvalue_t
pkt_hash_rrset_rest(hashvalue_t dname_h, uint16_t type, uint16_t dclass,
static hashvalue_type
pkt_hash_rrset_rest(hashvalue_type dname_h, uint16_t type, uint16_t dclass,
uint32_t rrset_flags)
{
/* works together with pkt_hash_rrset_first */
/* note this MUST be identical to rrset_key_hash in packed_rrset.c */
hashvalue_t h;
hashvalue_type h;
h = hashlittle(&type, sizeof(type), dname_h); /* host order */
h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */
h = hashlittle(&rrset_flags, sizeof(uint32_t), h);
@ -200,7 +201,7 @@ pkt_hash_rrset_rest(hashvalue_t dname_h, uint16_t type, uint16_t dclass,
/** compare rrset_parse with data */
static int
rrset_parse_equals(struct rrset_parse* p, sldns_buffer* pkt, hashvalue_t h,
rrset_parse_equals(struct rrset_parse* p, sldns_buffer* pkt, hashvalue_type h,
uint32_t rrset_flags, uint8_t* dname, size_t dnamelen,
uint16_t type, uint16_t dclass)
{
@ -214,8 +215,8 @@ rrset_parse_equals(struct rrset_parse* p, sldns_buffer* pkt, hashvalue_t h,
struct rrset_parse*
msgparse_hashtable_lookup(struct msg_parse* msg, sldns_buffer* pkt,
hashvalue_t h, uint32_t rrset_flags, uint8_t* dname, size_t dnamelen,
uint16_t type, uint16_t dclass)
hashvalue_type h, uint32_t rrset_flags, uint8_t* dname,
size_t dnamelen, uint16_t type, uint16_t dclass)
{
struct rrset_parse* p = msg->hashtable[h & (PARSE_TABLE_SIZE-1)];
while(p) {
@ -387,7 +388,7 @@ change_rrsig_rrset(struct rrset_parse* sigset, struct msg_parse* msg,
int hasother, sldns_pkt_section section, struct regional* region)
{
struct rrset_parse* dataset = sigset;
hashvalue_t hash = pkt_hash_rrset(pkt, sigset->dname, datatype,
hashvalue_type hash = pkt_hash_rrset(pkt, sigset->dname, datatype,
sigset->rrset_class, rrset_flags);
log_assert( sigset->type == LDNS_RR_TYPE_RRSIG );
log_assert( datatype != LDNS_RR_TYPE_RRSIG );
@ -454,14 +455,14 @@ change_rrsig_rrset(struct rrset_parse* sigset, struct msg_parse* msg,
*/
static int
find_rrset(struct msg_parse* msg, sldns_buffer* pkt, uint8_t* dname,
size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_t* hash,
size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_type* hash,
uint32_t* rrset_flags,
uint8_t** prev_dname_first, uint8_t** prev_dname_last,
size_t* prev_dnamelen, uint16_t* prev_type,
uint16_t* prev_dclass, struct rrset_parse** rrset_prev,
sldns_pkt_section section, struct regional* region)
{
hashvalue_t dname_h = pkt_hash_rrset_first(pkt, dname);
hashvalue_type dname_h = pkt_hash_rrset_first(pkt, dname);
uint16_t covtype;
if(*rrset_prev) {
/* check if equal to previous item */
@ -823,7 +824,7 @@ parse_section(sldns_buffer* pkt, struct msg_parse* msg,
uint16_t type, prev_type = 0;
uint16_t dclass, prev_dclass = 0;
uint32_t rrset_flags = 0;
hashvalue_t hash = 0;
hashvalue_type hash = 0;
struct rrset_parse* rrset = NULL;
int r;
@ -933,13 +934,41 @@ parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region)
return 0;
}
/** parse EDNS options from EDNS wireformat rdata */
static int
parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len,
struct edns_data* edns, struct regional* region)
{
/* while still more options, and have code+len to read */
/* ignores partial content (i.e. rdata len 3) */
while(rdata_len >= 4) {
uint16_t opt_code = sldns_read_uint16(rdata_ptr);
uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
rdata_ptr += 4;
rdata_len -= 4;
if(opt_len > rdata_len)
break; /* option code partial */
if(!edns_opt_append(edns, region, opt_code, opt_len,
rdata_ptr)) {
log_err("out of memory");
return 0;
}
rdata_ptr += opt_len;
rdata_len -= opt_len;
}
return 1;
}
int
parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
struct regional* region)
{
struct rrset_parse* rrset = msg->rrset_first;
struct rrset_parse* prev = 0;
struct rrset_parse* found = 0;
struct rrset_parse* found_prev = 0;
size_t rdata_len;
uint8_t* rdata_ptr;
/* since the class encodes the UDP size, we cannot use hash table to
* find the EDNS OPT record. Scan the packet. */
while(rrset) {
@ -986,13 +1015,25 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
edns->edns_version = found->rr_last->ttl_data[1];
edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]);
edns->udp_size = ntohs(found->rrset_class);
/* ignore rdata and rrsigs */
edns->opt_list = NULL;
/* take the options */
rdata_len = found->rr_first->size;
rdata_ptr = found->rr_first->ttl_data+6;
if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
return 0;
/* ignore rrsigs */
return 0;
}
int
parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns)
parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
struct regional* region)
{
size_t rdata_len;
uint8_t* rdata_ptr;
log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
log_assert(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0);
log_assert(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) == 0);
@ -1017,6 +1058,36 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns)
edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */
edns->edns_version = sldns_buffer_read_u8(pkt);
edns->bits = sldns_buffer_read_u16(pkt);
/* ignore rdata and rrsigs */
edns->opt_list = NULL;
/* take the options */
rdata_len = sldns_buffer_read_u16(pkt);
if(sldns_buffer_remaining(pkt) < rdata_len)
return LDNS_RCODE_FORMERR;
rdata_ptr = sldns_buffer_current(pkt);
if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
return LDNS_RCODE_SERVFAIL;
/* ignore rrsigs */
return 0;
}
void
log_edns_opt_list(enum verbosity_value level, const char* info_str,
struct edns_option* list)
{
if(verbosity >= level && list) {
char str[128], *s;
size_t slen;
verbose(level, "%s", info_str);
while(list) {
s = str;
slen = sizeof(str);
(void)sldns_wire2str_edns_option_print(&s, &slen, list->opt_code,
list->opt_data, list->opt_len);
verbose(level, " %s", str);
list = list->next;
}
}
}

View file

@ -69,6 +69,7 @@ struct sldns_buffer;
struct rrset_parse;
struct rr_parse;
struct regional;
struct edns_option;
/** number of buckets in parse rrset hash table. Must be power of 2. */
#define PARSE_TABLE_SIZE 32
@ -137,7 +138,7 @@ struct rrset_parse {
/** next in list of all rrsets */
struct rrset_parse* rrset_all_next;
/** hash value of rrset */
hashvalue_t hash;
hashvalue_type hash;
/** which section was it found in: one of
* LDNS_SECTION_ANSWER, LDNS_SECTION_AUTHORITY, LDNS_SECTION_ADDITIONAL
*/
@ -202,7 +203,8 @@ struct rr_parse {
/**
* EDNS data storage
* EDNS rdata is ignored.
* rdata is parsed in a list (has accessor functions). allocated in a
* region.
*/
struct edns_data {
/** if EDNS OPT record was present */
@ -215,6 +217,22 @@ struct edns_data {
uint16_t bits;
/** UDP reassembly size. */
uint16_t udp_size;
/** rdata element list, or NULL if none */
struct edns_option* opt_list;
};
/**
* EDNS option
*/
struct edns_option {
/** next item in list */
struct edns_option* next;
/** type of this edns option */
uint16_t opt_code;
/** length of this edns option (cannot exceed uint16 in encoding) */
size_t opt_len;
/** data of this edns option; allocated in region, or NULL if len=0 */
uint8_t* opt_data;
};
/**
@ -249,10 +267,12 @@ int parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg,
* @param msg: parsed message structure. Modified on exit, if EDNS was present
* it is removed from the additional section.
* @param edns: the edns data is stored here. Does not have to be initialised.
* @param region: region to alloc results in (edns option contents)
* @return: 0 on success. or an RCODE on an error.
* RCODE formerr if OPT in wrong section, and so on.
*/
int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns);
int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
struct regional* region);
/**
* If EDNS data follows a query section, extract it and initialize edns struct.
@ -260,10 +280,12 @@ int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns);
* section. At end, right after EDNS data or no movement if failed.
* @param edns: the edns data allocated by the caller. Does not have to be
* initialised.
* @param region: region to alloc results in (edns option contents)
* @return: 0 on success, or an RCODE on error.
* RCODE formerr if OPT is badly formatted and so on.
*/
int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns);
int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
struct regional* region);
/**
* Calculate hash value for rrset in packet.
@ -274,8 +296,8 @@ int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns);
* @param rrset_flags: rrset flags (same as packed_rrset flags).
* @return hash value
*/
hashvalue_t pkt_hash_rrset(struct sldns_buffer* pkt, uint8_t* dname, uint16_t type,
uint16_t dclass, uint32_t rrset_flags);
hashvalue_type pkt_hash_rrset(struct sldns_buffer* pkt, uint8_t* dname,
uint16_t type, uint16_t dclass, uint32_t rrset_flags);
/**
* Lookup in msg hashtable to find a rrset.
@ -290,7 +312,7 @@ hashvalue_t pkt_hash_rrset(struct sldns_buffer* pkt, uint8_t* dname, uint16_t ty
* @return NULL or the rrset_parse if found.
*/
struct rrset_parse* msgparse_hashtable_lookup(struct msg_parse* msg,
struct sldns_buffer* pkt, hashvalue_t h, uint32_t rrset_flags,
struct sldns_buffer* pkt, hashvalue_type h, uint32_t rrset_flags,
uint8_t* dname, size_t dnamelen, uint16_t type, uint16_t dclass);
/**
@ -300,4 +322,13 @@ struct rrset_parse* msgparse_hashtable_lookup(struct msg_parse* msg,
*/
void msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset);
/**
* Log the edns options in the edns option list.
* @param level: the verbosity level.
* @param info_str: the informational string to be printed before the options.
* @param list: the edns option list.
*/
void log_edns_opt_list(enum verbosity_value level, const char* info_str,
struct edns_option* list);
#endif /* UTIL_DATA_MSGPARSE_H */

View file

@ -52,6 +52,8 @@
#include "util/data/msgencode.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "util/module.h"
#include "util/fptr_wlist.h"
/** MAX TTL default for messages and rrsets */
time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
@ -76,6 +78,7 @@ parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg,
qinf->qname_len = msg->qname_len;
qinf->qtype = msg->qtype;
qinf->qclass = msg->qclass;
qinf->local_alias = NULL;
return 1;
}
@ -130,9 +133,8 @@ parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep,
return 1;
}
/** allocate (special) rrset keys, return 0 on error */
static int
repinfo_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc,
int
reply_info_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc,
struct regional* region)
{
size_t i;
@ -435,7 +437,7 @@ parse_create_msg(sldns_buffer* pkt, struct msg_parse* msg,
return 0;
if(!parse_create_repinfo(msg, rep, region))
return 0;
if(!repinfo_alloc_rrset_keys(*rep, alloc, region))
if(!reply_info_alloc_rrset_keys(*rep, alloc, region))
return 0;
if(!parse_copy_decompress(pkt, msg, *rep, region))
return 0;
@ -451,6 +453,7 @@ int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
int ret;
qinf->qname = NULL;
qinf->local_alias = NULL;
*rep = NULL;
if(!(msg = regional_alloc(region, sizeof(*msg)))) {
return LDNS_RCODE_SERVFAIL;
@ -461,7 +464,7 @@ int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
if((ret = parse_packet(pkt, msg, region)) != 0) {
return ret;
}
if((ret = parse_extract_edns(msg, edns)) != 0)
if((ret = parse_extract_edns(msg, edns, region)) != 0)
return ret;
/* parse OK, allocate return structures */
@ -542,6 +545,7 @@ query_info_parse(struct query_info* m, sldns_buffer* query)
return 0; /* need qtype, qclass */
m->qtype = sldns_buffer_read_u16(query);
m->qclass = sldns_buffer_read_u16(query);
m->local_alias = NULL;
return 1;
}
@ -603,10 +607,10 @@ reply_info_delete(void* d, void* ATTR_UNUSED(arg))
free(r);
}
hashvalue_t
hashvalue_type
query_info_hash(struct query_info *q, uint16_t flags)
{
hashvalue_t h = 0xab;
hashvalue_type h = 0xab;
h = hashlittle(&q->qtype, sizeof(q->qtype), h);
if(q->qtype == LDNS_RR_TYPE_AAAA && (flags&BIT_CD))
h++;
@ -617,7 +621,7 @@ query_info_hash(struct query_info *q, uint16_t flags)
struct msgreply_entry*
query_info_entrysetup(struct query_info* q, struct reply_info* r,
hashvalue_t h)
hashvalue_type h)
{
struct msgreply_entry* e = (struct msgreply_entry*)malloc(
sizeof(struct msgreply_entry));
@ -683,7 +687,7 @@ reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc,
if(!cp)
return NULL;
/* allocate ub_key structures special or not */
if(!repinfo_alloc_rrset_keys(cp, alloc, region)) {
if(!reply_info_alloc_rrset_keys(cp, alloc, region)) {
if(!region)
reply_info_parsedelete(cp, alloc);
return NULL;
@ -814,7 +818,39 @@ log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
regional_destroy(region);
}
void
void
log_reply_info(enum verbosity_value v, struct query_info *qinf,
struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur,
int cached, struct sldns_buffer *rmsg)
{
char qname_buf[LDNS_MAX_DOMAINLEN+1];
char clientip_buf[128];
char rcode_buf[16];
char type_buf[16];
char class_buf[16];
size_t pktlen;
uint16_t rcode = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(rmsg, 2));
if(verbosity < v)
return;
sldns_wire2str_rcode_buf((int)rcode, rcode_buf, sizeof(rcode_buf));
addr_to_str(addr, addrlen, clientip_buf, sizeof(clientip_buf));
if(rcode == LDNS_RCODE_FORMERR)
{
log_info("%s - - - %s - - - ", clientip_buf, rcode_buf);
} else {
dname_str(qinf->qname, qname_buf);
pktlen = sldns_buffer_limit(rmsg);
sldns_wire2str_type_buf(qinf->qtype, type_buf, sizeof(type_buf));
sldns_wire2str_class_buf(qinf->qclass, class_buf, sizeof(class_buf));
log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",
clientip_buf, qname_buf, type_buf, class_buf,
rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen);
}
}
void
log_query_info(enum verbosity_value v, const char* str,
struct query_info* qinf)
{
@ -857,3 +893,314 @@ reply_all_rrsets_secure(struct reply_info* rep)
}
return 1;
}
int edns_opt_append(struct edns_data* edns, struct regional* region,
uint16_t code, size_t len, uint8_t* data)
{
struct edns_option** prevp;
struct edns_option* opt;
/* allocate new element */
opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
if(!opt)
return 0;
opt->next = NULL;
opt->opt_code = code;
opt->opt_len = len;
opt->opt_data = NULL;
if(len > 0) {
opt->opt_data = regional_alloc_init(region, data, len);
if(!opt->opt_data)
return 0;
}
/* append at end of list */
prevp = &edns->opt_list;
while(*prevp != NULL)
prevp = &((*prevp)->next);
*prevp = opt;
return 1;
}
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
uint8_t* data, struct regional* region)
{
struct edns_option** prevp;
struct edns_option* opt;
/* allocate new element */
opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
if(!opt)
return 0;
opt->next = NULL;
opt->opt_code = code;
opt->opt_len = len;
opt->opt_data = NULL;
if(len > 0) {
opt->opt_data = regional_alloc_init(region, data, len);
if(!opt->opt_data)
return 0;
}
/* append at end of list */
prevp = list;
while(*prevp != NULL) {
prevp = &((*prevp)->next);
}
*prevp = opt;
return 1;
}
int edns_opt_list_remove(struct edns_option** list, uint16_t code)
{
/* The list should already be allocated in a region. Freeing the
* allocated space in a region is not possible. We just unlink the
* required elements and they will be freed together with the region. */
struct edns_option* prev;
struct edns_option* curr;
if(!list || !(*list)) return 0;
/* Unlink and repoint if the element(s) are first in list */
while(list && *list && (*list)->opt_code == code) {
*list = (*list)->next;
}
if(!list || !(*list)) return 1;
/* Unlink elements and reattach the list */
prev = *list;
curr = (*list)->next;
while(curr != NULL) {
if(curr->opt_code == code) {
prev->next = curr->next;
curr = curr->next;
} else {
prev = curr;
curr = curr->next;
}
}
return 1;
}
static int inplace_cb_reply_call_generic(
struct inplace_cb* callback_list, enum inplace_cb_list_type type,
struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns,
struct regional* region)
{
struct inplace_cb* cb;
struct edns_option* opt_list_out = NULL;
if(qstate)
opt_list_out = qstate->edns_opts_front_out;
for(cb=callback_list; cb; cb=cb->next) {
fptr_ok(fptr_whitelist_inplace_cb_reply_generic(
(inplace_cb_reply_func_type*)cb->cb, type));
(void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep,
rcode, edns, &opt_list_out, region, cb->id, cb->cb_arg);
}
edns->opt_list = opt_list_out;
return 1;
}
int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
struct module_qstate* qstate, struct reply_info* rep, int rcode,
struct edns_data* edns, struct regional* region)
{
return inplace_cb_reply_call_generic(
env->inplace_cb_lists[inplace_cb_reply], inplace_cb_reply, qinfo,
qstate, rep, rcode, edns, region);
}
int inplace_cb_reply_cache_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns,
struct regional* region)
{
return inplace_cb_reply_call_generic(
env->inplace_cb_lists[inplace_cb_reply_cache], inplace_cb_reply_cache,
qinfo, qstate, rep, rcode, edns, region);
}
int inplace_cb_reply_local_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns,
struct regional* region)
{
return inplace_cb_reply_call_generic(
env->inplace_cb_lists[inplace_cb_reply_local], inplace_cb_reply_local,
qinfo, qstate, rep, rcode, edns, region);
}
int inplace_cb_reply_servfail_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns,
struct regional* region)
{
/* We are going to servfail. Remove any potential edns options. */
if(qstate)
qstate->edns_opts_front_out = NULL;
return inplace_cb_reply_call_generic(
env->inplace_cb_lists[inplace_cb_reply_servfail],
inplace_cb_reply_servfail, qinfo, qstate, rep, rcode, edns, region);
}
int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
struct regional* region)
{
struct inplace_cb* cb = env->inplace_cb_lists[inplace_cb_query];
for(; cb; cb=cb->next) {
fptr_ok(fptr_whitelist_inplace_cb_query(
(inplace_cb_query_func_type*)cb->cb));
(void)(*(inplace_cb_query_func_type*)cb->cb)(qinfo, flags,
qstate, addr, addrlen, zone, zonelen, region,
cb->id, cb->cb_arg);
}
return 1;
}
int inplace_cb_edns_back_parsed_call(struct module_env* env,
struct module_qstate* qstate)
{
struct inplace_cb* cb =
env->inplace_cb_lists[inplace_cb_edns_back_parsed];
for(; cb; cb=cb->next) {
fptr_ok(fptr_whitelist_inplace_cb_edns_back_parsed(
(inplace_cb_edns_back_parsed_func_type*)cb->cb));
(void)(*(inplace_cb_edns_back_parsed_func_type*)cb->cb)(qstate,
cb->id, cb->cb_arg);
}
return 1;
}
int inplace_cb_query_response_call(struct module_env* env,
struct module_qstate* qstate, struct dns_msg* response) {
struct inplace_cb* cb =
env->inplace_cb_lists[inplace_cb_query_response];
for(; cb; cb=cb->next) {
fptr_ok(fptr_whitelist_inplace_cb_query_response(
(inplace_cb_query_response_func_type*)cb->cb));
(void)(*(inplace_cb_query_response_func_type*)cb->cb)(qstate,
response, cb->id, cb->cb_arg);
}
return 1;
}
struct edns_option* edns_opt_copy_region(struct edns_option* list,
struct regional* region)
{
struct edns_option* result = NULL, *cur = NULL, *s;
while(list) {
/* copy edns option structure */
s = regional_alloc_init(region, list, sizeof(*list));
if(!s) return NULL;
s->next = NULL;
/* copy option data */
if(s->opt_data) {
s->opt_data = regional_alloc_init(region, s->opt_data,
s->opt_len);
if(!s->opt_data)
return NULL;
}
/* link into list */
if(cur)
cur->next = s;
else result = s;
cur = s;
/* examine next element */
list = list->next;
}
return result;
}
int edns_opt_compare(struct edns_option* p, struct edns_option* q)
{
if(!p && !q) return 0;
if(!p) return -1;
if(!q) return 1;
log_assert(p && q);
if(p->opt_code != q->opt_code)
return (int)q->opt_code - (int)p->opt_code;
if(p->opt_len != q->opt_len)
return (int)q->opt_len - (int)p->opt_len;
if(p->opt_len != 0)
return memcmp(p->opt_data, q->opt_data, p->opt_len);
return 0;
}
int edns_opt_list_compare(struct edns_option* p, struct edns_option* q)
{
int r;
while(p && q) {
r = edns_opt_compare(p, q);
if(r != 0)
return r;
p = p->next;
q = q->next;
}
if(p || q) {
/* uneven length lists */
if(p) return 1;
if(q) return -1;
}
return 0;
}
void edns_opt_list_free(struct edns_option* list)
{
struct edns_option* n;
while(list) {
free(list->opt_data);
n = list->next;
free(list);
list = n;
}
}
struct edns_option* edns_opt_copy_alloc(struct edns_option* list)
{
struct edns_option* result = NULL, *cur = NULL, *s;
while(list) {
/* copy edns option structure */
s = memdup(list, sizeof(*list));
if(!s) {
edns_opt_list_free(result);
return NULL;
}
s->next = NULL;
/* copy option data */
if(s->opt_data) {
s->opt_data = memdup(s->opt_data, s->opt_len);
if(!s->opt_data) {
free(s);
edns_opt_list_free(result);
return NULL;
}
}
/* link into list */
if(cur)
cur->next = s;
else result = s;
cur = s;
/* examine next element */
list = list->next;
}
return result;
}
struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code)
{
struct edns_option* p;
for(p=list; p; p=p->next) {
if(p->opt_code == code)
return p;
}
return NULL;
}

View file

@ -49,8 +49,14 @@ struct alloc_cache;
struct iovec;
struct regional;
struct edns_data;
struct edns_option;
struct inplace_cb;
struct module_qstate;
struct module_env;
struct msg_parse;
struct rrset_parse;
struct local_rrset;
struct dns_msg;
/** calculate the prefetch TTL as 90% of original. Calculation
* without numerical overflow (uin32_t) */
@ -73,6 +79,23 @@ struct query_info {
uint16_t qtype;
/** qclass, host byte order */
uint16_t qclass;
/**
* Alias local answer(s) for the qname. If 'qname' is an alias defined
* in a local zone, this field will be set to the corresponding local
* RRset when the alias is determined.
* In the initial implementation this can only be a single CNAME RR
* (or NULL), but it could possibly be extended to be a DNAME or a
* chain of aliases.
* Users of this structure are responsible to initialize this field
* to be NULL; otherwise other part of query handling code may be
* confused.
* Users also have to be careful about the lifetime of data. On return
* from local zone lookup, it may point to data derived from
* configuration that may be dynamically invalidated or data allocated
* in an ephemeral regional allocator. A deep copy of the data may
* have to be generated if it has to be kept during iterative
* resolution. */
struct local_rrset* local_alias;
};
/**
@ -82,7 +105,7 @@ struct rrset_ref {
/** the key with lock, and ptr to packed data. */
struct ub_packed_rrset_key* key;
/** id needed */
rrset_id_t id;
rrset_id_type id;
};
/**
@ -307,7 +330,7 @@ void reply_info_delete(void* d, void* arg);
/** calculate hash value of query_info, lowercases the qname,
* uses CD flag for AAAA qtype */
hashvalue_t query_info_hash(struct query_info *q, uint16_t flags);
hashvalue_type query_info_hash(struct query_info *q, uint16_t flags);
/**
* Setup query info entry
@ -317,7 +340,7 @@ hashvalue_t query_info_hash(struct query_info *q, uint16_t flags);
* @return: newly allocated message reply cache item.
*/
struct msgreply_entry* query_info_entrysetup(struct query_info* q,
struct reply_info* r, hashvalue_t h);
struct reply_info* r, hashvalue_type h);
/**
* Copy reply_info and all rrsets in it and allocate.
@ -333,6 +356,21 @@ struct msgreply_entry* query_info_entrysetup(struct query_info* q,
struct reply_info* reply_info_copy(struct reply_info* rep,
struct alloc_cache* alloc, struct regional* region);
/**
* Allocate (special) rrset keys.
* @param rep: reply info in which the rrset keys to be allocated, rrset[]
* array should have bee allocated with NULL pointers.
* @param alloc: how to allocate rrset keys.
* Not used if region!=NULL, it can be NULL in that case.
* @param region: if this parameter is NULL then the alloc is used.
* otherwise, rrset keys are allocated in this region.
* In a region, no special rrset key structures are needed (not shared).
* and no rrset_ref array in the reply needs to be built up.
* @return 1 on success, 0 on error
*/
int reply_info_alloc_rrset_keys(struct reply_info* rep,
struct alloc_cache* alloc, struct regional* region);
/**
* Copy a parsed rrset into given key, decompressing and allocating rdata.
* @param pkt: packet for decompression
@ -425,9 +463,26 @@ struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep,
* @param qinfo: query section.
* @param rep: rest of message.
*/
void log_dns_msg(const char* str, struct query_info* qinfo,
void log_dns_msg(const char* str, struct query_info* qinfo,
struct reply_info* rep);
/**
* Print string with neat domain name, type, class,
* status code from, and size of a query response.
*
* @param v: at what verbosity level to print this.
* @param qinf: query section.
* @param addr: address of the client.
* @param addrlen: length of the client address.
* @param dur: how long it took to complete the query.
* @param cached: whether or not the reply is coming from
* the cache, or an outside network.
* @param rmsg: sldns buffer packet.
*/
void log_reply_info(enum verbosity_value v, struct query_info *qinf,
struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur,
int cached, struct sldns_buffer *rmsg);
/**
* Print string with neat domain name, type, class from query info.
* @param v: at what verbosity level to print this.
@ -437,4 +492,183 @@ void log_dns_msg(const char* str, struct query_info* qinfo,
void log_query_info(enum verbosity_value v, const char* str,
struct query_info* qinf);
/**
* Append edns option to edns data structure
* @param edns: the edns data structure to append the edns option to.
* @param region: region to allocate the new edns option.
* @param code: the edns option's code.
* @param len: the edns option's length.
* @param data: the edns option's data.
* @return false on failure.
*/
int edns_opt_append(struct edns_data* edns, struct regional* region,
uint16_t code, size_t len, uint8_t* data);
/**
* Append edns option to edns option list
* @param list: the edns option list to append the edns option to.
* @param code: the edns option's code.
* @param len: the edns option's length.
* @param data: the edns option's data.
* @param region: region to allocate the new edns option.
* @return false on failure.
*/
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
uint8_t* data, struct regional* region);
/**
* Remove any option found on the edns option list that matches the code.
* @param list: the list of edns options.
* @param code: the opt code to remove.
* @return true when at least one edns option was removed, false otherwise.
*/
int edns_opt_list_remove(struct edns_option** list, uint16_t code);
/**
* Find edns option in edns list
* @param list: list of edns options (eg. edns.opt_list)
* @param code: opt code to find.
* @return NULL or the edns_option element.
*/
struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code);
/**
* Call the registered functions in the inplace_cb_reply linked list.
* This function is going to get called while answering with a resolved query.
* @param env: module environment.
* @param qinfo: query info.
* @param qstate: module qstate.
* @param rep: Reply info. Could be NULL.
* @param rcode: return code.
* @param edns: edns data of the reply.
* @param region: region to store data.
* @return false on failure (a callback function returned an error).
*/
int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
struct module_qstate* qstate, struct reply_info* rep, int rcode,
struct edns_data* edns, struct regional* region);
/**
* Call the registered functions in the inplace_cb_reply_cache linked list.
* This function is going to get called while answering from cache.
* @param env: module environment.
* @param qinfo: query info.
* @param qstate: module qstate. NULL when replying from cache.
* @param rep: Reply info.
* @param rcode: return code.
* @param edns: edns data of the reply. Edns input can be found here.
* @param region: region to store data.
* @return false on failure (a callback function returned an error).
*/
int inplace_cb_reply_cache_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns,
struct regional* region);
/**
* Call the registered functions in the inplace_cb_reply_local linked list.
* This function is going to get called while answering with local data.
* @param env: module environment.
* @param qinfo: query info.
* @param qstate: module qstate. NULL when replying from cache.
* @param rep: Reply info.
* @param rcode: return code.
* @param edns: edns data of the reply. Edns input can be found here.
* @param region: region to store data.
* @return false on failure (a callback function returned an error).
*/
int inplace_cb_reply_local_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns,
struct regional* region);
/**
* Call the registered functions in the inplace_cb_reply linked list.
* This function is going to get called while answering with a servfail.
* @param env: module environment.
* @param qinfo: query info.
* @param qstate: module qstate. Contains the edns option lists. Could be NULL.
* @param rep: Reply info. NULL when servfail.
* @param rcode: return code. LDNS_RCODE_SERVFAIL.
* @param edns: edns data of the reply. Edns input can be found here if qstate
* is NULL.
* @param region: region to store data.
* @return false on failure (a callback function returned an error).
*/
int inplace_cb_reply_servfail_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns,
struct regional* region);
/**
* Call the registered functions in the inplace_cb_query linked list.
* This function is going to get called just before sending a query to a
* nameserver.
* @param env: module environment.
* @param qinfo: query info.
* @param flags: flags of the query.
* @param addr: to which server to send the query.
* @param addrlen: length of addr.
* @param zone: name of the zone of the delegation point. wireformat dname.
* This is the delegation point name for which the server is deemed
* authoritative.
* @param zonelen: length of zone.
* @param qstate: module qstate.
* @param region: region to store data.
* @return false on failure (a callback function returned an error).
*/
int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
struct regional* region);
/**
* Call the registered functions in the inplace_cb_edns_back_parsed linked list.
* This function is going to get called after parsing the EDNS data on the
* reply from a nameserver.
* @param env: module environment.
* @param qstate: module qstate.
* @return false on failure (a callback function returned an error).
*/
int inplace_cb_edns_back_parsed_call(struct module_env* env,
struct module_qstate* qstate);
/**
* Call the registered functions in the inplace_cb_query_reponse linked list.
* This function is going to get called after receiving a reply from a
* nameserver.
* @param env: module environment.
* @param qstate: module qstate.
* @param response: received response
* @return false on failure (a callback function returned an error).
*/
int inplace_cb_query_response_call(struct module_env* env,
struct module_qstate* qstate, struct dns_msg* response);
/**
* Copy edns option list allocated to the new region
*/
struct edns_option* edns_opt_copy_region(struct edns_option* list,
struct regional* region);
/**
* Copy edns option list allocated with malloc
*/
struct edns_option* edns_opt_copy_alloc(struct edns_option* list);
/**
* Free edns option list allocated with malloc
*/
void edns_opt_list_free(struct edns_option* list);
/**
* Compare an edns option. (not entire list). Also compares contents.
*/
int edns_opt_compare(struct edns_option* p, struct edns_option* q);
/**
* Compare edns option lists, also the order and contents of edns-options.
*/
int edns_opt_list_compare(struct edns_option* p, struct edns_option* q);
#endif /* UTIL_DATA_MSGREPLY_H */

View file

@ -158,14 +158,14 @@ rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2)
return 1;
}
hashvalue_t
hashvalue_type
rrset_key_hash(struct packed_rrset_key* key)
{
/* type is hashed in host order */
uint16_t t = ntohs(key->type);
/* Note this MUST be identical to pkt_hash_rrset in msgparse.c */
/* this routine does not have a compressed name */
hashvalue_t h = 0xab;
hashvalue_type h = 0xab;
h = dname_query_hash(key->dname, h);
h = hashlittle(&t, sizeof(t), h);
h = hashlittle(&key->rrset_class, sizeof(uint16_t), h);

View file

@ -47,7 +47,7 @@ struct regional;
/** type used to uniquely identify rrsets. Cannot be reused without
* clearing the cache. */
typedef uint64_t rrset_id_t;
typedef uint64_t rrset_id_type;
/** this rrset is NSEC and is at zone apex (at child side of zonecut) */
#define PACKED_RRSET_NSEC_AT_APEX 0x1
@ -57,6 +57,10 @@ typedef uint64_t rrset_id_t;
* this is set on SOA rrsets in the authority section, to keep its TTL separate
* from the SOA in the answer section from a direct SOA query or ANY query. */
#define PACKED_RRSET_SOA_NEG 0x4
/** This rrset is considered to have a fixed TTL; its TTL doesn't have to be
* updated on encoding in a reply. This flag is not expected to be set in
* cached data. */
#define PACKED_RRSET_FIXEDTTL 0x80000000
/** number of rrs and rrsets for integer overflow protection. More than
* this is not really possible (64K packet has much less RRs and RRsets) in
@ -83,6 +87,7 @@ struct packed_rrset_key {
* o PACKED_RRSET_NSEC_AT_APEX
* o PACKED_RRSET_PARENT_SIDE
* o PACKED_RRSET_SOA_NEG
* o PACKED_RRSET_FIXEDTTL (not supposed to be cached)
*/
uint32_t flags;
/** the rrset type in network format */
@ -114,7 +119,7 @@ struct ub_packed_rrset_key {
* The other values in this struct may only be altered after changing
* the id (which needs a writelock on entry.lock).
*/
rrset_id_t id;
rrset_id_type id;
/** key data: dname, type and class */
struct packed_rrset_key rk;
};
@ -191,6 +196,12 @@ enum sec_status {
* RRset data.
*
* The data is packed, stored contiguously in memory.
*
* It is not always stored contiguously, in that case, an unpacked-packed
* rrset has the arrays separate. A bunch of routines work on that, but
* the packed rrset that is contiguous is for the rrset-cache and the
* cache-response routines in daemon/worker.c.
*
* memory layout:
* o base struct
* o rr_len size_t array
@ -334,7 +345,7 @@ void rrset_data_delete(void* data, void* userdata);
* @param key: the rrset key with name, type, class, flags.
* @return hash value.
*/
hashvalue_t rrset_key_hash(struct packed_rrset_key* key);
hashvalue_type rrset_key_hash(struct packed_rrset_key* key);
/**
* Fixup pointers in fixed data packed_rrset_data blob.

View file

@ -51,6 +51,7 @@
#include "services/localzone.h"
#include "services/cache/infra.h"
#include "services/cache/rrset.h"
#include "services/view.h"
#include "dns64/dns64.h"
#include "iterator/iterator.h"
#include "iterator/iter_fwd.h"
@ -74,13 +75,20 @@
#ifdef UB_ON_WINDOWS
#include "winrc/win_svc.h"
#endif
#include "respip/respip.h"
#ifdef WITH_PYTHONMODULE
#include "pythonmod/pythonmod.h"
#endif
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
#ifdef CLIENT_SUBNET
#include "edns-subnet/subnetmod.h"
#endif
int
fptr_whitelist_comm_point(comm_point_callback_t *fptr)
fptr_whitelist_comm_point(comm_point_callback_type *fptr)
{
if(fptr == &worker_handle_request) return 1;
else if(fptr == &outnet_udp_cb) return 1;
@ -90,7 +98,7 @@ fptr_whitelist_comm_point(comm_point_callback_t *fptr)
}
int
fptr_whitelist_comm_point_raw(comm_point_callback_t *fptr)
fptr_whitelist_comm_point_raw(comm_point_callback_type *fptr)
{
if(fptr == &tube_handle_listen) return 1;
else if(fptr == &tube_handle_write) return 1;
@ -152,7 +160,7 @@ fptr_whitelist_event(void (*fptr)(int, short, void *))
}
int
fptr_whitelist_pending_udp(comm_point_callback_t *fptr)
fptr_whitelist_pending_udp(comm_point_callback_type *fptr)
{
if(fptr == &serviced_udp_callback) return 1;
else if(fptr == &worker_handle_reply) return 1;
@ -161,7 +169,7 @@ fptr_whitelist_pending_udp(comm_point_callback_t *fptr)
}
int
fptr_whitelist_pending_tcp(comm_point_callback_t *fptr)
fptr_whitelist_pending_tcp(comm_point_callback_type *fptr)
{
if(fptr == &serviced_tcp_callback) return 1;
else if(fptr == &worker_handle_reply) return 1;
@ -170,7 +178,7 @@ fptr_whitelist_pending_tcp(comm_point_callback_t *fptr)
}
int
fptr_whitelist_serviced_query(comm_point_callback_t *fptr)
fptr_whitelist_serviced_query(comm_point_callback_type *fptr)
{
if(fptr == &worker_handle_service_reply) return 1;
else if(fptr == &libworker_handle_service_reply) return 1;
@ -200,47 +208,54 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
else if(fptr == &val_neg_zone_compare) return 1;
else if(fptr == &probetree_cmp) return 1;
else if(fptr == &replay_var_compare) return 1;
else if(fptr == &view_cmp) return 1;
return 0;
}
int
fptr_whitelist_hash_sizefunc(lruhash_sizefunc_t fptr)
fptr_whitelist_hash_sizefunc(lruhash_sizefunc_type fptr)
{
if(fptr == &msgreply_sizefunc) return 1;
else if(fptr == &ub_rrset_sizefunc) return 1;
else if(fptr == &infra_sizefunc) return 1;
else if(fptr == &key_entry_sizefunc) return 1;
else if(fptr == &rate_sizefunc) return 1;
else if(fptr == &ip_rate_sizefunc) return 1;
else if(fptr == &test_slabhash_sizefunc) return 1;
#ifdef CLIENT_SUBNET
else if(fptr == &msg_cache_sizefunc) return 1;
#endif
return 0;
}
int
fptr_whitelist_hash_compfunc(lruhash_compfunc_t fptr)
fptr_whitelist_hash_compfunc(lruhash_compfunc_type fptr)
{
if(fptr == &query_info_compare) return 1;
else if(fptr == &ub_rrset_compare) return 1;
else if(fptr == &infra_compfunc) return 1;
else if(fptr == &key_entry_compfunc) return 1;
else if(fptr == &rate_compfunc) return 1;
else if(fptr == &ip_rate_compfunc) return 1;
else if(fptr == &test_slabhash_compfunc) return 1;
return 0;
}
int
fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_t fptr)
fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_type fptr)
{
if(fptr == &query_entry_delete) return 1;
else if(fptr == &ub_rrset_key_delete) return 1;
else if(fptr == &infra_delkeyfunc) return 1;
else if(fptr == &key_entry_delkeyfunc) return 1;
else if(fptr == &rate_delkeyfunc) return 1;
else if(fptr == &ip_rate_delkeyfunc) return 1;
else if(fptr == &test_slabhash_delkey) return 1;
return 0;
}
int
fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_t fptr)
fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_type fptr)
{
if(fptr == &reply_info_delete) return 1;
else if(fptr == &rrset_data_delete) return 1;
@ -248,11 +263,14 @@ fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_t fptr)
else if(fptr == &key_entry_deldatafunc) return 1;
else if(fptr == &rate_deldatafunc) return 1;
else if(fptr == &test_slabhash_deldata) return 1;
#ifdef CLIENT_SUBNET
else if(fptr == &subnet_data_delete) return 1;
#endif
return 0;
}
int
fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr)
fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_type fptr)
{
if(fptr == NULL) return 1;
else if(fptr == &rrset_markdel) return 1;
@ -262,11 +280,9 @@ fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr)
/** whitelist env->send_query callbacks */
int
fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct module_qstate* q))
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q))
{
if(fptr == &worker_send_query) return 1;
else if(fptr == &libworker_send_query) return 1;
@ -312,8 +328,15 @@ fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
if(fptr == &iter_init) return 1;
else if(fptr == &val_init) return 1;
else if(fptr == &dns64_init) return 1;
else if(fptr == &respip_init) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_init) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_init) return 1;
#endif
#ifdef CLIENT_SUBNET
else if(fptr == &subnetmod_init) return 1;
#endif
return 0;
}
@ -324,8 +347,15 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
if(fptr == &iter_deinit) return 1;
else if(fptr == &val_deinit) return 1;
else if(fptr == &dns64_deinit) return 1;
else if(fptr == &respip_deinit) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_deinit) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_deinit) return 1;
#endif
#ifdef CLIENT_SUBNET
else if(fptr == &subnetmod_deinit) return 1;
#endif
return 0;
}
@ -337,8 +367,15 @@ fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
if(fptr == &iter_operate) return 1;
else if(fptr == &val_operate) return 1;
else if(fptr == &dns64_operate) return 1;
else if(fptr == &respip_operate) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_operate) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_operate) return 1;
#endif
#ifdef CLIENT_SUBNET
else if(fptr == &subnetmod_operate) return 1;
#endif
return 0;
}
@ -350,8 +387,15 @@ fptr_whitelist_mod_inform_super(void (*fptr)(
if(fptr == &iter_inform_super) return 1;
else if(fptr == &val_inform_super) return 1;
else if(fptr == &dns64_inform_super) return 1;
else if(fptr == &respip_inform_super) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_inform_super) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_inform_super) return 1;
#endif
#ifdef CLIENT_SUBNET
else if(fptr == &subnetmod_inform_super) return 1;
#endif
return 0;
}
@ -363,8 +407,15 @@ fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate,
if(fptr == &iter_clear) return 1;
else if(fptr == &val_clear) return 1;
else if(fptr == &dns64_clear) return 1;
else if(fptr == &respip_clear) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_clear) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_clear) return 1;
#endif
#ifdef CLIENT_SUBNET
else if(fptr == &subnetmod_clear) return 1;
#endif
return 0;
}
@ -375,8 +426,15 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id))
if(fptr == &iter_get_mem) return 1;
else if(fptr == &val_get_mem) return 1;
else if(fptr == &dns64_get_mem) return 1;
else if(fptr == &respip_get_mem) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_get_mem) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_get_mem) return 1;
#endif
#ifdef CLIENT_SUBNET
else if(fptr == &subnetmod_get_mem) return 1;
#endif
return 0;
}
@ -388,14 +446,14 @@ fptr_whitelist_alloc_cleanup(void (*fptr)(void*))
return 0;
}
int fptr_whitelist_tube_listen(tube_callback_t* fptr)
int fptr_whitelist_tube_listen(tube_callback_type* fptr)
{
if(fptr == &worker_handle_control_cmd) return 1;
else if(fptr == &libworker_handle_control_cmd) return 1;
return 0;
}
int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr)
int fptr_whitelist_mesh_cb(mesh_cb_func_type fptr)
{
if(fptr == &libworker_fg_done_cb) return 1;
else if(fptr == &libworker_bg_done_cb) return 1;
@ -411,3 +469,64 @@ int fptr_whitelist_print_func(void (*fptr)(char*,void*))
else if(fptr == &remote_get_opt_ssl) return 1;
return 0;
}
int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_type* fptr,
enum inplace_cb_list_type type)
{
#ifndef WITH_PYTHONMODULE
(void)fptr;
#endif
if(type == inplace_cb_reply) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
} else if(type == inplace_cb_reply_cache) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
} else if(type == inplace_cb_reply_local) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
} else if(type == inplace_cb_reply_servfail) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
}
return 0;
}
int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* fptr)
{
#ifdef CLIENT_SUBNET
if(fptr == &ecs_whitelist_check)
return 1;
#else
(void)fptr;
#endif
return 0;
}
int fptr_whitelist_inplace_cb_edns_back_parsed(
inplace_cb_edns_back_parsed_func_type* fptr)
{
#ifdef CLIENT_SUBNET
if(fptr == &ecs_edns_back_parsed)
return 1;
#else
(void)fptr;
#endif
return 0;
}
int fptr_whitelist_inplace_cb_query_response(
inplace_cb_query_response_func_type* fptr)
{
#ifdef CLIENT_SUBNET
if(fptr == &ecs_query_response)
return 1;
#else
(void)fptr;
#endif
return 0;
}

View file

@ -80,7 +80,7 @@
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_comm_point(comm_point_callback_t *fptr);
int fptr_whitelist_comm_point(comm_point_callback_type *fptr);
/**
* Check function pointer whitelist for raw comm_point callback values.
@ -88,7 +88,7 @@ int fptr_whitelist_comm_point(comm_point_callback_t *fptr);
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_comm_point_raw(comm_point_callback_t *fptr);
int fptr_whitelist_comm_point_raw(comm_point_callback_type *fptr);
/**
* Check function pointer whitelist for comm_timer callback values.
@ -137,7 +137,7 @@ int fptr_whitelist_event(void (*fptr)(int, short, void *));
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_pending_udp(comm_point_callback_t *fptr);
int fptr_whitelist_pending_udp(comm_point_callback_type *fptr);
/**
* Check function pointer whitelist for pending tcp callback values.
@ -145,7 +145,7 @@ int fptr_whitelist_pending_udp(comm_point_callback_t *fptr);
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_pending_tcp(comm_point_callback_t *fptr);
int fptr_whitelist_pending_tcp(comm_point_callback_type *fptr);
/**
* Check function pointer whitelist for serviced query callback values.
@ -153,7 +153,7 @@ int fptr_whitelist_pending_tcp(comm_point_callback_t *fptr);
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_serviced_query(comm_point_callback_t *fptr);
int fptr_whitelist_serviced_query(comm_point_callback_type *fptr);
/**
* Check function pointer whitelist for rbtree cmp callback values.
@ -169,7 +169,7 @@ int fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *));
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_hash_sizefunc(lruhash_sizefunc_t fptr);
int fptr_whitelist_hash_sizefunc(lruhash_sizefunc_type fptr);
/**
* Check function pointer whitelist for lruhash compfunc callback values.
@ -177,7 +177,7 @@ int fptr_whitelist_hash_sizefunc(lruhash_sizefunc_t fptr);
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_hash_compfunc(lruhash_compfunc_t fptr);
int fptr_whitelist_hash_compfunc(lruhash_compfunc_type fptr);
/**
* Check function pointer whitelist for lruhash delkeyfunc callback values.
@ -185,7 +185,7 @@ int fptr_whitelist_hash_compfunc(lruhash_compfunc_t fptr);
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_t fptr);
int fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_type fptr);
/**
* Check function pointer whitelist for lruhash deldata callback values.
@ -193,7 +193,7 @@ int fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_t fptr);
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_t fptr);
int fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_type fptr);
/**
* Check function pointer whitelist for lruhash markdel callback values.
@ -201,7 +201,7 @@ int fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_t fptr);
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr);
int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_type fptr);
/**
* Check function pointer whitelist for module_env send_query callback values.
@ -210,11 +210,9 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr);
* @return false if not in whitelist.
*/
int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct module_qstate* q));
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q));
/**
* Check function pointer whitelist for module_env detach_subs callback values.
@ -318,7 +316,7 @@ int fptr_whitelist_alloc_cleanup(void (*fptr)(void*));
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_tube_listen(tube_callback_t* fptr);
int fptr_whitelist_tube_listen(tube_callback_type* fptr);
/**
* Check function pointer whitelist for mesh state callback values.
@ -326,7 +324,7 @@ int fptr_whitelist_tube_listen(tube_callback_t* fptr);
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr);
int fptr_whitelist_mesh_cb(mesh_cb_func_type fptr);
/**
* Check function pointer whitelist for config_get_option func values.
@ -335,6 +333,40 @@ int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr);
*/
int fptr_whitelist_print_func(void (*fptr)(char*,void*));
/**
* Check function pointer whitelist for inplace_cb_reply,
* inplace_cb_reply_cache, inplace_cb_reply_local and inplace_cb_reply_servfail
* func values.
* @param fptr: function pointer to check.
* @param type: the type of the callback function.
* @return false if not in whitelist.
*/
int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_type* fptr,
enum inplace_cb_list_type type);
/**
* Check function pointer whitelist for inplace_cb_query func values.
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* fptr);
/**
* Check function pointer whitelist for inplace_cb_edns_back_parsed func values.
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_inplace_cb_edns_back_parsed(
inplace_cb_edns_back_parsed_func_type* fptr);
/**
* Check function pointer whitelist for inplace_cb_query_response func values.
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_inplace_cb_query_response(
inplace_cb_query_response_func_type* fptr);
/** Due to module breakage by fptr wlist, these test app declarations
* are presented here */
/**

View file

@ -661,6 +661,7 @@
847,
848,
853,
854,
860,
861,
862,
@ -1186,6 +1187,7 @@
1525,
1526,
1527,
1528,
1529,
1530,
1531,
@ -3775,6 +3777,7 @@
4188,
4191,
4192,
4197,
4199,
4300,
4301,
@ -3844,6 +3847,8 @@
4412,
4413,
4416,
4418,
4420,
4425,
4426,
4430,
@ -3904,6 +3909,7 @@
4599,
4600,
4601,
4621,
4658,
4659,
4660,
@ -3942,6 +3948,7 @@
4700,
4701,
4702,
4711,
4725,
4726,
4727,
@ -3958,12 +3965,15 @@
4743,
4744,
4745,
4746,
4747,
4749,
4750,
4751,
4752,
4753,
4754,
4755,
4784,
4785,
4789,
@ -4222,6 +4232,7 @@
5436,
5437,
5443,
5450,
5453,
5454,
5455,
@ -4446,6 +4457,7 @@
6446,
6455,
6456,
6464,
6471,
6480,
6481,
@ -4493,6 +4505,7 @@
6626,
6627,
6628,
6629,
6633,
6634,
6635,
@ -4522,7 +4535,6 @@
6786,
6787,
6788,
6789,
6790,
6791,
6801,
@ -4562,6 +4574,7 @@
7013,
7014,
7015,
7016,
7019,
7020,
7021,
@ -4598,6 +4611,7 @@
7201,
7227,
7235,
7244,
7262,
7272,
7273,
@ -4651,6 +4665,7 @@
7570,
7574,
7588,
7606,
7624,
7627,
7628,
@ -4718,6 +4733,7 @@
8002,
8003,
8005,
8006,
8008,
8019,
8020,
@ -4777,9 +4793,12 @@
8207,
8208,
8230,
8231,
8232,
8243,
8276,
8280,
8282,
8292,
8294,
8300,
@ -4836,6 +4855,7 @@
8793,
8800,
8804,
8808,
8873,
8880,
8883,
@ -4873,6 +4893,7 @@
9024,
9025,
9026,
9060,
9080,
9084,
9085,
@ -5199,6 +5220,7 @@
18463,
18634,
18635,
18668,
18769,
18881,
18888,
@ -5206,6 +5228,7 @@
19007,
19191,
19194,
19220,
19283,
19315,
19398,
@ -5266,6 +5289,7 @@
23004,
23005,
23272,
23294,
23333,
23400,
23401,
@ -5335,6 +5359,7 @@
30260,
30832,
30999,
31016,
31029,
31416,
31457,
@ -5368,12 +5393,14 @@
34249,
34378,
34379,
34567,
34962,
34963,
34964,
34980,
35001,
35004,
35100,
35355,
36001,
36411,
@ -5415,6 +5442,7 @@
44900,
45000,
45054,
45514,
45678,
45825,
45966,

View file

@ -110,15 +110,15 @@ void ub_thread_sig_unblock(int sig)
* @param arg: user argument to func.
*/
void
ub_thr_fork_create(ub_thread_t* thr, void* (*func)(void*), void* arg)
ub_thr_fork_create(ub_thread_type* thr, void* (*func)(void*), void* arg)
{
pid_t pid = fork();
switch(pid) {
default: /* main */
*thr = (ub_thread_t)pid;
*thr = (ub_thread_type)pid;
return;
case 0: /* child */
*thr = (ub_thread_t)getpid();
*thr = (ub_thread_type)getpid();
(void)(*func)(arg);
exit(0);
case -1: /* error */
@ -128,10 +128,10 @@ ub_thr_fork_create(ub_thread_t* thr, void* (*func)(void*), void* arg)
/**
* There is no threading. Wait for a process to terminate.
* Note that ub_thread_t is defined as pid_t.
* Note that ub_thread_type is defined as pid_t.
* @param thread: the process id to wait for.
*/
void ub_thr_fork_wait(ub_thread_t thread)
void ub_thr_fork_wait(ub_thread_type thread)
{
int status = 0;
if(waitpid((pid_t)thread, &status, 0) == -1)
@ -143,7 +143,7 @@ void ub_thr_fork_wait(ub_thread_t thread)
#endif /* !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) && !defined(HAVE_WINDOWS_THREADS) */
#ifdef HAVE_SOLARIS_THREADS
void* ub_thread_key_get(ub_thread_key_t key)
void* ub_thread_key_get(ub_thread_key_type key)
{
void* ret=NULL;
LOCKRET(thr_getspecific(key, &ret));
@ -167,19 +167,19 @@ static void log_win_err(const char* str, DWORD err)
LocalFree(buf);
}
void lock_basic_init(lock_basic_t* lock)
void lock_basic_init(lock_basic_type* lock)
{
/* implement own lock, because windows HANDLE as Mutex usage
* uses too many handles and would bog down the whole system. */
(void)InterlockedExchange(lock, 0);
}
void lock_basic_destroy(lock_basic_t* lock)
void lock_basic_destroy(lock_basic_type* lock)
{
(void)InterlockedExchange(lock, 0);
}
void lock_basic_lock(lock_basic_t* lock)
void lock_basic_lock(lock_basic_type* lock)
{
LONG wait = 1; /* wait 1 msec at first */
@ -191,13 +191,13 @@ void lock_basic_lock(lock_basic_t* lock)
/* the old value was 0, but we inserted 1, we locked it! */
}
void lock_basic_unlock(lock_basic_t* lock)
void lock_basic_unlock(lock_basic_type* lock)
{
/* unlock it by inserting the value of 0. xchg for cache coherency. */
(void)InterlockedExchange(lock, 0);
}
void ub_thread_key_create(ub_thread_key_t* key, void* f)
void ub_thread_key_create(ub_thread_key_type* key, void* f)
{
*key = TlsAlloc();
if(*key == TLS_OUT_OF_INDEXES) {
@ -207,14 +207,14 @@ void ub_thread_key_create(ub_thread_key_t* key, void* f)
else ub_thread_key_set(*key, f);
}
void ub_thread_key_set(ub_thread_key_t key, void* v)
void ub_thread_key_set(ub_thread_key_type key, void* v)
{
if(!TlsSetValue(key, v)) {
log_win_err("TlsSetValue failed", GetLastError());
}
}
void* ub_thread_key_get(ub_thread_key_t key)
void* ub_thread_key_get(ub_thread_key_type key)
{
void* ret = (void*)TlsGetValue(key);
if(ret == NULL && GetLastError() != ERROR_SUCCESS) {
@ -223,7 +223,7 @@ void* ub_thread_key_get(ub_thread_key_t key)
return ret;
}
void ub_thread_create(ub_thread_t* thr, void* (*func)(void*), void* arg)
void ub_thread_create(ub_thread_type* thr, void* (*func)(void*), void* arg)
{
#ifndef HAVE__BEGINTHREADEX
*thr = CreateThread(NULL, /* default security (no inherit handle) */
@ -233,7 +233,7 @@ void ub_thread_create(ub_thread_t* thr, void* (*func)(void*), void* arg)
NULL); /* do not store thread identifier anywhere */
#else
/* the beginthreadex routine setups for the C lib; aligns stack */
*thr=(ub_thread_t)_beginthreadex(NULL, 0, (void*)func, arg, 0, NULL);
*thr=(ub_thread_type)_beginthreadex(NULL, 0, (void*)func, arg, 0, NULL);
#endif
if(*thr == NULL) {
log_win_err("CreateThread failed", GetLastError());
@ -241,12 +241,12 @@ void ub_thread_create(ub_thread_t* thr, void* (*func)(void*), void* arg)
}
}
ub_thread_t ub_thread_self(void)
ub_thread_type ub_thread_self(void)
{
return GetCurrentThread();
}
void ub_thread_join(ub_thread_t thr)
void ub_thread_join(ub_thread_type thr)
{
DWORD ret = WaitForSingleObject(thr, INFINITE);
if(ret == WAIT_FAILED) {

View file

@ -95,7 +95,7 @@
/******************* PTHREAD ************************/
/** use pthread mutex for basic lock */
typedef pthread_mutex_t lock_basic_t;
typedef pthread_mutex_t lock_basic_type;
/** small front for pthread init func, NULL is default attrs. */
#define lock_basic_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
#define lock_basic_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
@ -104,7 +104,7 @@ typedef pthread_mutex_t lock_basic_t;
#ifndef HAVE_PTHREAD_RWLOCK_T
/** in case rwlocks are not supported, use a mutex. */
typedef pthread_mutex_t lock_rw_t;
typedef pthread_mutex_t lock_rw_type;
#define lock_rw_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
#define lock_rw_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
#define lock_rw_rdlock(lock) LOCKRET(pthread_mutex_lock(lock))
@ -112,7 +112,7 @@ typedef pthread_mutex_t lock_rw_t;
#define lock_rw_unlock(lock) LOCKRET(pthread_mutex_unlock(lock))
#else /* HAVE_PTHREAD_RWLOCK_T */
/** we use the pthread rwlock */
typedef pthread_rwlock_t lock_rw_t;
typedef pthread_rwlock_t lock_rw_type;
/** small front for pthread init func, NULL is default attrs. */
#define lock_rw_init(lock) LOCKRET(pthread_rwlock_init(lock, NULL))
#define lock_rw_destroy(lock) LOCKRET(pthread_rwlock_destroy(lock))
@ -123,7 +123,7 @@ typedef pthread_rwlock_t lock_rw_t;
#ifndef HAVE_PTHREAD_SPINLOCK_T
/** in case spinlocks are not supported, use a mutex. */
typedef pthread_mutex_t lock_quick_t;
typedef pthread_mutex_t lock_quick_type;
/** small front for pthread init func, NULL is default attrs. */
#define lock_quick_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
#define lock_quick_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
@ -132,7 +132,7 @@ typedef pthread_mutex_t lock_quick_t;
#else /* HAVE_PTHREAD_SPINLOCK_T */
/** use pthread spinlock for the quick lock */
typedef pthread_spinlock_t lock_quick_t;
typedef pthread_spinlock_t lock_quick_type;
/**
* allocate process private since this is available whether
* Thread Process-Shared Synchronization is supported or not.
@ -148,14 +148,31 @@ typedef pthread_spinlock_t lock_quick_t;
#endif /* HAVE SPINLOCK */
/** Thread creation */
typedef pthread_t ub_thread_t;
/** Pass where to store tread_t in thr. Use default NULL attributes. */
#define ub_thread_create(thr, func, arg) LOCKRET(pthread_create(thr, NULL, func, arg))
typedef pthread_t ub_thread_type;
/** On alpine linux default thread stack size is 80 Kb. See
http://wiki.musl-libc.org/wiki/Functional_differences_from_glibc#Thread_stack_size
This is not enough and cause segfault. Other linux distros have 2 Mb at least.
Wrapper for set up thread stack size */
#define PTHREADSTACKSIZE 2*1024*1024
#define PTHREADCREATE(thr, stackrequired, func, arg) do {\
pthread_attr_t attr; \
size_t stacksize; \
LOCKRET(pthread_attr_init(&attr)); \
LOCKRET(pthread_attr_getstacksize(&attr, &stacksize)); \
if (stacksize < stackrequired) { \
LOCKRET(pthread_attr_setstacksize(&attr, stackrequired)); \
LOCKRET(pthread_create(thr, &attr, func, arg)); \
LOCKRET(pthread_attr_getstacksize(&attr, &stacksize)); \
verbose(VERB_ALGO, "Thread stack size set to %u", (unsigned)stacksize); \
} else {LOCKRET(pthread_create(thr, NULL, func, arg));} \
} while(0)
/** Use wrapper for set thread stack size on attributes. */
#define ub_thread_create(thr, func, arg) PTHREADCREATE(thr, PTHREADSTACKSIZE, func, arg)
/** get self id. */
#define ub_thread_self() pthread_self()
/** wait for another thread to terminate */
#define ub_thread_join(thread) LOCKRET(pthread_join(thread, NULL))
typedef pthread_key_t ub_thread_key_t;
typedef pthread_key_t ub_thread_key_type;
#define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f))
#define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v))
#define ub_thread_key_get(key) pthread_getspecific(key)
@ -167,7 +184,7 @@ typedef pthread_key_t ub_thread_key_t;
#include <synch.h>
#include <thread.h>
typedef rwlock_t lock_rw_t;
typedef rwlock_t lock_rw_type;
#define lock_rw_init(lock) LOCKRET(rwlock_init(lock, USYNC_THREAD, NULL))
#define lock_rw_destroy(lock) LOCKRET(rwlock_destroy(lock))
#define lock_rw_rdlock(lock) LOCKRET(rw_rdlock(lock))
@ -175,28 +192,28 @@ typedef rwlock_t lock_rw_t;
#define lock_rw_unlock(lock) LOCKRET(rw_unlock(lock))
/** use basic mutex */
typedef mutex_t lock_basic_t;
typedef mutex_t lock_basic_type;
#define lock_basic_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL))
#define lock_basic_destroy(lock) LOCKRET(mutex_destroy(lock))
#define lock_basic_lock(lock) LOCKRET(mutex_lock(lock))
#define lock_basic_unlock(lock) LOCKRET(mutex_unlock(lock))
/** No spinlocks in solaris threads API. Use a mutex. */
typedef mutex_t lock_quick_t;
typedef mutex_t lock_quick_type;
#define lock_quick_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL))
#define lock_quick_destroy(lock) LOCKRET(mutex_destroy(lock))
#define lock_quick_lock(lock) LOCKRET(mutex_lock(lock))
#define lock_quick_unlock(lock) LOCKRET(mutex_unlock(lock))
/** Thread creation, create a default thread. */
typedef thread_t ub_thread_t;
typedef thread_t ub_thread_type;
#define ub_thread_create(thr, func, arg) LOCKRET(thr_create(NULL, NULL, func, arg, NULL, thr))
#define ub_thread_self() thr_self()
#define ub_thread_join(thread) LOCKRET(thr_join(thread, NULL, NULL))
typedef thread_key_t ub_thread_key_t;
typedef thread_key_t ub_thread_key_type;
#define ub_thread_key_create(key, f) LOCKRET(thr_keycreate(key, f))
#define ub_thread_key_set(key, v) LOCKRET(thr_setspecific(key, v))
void* ub_thread_key_get(ub_thread_key_t key);
void* ub_thread_key_get(ub_thread_key_type key);
#else /* we do not HAVE_SOLARIS_THREADS and no PTHREADS */
@ -205,7 +222,7 @@ void* ub_thread_key_get(ub_thread_key_t key);
#include <windows.h>
/* Use a mutex */
typedef LONG lock_rw_t;
typedef LONG lock_rw_type;
#define lock_rw_init(lock) lock_basic_init(lock)
#define lock_rw_destroy(lock) lock_basic_destroy(lock)
#define lock_rw_rdlock(lock) lock_basic_lock(lock)
@ -213,35 +230,35 @@ typedef LONG lock_rw_t;
#define lock_rw_unlock(lock) lock_basic_unlock(lock)
/** the basic lock is a mutex, implemented opaquely, for error handling. */
typedef LONG lock_basic_t;
void lock_basic_init(lock_basic_t* lock);
void lock_basic_destroy(lock_basic_t* lock);
void lock_basic_lock(lock_basic_t* lock);
void lock_basic_unlock(lock_basic_t* lock);
typedef LONG lock_basic_type;
void lock_basic_init(lock_basic_type* lock);
void lock_basic_destroy(lock_basic_type* lock);
void lock_basic_lock(lock_basic_type* lock);
void lock_basic_unlock(lock_basic_type* lock);
/** on windows no spinlock, use mutex too. */
typedef LONG lock_quick_t;
typedef LONG lock_quick_type;
#define lock_quick_init(lock) lock_basic_init(lock)
#define lock_quick_destroy(lock) lock_basic_destroy(lock)
#define lock_quick_lock(lock) lock_basic_lock(lock)
#define lock_quick_unlock(lock) lock_basic_unlock(lock)
/** Thread creation, create a default thread. */
typedef HANDLE ub_thread_t;
void ub_thread_create(ub_thread_t* thr, void* (*func)(void*), void* arg);
ub_thread_t ub_thread_self(void);
void ub_thread_join(ub_thread_t thr);
typedef DWORD ub_thread_key_t;
void ub_thread_key_create(ub_thread_key_t* key, void* f);
void ub_thread_key_set(ub_thread_key_t key, void* v);
void* ub_thread_key_get(ub_thread_key_t key);
typedef HANDLE ub_thread_type;
void ub_thread_create(ub_thread_type* thr, void* (*func)(void*), void* arg);
ub_thread_type ub_thread_self(void);
void ub_thread_join(ub_thread_type thr);
typedef DWORD ub_thread_key_type;
void ub_thread_key_create(ub_thread_key_type* key, void* f);
void ub_thread_key_set(ub_thread_key_type key, void* v);
void* ub_thread_key_get(ub_thread_key_type key);
#else /* we do not HAVE_SOLARIS_THREADS, PTHREADS or WINDOWS_THREADS */
/******************* NO THREADS ************************/
#define THREADS_DISABLED 1
/** In case there is no thread support, define locks to do nothing */
typedef int lock_rw_t;
typedef int lock_rw_type;
#define lock_rw_init(lock) /* nop */
#define lock_rw_destroy(lock) /* nop */
#define lock_rw_rdlock(lock) /* nop */
@ -249,30 +266,30 @@ typedef int lock_rw_t;
#define lock_rw_unlock(lock) /* nop */
/** define locks to do nothing */
typedef int lock_basic_t;
typedef int lock_basic_type;
#define lock_basic_init(lock) /* nop */
#define lock_basic_destroy(lock) /* nop */
#define lock_basic_lock(lock) /* nop */
#define lock_basic_unlock(lock) /* nop */
/** define locks to do nothing */
typedef int lock_quick_t;
typedef int lock_quick_type;
#define lock_quick_init(lock) /* nop */
#define lock_quick_destroy(lock) /* nop */
#define lock_quick_lock(lock) /* nop */
#define lock_quick_unlock(lock) /* nop */
/** Thread creation, threads do not exist */
typedef pid_t ub_thread_t;
typedef pid_t ub_thread_type;
/** ub_thread_create is simulated with fork (extremely heavy threads,
* with no shared memory). */
#define ub_thread_create(thr, func, arg) \
ub_thr_fork_create(thr, func, arg)
#define ub_thread_self() getpid()
#define ub_thread_join(thread) ub_thr_fork_wait(thread)
void ub_thr_fork_wait(ub_thread_t thread);
void ub_thr_fork_create(ub_thread_t* thr, void* (*func)(void*), void* arg);
typedef void* ub_thread_key_t;
void ub_thr_fork_wait(ub_thread_type thread);
void ub_thr_fork_create(ub_thread_type* thr, void* (*func)(void*), void* arg);
typedef void* ub_thread_key_type;
#define ub_thread_key_create(key, f) (*(key)) = NULL
#define ub_thread_key_set(key, v) (key) = (v)
#define ub_thread_key_get(key) (key)

View file

@ -67,10 +67,10 @@ static FILE* logfile = 0;
/** if key has been created */
static int key_created = 0;
/** pthread key for thread ids in logfile */
static ub_thread_key_t logkey;
static ub_thread_key_type logkey;
#ifndef THREADS_DISABLED
/** pthread mutex to protect FILE* */
static lock_quick_t log_lock;
static lock_quick_type log_lock;
#endif
/** the identity of this executable/process */
static const char* ident="unbound";

View file

@ -147,7 +147,7 @@ static void handle_timeouts(struct event_base* base, struct timeval* now,
wait->tv_sec = (time_t)-1;
#endif
while((rbnode_t*)(p = (struct event*)rbtree_first(base->times))
while((rbnode_type*)(p = (struct event*)rbtree_first(base->times))
!=RBTREE_NULL) {
#ifndef S_SPLINT_S
if(p->ev_timeout.tv_sec > now->tv_sec ||

View file

@ -96,7 +96,7 @@
struct event_base
{
/** sorted by timeout (absolute), ptr */
rbtree_t* times;
rbtree_type* times;
/** array of 0 - maxfd of ptr to event for it */
struct event** fds;
/** max fd in use */
@ -128,7 +128,7 @@ struct event_base
*/
struct event {
/** node in timeout rbtree */
rbnode_t node;
rbnode_type node;
/** is event already added */
int added;

View file

@ -39,6 +39,7 @@
#include "config.h"
#include "util/module.h"
#include "sldns/wire2str.h"
const char*
strextstate(enum module_ext_state s)
@ -69,3 +70,169 @@ strmodulevent(enum module_ev e)
}
return "bad_event_value";
}
int
edns_known_options_init(struct module_env* env)
{
env->edns_known_options_num = 0;
env->edns_known_options = (struct edns_known_option*)calloc(
MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option));
if(!env->edns_known_options) return 0;
return 1;
}
void
edns_known_options_delete(struct module_env* env)
{
free(env->edns_known_options);
env->edns_known_options = NULL;
env->edns_known_options_num = 0;
}
int
edns_register_option(uint16_t opt_code, int bypass_cache_stage,
int no_aggregation, struct module_env* env)
{
size_t i;
if(env->worker) {
log_err("invalid edns registration: "
"trying to register option after module init phase");
return 0;
}
/**
* Checking if we are full first is faster but it does not provide
* the option to change the flags when the array is full.
* It only impacts unbound initialization, leave it for now.
*/
/* Check if the option is already registered. */
for(i=0; i<env->edns_known_options_num; i++)
if(env->edns_known_options[i].opt_code == opt_code)
break;
/* If it is not yet registered check if we have space to add a new one. */
if(i == env->edns_known_options_num) {
if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) {
log_err("invalid edns registration: maximum options reached");
return 0;
}
env->edns_known_options_num++;
}
env->edns_known_options[i].opt_code = opt_code;
env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage;
env->edns_known_options[i].no_aggregation = no_aggregation;
return 1;
}
int
inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
struct module_env* env, int id)
{
struct inplace_cb* callback;
struct inplace_cb** prevp;
if(env->worker) {
log_err("invalid edns callback registration: "
"trying to register callback after module init phase");
return 0;
}
callback = (struct inplace_cb*)calloc(1, sizeof(*callback));
if(callback == NULL) {
log_err("out of memory during edns callback registration.");
return 0;
}
callback->id = id;
callback->next = NULL;
callback->cb = cb;
callback->cb_arg = cbarg;
prevp = (struct inplace_cb**) &env->inplace_cb_lists[type];
/* append at end of list */
while(*prevp != NULL)
prevp = &((*prevp)->next);
*prevp = callback;
return 1;
}
void
inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
int id)
{
struct inplace_cb* temp = env->inplace_cb_lists[type];
struct inplace_cb* prev = NULL;
while(temp) {
if(temp->id == id) {
if(!prev) {
env->inplace_cb_lists[type] = temp->next;
free(temp);
temp = env->inplace_cb_lists[type];
}
else {
prev->next = temp->next;
free(temp);
temp = prev->next;
}
}
else {
prev = temp;
temp = temp->next;
}
}
}
struct edns_known_option*
edns_option_is_known(uint16_t opt_code, struct module_env* env)
{
size_t i;
for(i=0; i<env->edns_known_options_num; i++)
if(env->edns_known_options[i].opt_code == opt_code)
return env->edns_known_options + i;
return NULL;
}
int
edns_bypass_cache_stage(struct edns_option* list, struct module_env* env)
{
size_t i;
for(; list; list=list->next)
for(i=0; i<env->edns_known_options_num; i++)
if(env->edns_known_options[i].opt_code == list->opt_code &&
env->edns_known_options[i].bypass_cache_stage == 1)
return 1;
return 0;
}
int
unique_mesh_state(struct edns_option* list, struct module_env* env)
{
size_t i;
if(env->unique_mesh)
return 1;
for(; list; list=list->next)
for(i=0; i<env->edns_known_options_num; i++)
if(env->edns_known_options[i].opt_code == list->opt_code &&
env->edns_known_options[i].no_aggregation == 1)
return 1;
return 0;
}
void
log_edns_known_options(enum verbosity_value level, struct module_env* env)
{
size_t i;
char str[32], *s;
size_t slen;
if(env->edns_known_options_num > 0 && verbosity >= level) {
verbose(level, "EDNS known options:");
verbose(level, " Code: Bypass_cache_stage: Aggregate_mesh:");
for(i=0; i<env->edns_known_options_num; i++) {
s = str;
slen = sizeof(str);
(void)sldns_wire2str_edns_option_code_print(&s, &slen,
env->edns_known_options[i].opt_code);
verbose(level, " %-8.8s %-19s %-15s", str,
env->edns_known_options[i].bypass_cache_stage?"YES":"NO",
env->edns_known_options[i].no_aggregation?"NO":"YES");
}
}
}

View file

@ -174,9 +174,128 @@ struct val_anchors;
struct val_neg_cache;
struct iter_forwards;
struct iter_hints;
struct respip_set;
struct respip_client_info;
struct respip_addr_info;
/** Maximum number of modules in operation */
#define MAX_MODULE 5
#define MAX_MODULE 16
/** Maximum number of known edns options */
#define MAX_KNOWN_EDNS_OPTS 256
enum inplace_cb_list_type {
/* Inplace callbacks for when a resolved reply is ready to be sent to the
* front.*/
inplace_cb_reply = 0,
/* Inplace callbacks for when a reply is given from the cache. */
inplace_cb_reply_cache,
/* Inplace callbacks for when a reply is given with local data
* (or Chaos reply). */
inplace_cb_reply_local,
/* Inplace callbacks for when the reply is servfail. */
inplace_cb_reply_servfail,
/* Inplace callbacks for when a query is ready to be sent to the back.*/
inplace_cb_query,
/* Inplace callback for when a reply is received from the back. */
inplace_cb_query_response,
/* Inplace callback for when EDNS is parsed on a reply received from the
* back. */
inplace_cb_edns_back_parsed,
/* Total number of types. Used for array initialization.
* Should always be last. */
inplace_cb_types_total
};
/** Known edns option. Can be populated during modules' init. */
struct edns_known_option {
/** type of this edns option */
uint16_t opt_code;
/** whether the option needs to bypass the cache stage */
int bypass_cache_stage;
/** whether the option needs mesh aggregation */
int no_aggregation;
};
/**
* Inplace callback list of registered routines to be called.
*/
struct inplace_cb {
/** next in list */
struct inplace_cb* next;
/** Inplace callback routine */
void* cb;
void* cb_arg;
/** module id */
int id;
};
/**
* Inplace callback function called before replying.
* Called as func(edns, qstate, opt_list_out, qinfo, reply_info, rcode,
* region, python_callback)
* Where:
* qinfo: the query info.
* qstate: the module state. NULL when calling before the query reaches the
* mesh states.
* rep: reply_info. Could be NULL.
* rcode: the return code.
* edns: the edns_data of the reply. When qstate is NULL, it is also used as
* the edns input.
* opt_list_out: the edns options list for the reply.
* region: region to store data.
* python_callback: only used for registering a python callback function.
*/
typedef int inplace_cb_reply_func_type(struct query_info* qinfo,
struct module_qstate* qstate, struct reply_info* rep, int rcode,
struct edns_data* edns, struct edns_option** opt_list_out,
struct regional* region, int id, void* callback);
/**
* Inplace callback function called before sending the query to a nameserver.
* Called as func(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region,
* python_callback)
* Where:
* qinfo: query info.
* flags: flags of the query.
* qstate: query state.
* addr: to which server to send the query.
* addrlen: length of addr.
* zone: name of the zone of the delegation point. wireformat dname.
* This is the delegation point name for which the server is deemed
* authoritative.
* zonelen: length of zone.
* region: region to store data.
* python_callback: only used for registering a python callback function.
*/
typedef int inplace_cb_query_func_type(struct query_info* qinfo, uint16_t flags,
struct module_qstate* qstate, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region,
int id, void* callback);
/**
* Inplace callback function called after parsing edns on query reply.
* Called as func(qstate, cb_args)
* Where:
* qstate: the query state
* id: module id
* cb_args: argument passed when registering callback.
*/
typedef int inplace_cb_edns_back_parsed_func_type(struct module_qstate* qstate,
int id, void* cb_args);
/**
* Inplace callback function called after parsing query response.
* Called as func(qstate, id, cb_args)
* Where:
* qstate: the query state
* response: query response
* id: module id
* cb_args: argument passed when registering callback.
*/
typedef int inplace_cb_query_response_func_type(struct module_qstate* qstate,
struct dns_msg* response, int id, void* cb_args);
/**
* Module environment.
@ -202,10 +321,7 @@ struct module_env {
* will cause operate() to be called with event timeout or reply.
* The time until a timeout is calculated from roundtrip timing,
* several UDP retries are attempted.
* @param qname: query name. (host order)
* @param qnamelen: length in bytes of qname, including trailing 0.
* @param qtype: query type. (host order)
* @param qclass: query class. (host order)
* @param qinfo: query info.
* @param flags: host order flags word, with opcode and CD bit.
* @param dnssec: if set, EDNS record will have bits set.
* If EDNS_DO bit is set, DO bit is set in EDNS records.
@ -218,16 +334,17 @@ struct module_env {
* @param addrlen: length of addr.
* @param zone: delegation point name.
* @param zonelen: length of zone name.
* @param ssl_upstream: use SSL for upstream queries.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent. Or returns an outbound entry with qsent and qstate set.
* This outbound_entry will be used on later module invocations
* that involve this query (timeout, error or reply).
*/
struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct outbound_entry* (*send_query)(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, int ssl_upstream,
struct module_qstate* q);
/**
@ -333,6 +450,20 @@ struct module_env {
struct iter_hints* hints;
/** module specific data. indexed by module id. */
void* modinfo[MAX_MODULE];
/* Shared linked list of inplace callback functions */
struct inplace_cb* inplace_cb_lists[inplace_cb_types_total];
/**
* Shared array of known edns options (size MAX_KNOWN_EDNS_OPTS).
* Filled by edns literate modules during init.
*/
struct edns_known_option* edns_known_options;
/* Number of known edns options */
size_t edns_known_options_num;
/* Make every mesh state unique, do not aggregate mesh states. */
int unique_mesh;
};
/**
@ -390,6 +521,8 @@ struct sock_list {
struct sockaddr_storage addr;
};
struct respip_action_info;
/**
* Module state, per query.
*/
@ -431,6 +564,32 @@ struct module_qstate {
struct mesh_state* mesh_info;
/** how many seconds before expiry is this prefetched (0 if not) */
time_t prefetch_leeway;
/** incoming edns options from the front end */
struct edns_option* edns_opts_front_in;
/** outgoing edns options to the back end */
struct edns_option* edns_opts_back_out;
/** incoming edns options from the back end */
struct edns_option* edns_opts_back_in;
/** outgoing edns options to the front end */
struct edns_option* edns_opts_front_out;
/** whether modules should answer from the cache */
int no_cache_lookup;
/** whether modules should store answer in the cache */
int no_cache_store;
/**
* Attributes of clients that share the qstate that may affect IP-based
* actions.
*/
struct respip_client_info* client_info;
/** Extended result of response-ip action processing, mainly
* for logging purposes. */
struct respip_action_info* respip_action_info;
/** whether the reply should be dropped */
int is_drop;
};
/**
@ -520,4 +679,100 @@ const char* strextstate(enum module_ext_state s);
*/
const char* strmodulevent(enum module_ev e);
/**
* Initialize the edns known options by allocating the required space.
* @param env: the module environment.
* @return false on failure (no memory).
*/
int edns_known_options_init(struct module_env* env);
/**
* Free the allocated space for the known edns options.
* @param env: the module environment.
*/
void edns_known_options_delete(struct module_env* env);
/**
* Register a known edns option. Overwrite the flags if it is already
* registered. Used before creating workers to register known edns options.
* @param opt_code: the edns option code.
* @param bypass_cache_stage: whether the option interacts with the cache.
* @param no_aggregation: whether the option implies more specific
* aggregation.
* @param env: the module environment.
* @return true on success, false on failure (registering more options than
* allowed or trying to register after the environment is copied to the
* threads.)
*/
int edns_register_option(uint16_t opt_code, int bypass_cache_stage,
int no_aggregation, struct module_env* env);
/**
* Register an inplace callback function.
* @param cb: pointer to the callback function.
* @param type: inplace callback type.
* @param cbarg: argument for the callback function, or NULL.
* @param env: the module environment.
* @param id: module id.
* @return true on success, false on failure (out of memory or trying to
* register after the environment is copied to the threads.)
*/
int
inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
struct module_env* env, int id);
/**
* Delete callback for specified type and module id.
* @param env: the module environment.
* @param type: inplace callback type.
* @param id: module id.
*/
void
inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
int id);
/**
* Delete all the inplace callback linked lists.
* @param env: the module environment.
*/
void inplace_cb_lists_delete(struct module_env* env);
/**
* Check if an edns option is known.
* @param opt_code: the edns option code.
* @param env: the module environment.
* @return pointer to registered option if the edns option is known,
* NULL otherwise.
*/
struct edns_known_option* edns_option_is_known(uint16_t opt_code,
struct module_env* env);
/**
* Check if an edns option needs to bypass the reply from cache stage.
* @param list: the edns options.
* @param env: the module environment.
* @return true if an edns option needs to bypass the cache stage,
* false otherwise.
*/
int edns_bypass_cache_stage(struct edns_option* list,
struct module_env* env);
/**
* Check if an unique mesh state is required. Might be triggered by EDNS option
* or set for the complete env.
* @param list: the edns options.
* @param env: the module environment.
* @return true if an edns option needs a unique mesh state,
* false otherwise.
*/
int unique_mesh_state(struct edns_option* list, struct module_env* env);
/**
* Log the known edns options.
* @param level: the desired verbosity level.
* @param env: the module environment.
*/
void log_edns_known_options(enum verbosity_value level,
struct module_env* env);
#endif /* UTIL_MODULE_H */

View file

@ -783,9 +783,9 @@ void* outgoing_ssl_fd(void* sslctx, int fd)
#endif
}
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
/** global lock list for openssl locks */
static lock_basic_t *ub_openssl_locks = NULL;
static lock_basic_type *ub_openssl_locks = NULL;
/** callback that gets thread id for openssl */
static unsigned long
@ -808,10 +808,10 @@ ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
int ub_openssl_lock_init(void)
{
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
int i;
ub_openssl_locks = (lock_basic_t*)reallocarray(
NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_t));
ub_openssl_locks = (lock_basic_type*)reallocarray(
NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type));
if(!ub_openssl_locks)
return 0;
for(i=0; i<CRYPTO_num_locks(); i++) {
@ -825,7 +825,7 @@ int ub_openssl_lock_init(void)
void ub_openssl_lock_delete(void)
{
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
int i;
if(!ub_openssl_locks)
return;

File diff suppressed because it is too large Load diff

View file

@ -60,18 +60,20 @@
#ifndef NET_EVENT_H
#define NET_EVENT_H
#include "dnscrypt/dnscrypt.h"
struct sldns_buffer;
struct comm_point;
struct comm_reply;
struct event_base;
struct ub_event_base;
/* internal event notification data storage structure. */
struct internal_event;
struct internal_base;
struct internal_timer;
struct internal_timer; /* A sub struct of the comm_timer super struct */
/** callback from communication point function type */
typedef int comm_point_callback_t(struct comm_point*, void*, int,
typedef int comm_point_callback_type(struct comm_point*, void*, int,
struct comm_reply*);
/** to pass no_error to callback function */
@ -114,6 +116,13 @@ struct comm_reply {
socklen_t addrlen;
/** return type 0 (none), 4(IP4), 6(IP6) */
int srctype;
/* DnsCrypt context */
#ifdef USE_DNSCRYPT
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES];
uint8_t nmkey[crypto_box_BEFORENMBYTES];
const KeyPair *keypair;
int is_dnscrypted;
#endif
/** the return source interface data */
union {
#ifdef IPV6_PKTINFO
@ -127,6 +136,8 @@ struct comm_reply {
}
/** variable with return source data */
pktinfo;
/** max udp size for udp packets */
size_t max_udp_size;
};
/**
@ -225,9 +236,23 @@ struct comm_point {
So that when that is done the callback is called. */
int tcp_do_toggle_rw;
/** timeout in msec for TCP wait times for this connection */
int tcp_timeout_msec;
/** if set, checks for pending error from nonblocking connect() call.*/
int tcp_check_nb_connect;
#ifdef USE_MSG_FASTOPEN
/** used to track if the sendto() call should be done when using TFO. */
int tcp_do_fastopen;
#endif
#ifdef USE_DNSCRYPT
/** Is this a dnscrypt channel */
int dnscrypt;
/** encrypted buffer pointer. Either to perthread, or own buffer or NULL */
struct sldns_buffer* dnscrypt_buffer;
#endif
/** number of queries outstanding on this socket, used by
* outside network for udp ports */
int inuse;
@ -256,7 +281,7 @@ struct comm_point {
For UDP this is done without changing the commpoint.
In TCP it sets write state.
*/
comm_point_callback_t* callback;
comm_point_callback_type* callback;
/** argument to pass to callback. */
void *cb_arg;
};
@ -265,7 +290,7 @@ struct comm_point {
* Structure only for making timeout events.
*/
struct comm_timer {
/** the internal event stuff */
/** the internal event stuff (derived) */
struct internal_timer* ev_timer;
/** callback function, takes user arg only */
@ -301,12 +326,12 @@ struct comm_signal {
struct comm_base* comm_base_create(int sigs);
/**
* Create comm base that uses the given event_base (underlying event
* mechanism pointer).
* @param base: underlying lib event base.
* Create comm base that uses the given ub_event_base (underlying pluggable
* event mechanism pointer).
* @param base: underlying pluggable event base.
* @return: the new comm base. NULL on error.
*/
struct comm_base* comm_base_create_event(struct event_base* base);
struct comm_base* comm_base_create_event(struct ub_event_base* base);
/**
* Delete comm base structure but not the underlying lib event base.
@ -357,9 +382,9 @@ void comm_base_set_slow_accept_handlers(struct comm_base* b,
/**
* Access internal data structure (for util/tube.c on windows)
* @param b: comm base
* @return event_base. Could be libevent, or internal event handler.
* @return ub_event_base.
*/
struct event_base* comm_base_internal(struct comm_base* b);
struct ub_event_base* comm_base_internal(struct comm_base* b);
/**
* Create an UDP comm point. Calls malloc.
@ -374,7 +399,7 @@ struct event_base* comm_base_internal(struct comm_base* b);
*/
struct comm_point* comm_point_create_udp(struct comm_base* base,
int fd, struct sldns_buffer* buffer,
comm_point_callback_t* callback, void* callback_arg);
comm_point_callback_type* callback, void* callback_arg);
/**
* Create an UDP with ancillary data comm point. Calls malloc.
@ -390,7 +415,7 @@ struct comm_point* comm_point_create_udp(struct comm_base* base,
*/
struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
int fd, struct sldns_buffer* buffer,
comm_point_callback_t* callback, void* callback_arg);
comm_point_callback_type* callback, void* callback_arg);
/**
* Create a TCP listener comm point. Calls malloc.
@ -411,7 +436,7 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
*/
struct comm_point* comm_point_create_tcp(struct comm_base* base,
int fd, int num, size_t bufsize,
comm_point_callback_t* callback, void* callback_arg);
comm_point_callback_type* callback, void* callback_arg);
/**
* Create an outgoing TCP commpoint. No file descriptor is opened, left at -1.
@ -422,7 +447,7 @@ struct comm_point* comm_point_create_tcp(struct comm_base* base,
* @return: the commpoint or NULL on error.
*/
struct comm_point* comm_point_create_tcp_out(struct comm_base* base,
size_t bufsize, comm_point_callback_t* callback, void* callback_arg);
size_t bufsize, comm_point_callback_type* callback, void* callback_arg);
/**
* Create commpoint to listen to a local domain file descriptor.
@ -435,7 +460,7 @@ struct comm_point* comm_point_create_tcp_out(struct comm_base* base,
*/
struct comm_point* comm_point_create_local(struct comm_base* base,
int fd, size_t bufsize,
comm_point_callback_t* callback, void* callback_arg);
comm_point_callback_type* callback, void* callback_arg);
/**
* Create commpoint to listen to a local domain pipe descriptor.
@ -448,7 +473,7 @@ struct comm_point* comm_point_create_local(struct comm_base* base,
*/
struct comm_point* comm_point_create_raw(struct comm_base* base,
int fd, int writing,
comm_point_callback_t* callback, void* callback_arg);
comm_point_callback_type* callback, void* callback_arg);
/**
* Close a comm point fd.
@ -496,9 +521,10 @@ void comm_point_stop_listening(struct comm_point* c);
* Start listening again for input on the comm point.
* @param c: commpoint to enable again.
* @param newfd: new fd, or -1 to leave fd be.
* @param sec: timeout in seconds, or -1 for no (change to the) timeout.
* @param msec: timeout in milliseconds, or -1 for no (change to the) timeout.
* So seconds*1000.
*/
void comm_point_start_listening(struct comm_point* c, int newfd, int sec);
void comm_point_start_listening(struct comm_point* c, int newfd, int msec);
/**
* Stop listening and start listening again for reading or writing.

View file

@ -50,7 +50,7 @@
#define RED 1
/** the NULL node, global alloc */
rbnode_t rbtree_null_node = {
rbnode_type rbtree_null_node = {
RBTREE_NULL, /* Parent. */
RBTREE_NULL, /* Left. */
RBTREE_NULL, /* Right. */
@ -59,13 +59,14 @@ rbnode_t rbtree_null_node = {
};
/** rotate subtree left (to preserve redblack property) */
static void rbtree_rotate_left(rbtree_t *rbtree, rbnode_t *node);
static void rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node);
/** rotate subtree right (to preserve redblack property) */
static void rbtree_rotate_right(rbtree_t *rbtree, rbnode_t *node);
static void rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node);
/** Fixup node colours when insert happened */
static void rbtree_insert_fixup(rbtree_t *rbtree, rbnode_t *node);
static void rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node);
/** Fixup node colours when delete happened */
static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* child_parent);
static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child,
rbnode_type* child_parent);
/*
* Creates a new red black tree, initializes and returns a pointer to it.
@ -73,13 +74,13 @@ static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* chi
* Return NULL on failure.
*
*/
rbtree_t *
rbtree_type *
rbtree_create (int (*cmpf)(const void *, const void *))
{
rbtree_t *rbtree;
rbtree_type *rbtree;
/* Allocate memory for it */
rbtree = (rbtree_t *) malloc(sizeof(rbtree_t));
rbtree = (rbtree_type *) malloc(sizeof(rbtree_type));
if (!rbtree) {
return NULL;
}
@ -91,7 +92,7 @@ rbtree_create (int (*cmpf)(const void *, const void *))
}
void
rbtree_init(rbtree_t *rbtree, int (*cmpf)(const void *, const void *))
rbtree_init(rbtree_type *rbtree, int (*cmpf)(const void *, const void *))
{
/* Initialize it */
rbtree->root = RBTREE_NULL;
@ -104,9 +105,9 @@ rbtree_init(rbtree_t *rbtree, int (*cmpf)(const void *, const void *))
*
*/
static void
rbtree_rotate_left(rbtree_t *rbtree, rbnode_t *node)
rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node)
{
rbnode_t *right = node->right;
rbnode_type *right = node->right;
node->right = right->left;
if (right->left != RBTREE_NULL)
right->left->parent = node;
@ -131,9 +132,9 @@ rbtree_rotate_left(rbtree_t *rbtree, rbnode_t *node)
*
*/
static void
rbtree_rotate_right(rbtree_t *rbtree, rbnode_t *node)
rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node)
{
rbnode_t *left = node->left;
rbnode_type *left = node->left;
node->left = left->right;
if (left->right != RBTREE_NULL)
left->right->parent = node;
@ -154,9 +155,9 @@ rbtree_rotate_right(rbtree_t *rbtree, rbnode_t *node)
}
static void
rbtree_insert_fixup(rbtree_t *rbtree, rbnode_t *node)
rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node)
{
rbnode_t *uncle;
rbnode_type *uncle;
/* While not at the root and need fixing... */
while (node != rbtree->root && node->parent->color == RED) {
@ -223,15 +224,15 @@ rbtree_insert_fixup(rbtree_t *rbtree, rbnode_t *node)
* Returns NULL on failure or the pointer to the newly added node
* otherwise.
*/
rbnode_t *
rbtree_insert (rbtree_t *rbtree, rbnode_t *data)
rbnode_type *
rbtree_insert (rbtree_type *rbtree, rbnode_type *data)
{
/* XXX Not necessary, but keeps compiler quiet... */
int r = 0;
/* We start at the root of the tree */
rbnode_t *node = rbtree->root;
rbnode_t *parent = RBTREE_NULL;
rbnode_type *node = rbtree->root;
rbnode_type *parent = RBTREE_NULL;
fptr_ok(fptr_whitelist_rbtree_cmp(rbtree->cmp));
/* Lets find the new parent... */
@ -276,10 +277,10 @@ rbtree_insert (rbtree_t *rbtree, rbnode_t *data)
* Searches the red black tree, returns the data if key is found or NULL otherwise.
*
*/
rbnode_t *
rbtree_search (rbtree_t *rbtree, const void *key)
rbnode_type *
rbtree_search (rbtree_type *rbtree, const void *key)
{
rbnode_t *node;
rbnode_type *node;
if (rbtree_find_less_equal(rbtree, key, &node)) {
return node;
@ -295,13 +296,14 @@ static void swap_int8(uint8_t* x, uint8_t* y)
}
/** helpers for delete: swap node pointers */
static void swap_np(rbnode_t** x, rbnode_t** y)
static void swap_np(rbnode_type** x, rbnode_type** y)
{
rbnode_t* t = *x; *x = *y; *y = t;
rbnode_type* t = *x; *x = *y; *y = t;
}
/** Update parent pointers of child trees of 'parent' */
static void change_parent_ptr(rbtree_t* rbtree, rbnode_t* parent, rbnode_t* old, rbnode_t* new)
static void change_parent_ptr(rbtree_type* rbtree, rbnode_type* parent,
rbnode_type* old, rbnode_type* new)
{
if(parent == RBTREE_NULL)
{
@ -315,18 +317,19 @@ static void change_parent_ptr(rbtree_t* rbtree, rbnode_t* parent, rbnode_t* old,
if(parent->right == old) parent->right = new;
}
/** Update parent pointer of a node 'child' */
static void change_child_ptr(rbnode_t* child, rbnode_t* old, rbnode_t* new)
static void change_child_ptr(rbnode_type* child, rbnode_type* old,
rbnode_type* new)
{
if(child == RBTREE_NULL) return;
log_assert(child->parent == old || child->parent == new);
if(child->parent == old) child->parent = new;
}
rbnode_t*
rbtree_delete(rbtree_t *rbtree, const void *key)
rbnode_type*
rbtree_delete(rbtree_type *rbtree, const void *key)
{
rbnode_t *to_delete;
rbnode_t *child;
rbnode_type *to_delete;
rbnode_type *child;
if((to_delete = rbtree_search(rbtree, key)) == 0) return 0;
rbtree->count--;
@ -334,11 +337,11 @@ rbtree_delete(rbtree_t *rbtree, const void *key)
if(to_delete->left != RBTREE_NULL && to_delete->right != RBTREE_NULL)
{
/* swap with smallest from right subtree (or largest from left) */
rbnode_t *smright = to_delete->right;
rbnode_type *smright = to_delete->right;
while(smright->left != RBTREE_NULL)
smright = smright->left;
/* swap the smright and to_delete elements in the tree,
* but the rbnode_t is first part of user data struct
* but the rbnode_type is first part of user data struct
* so cannot just swap the keys and data pointers. Instead
* readjust the pointers left,right,parent */
@ -400,9 +403,10 @@ rbtree_delete(rbtree_t *rbtree, const void *key)
return to_delete;
}
static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* child_parent)
static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child,
rbnode_type* child_parent)
{
rbnode_t* sibling;
rbnode_type* sibling;
int go_up = 1;
/* determine sibling to the node that is one-black short */
@ -504,10 +508,11 @@ static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* chi
}
int
rbtree_find_less_equal(rbtree_t *rbtree, const void *key, rbnode_t **result)
rbtree_find_less_equal(rbtree_type *rbtree, const void *key,
rbnode_type **result)
{
int r;
rbnode_t *node;
rbnode_type *node;
log_assert(result);
@ -540,19 +545,19 @@ rbtree_find_less_equal(rbtree_t *rbtree, const void *key, rbnode_t **result)
* Finds the first element in the red black tree
*
*/
rbnode_t *
rbtree_first (rbtree_t *rbtree)
rbnode_type *
rbtree_first (rbtree_type *rbtree)
{
rbnode_t *node;
rbnode_type *node;
for (node = rbtree->root; node->left != RBTREE_NULL; node = node->left);
return node;
}
rbnode_t *
rbtree_last (rbtree_t *rbtree)
rbnode_type *
rbtree_last (rbtree_type *rbtree)
{
rbnode_t *node;
rbnode_type *node;
for (node = rbtree->root; node->right != RBTREE_NULL; node = node->right);
return node;
@ -562,10 +567,10 @@ rbtree_last (rbtree_t *rbtree)
* Returns the next node...
*
*/
rbnode_t *
rbtree_next (rbnode_t *node)
rbnode_type *
rbtree_next (rbnode_type *node)
{
rbnode_t *parent;
rbnode_type *parent;
if (node->right != RBTREE_NULL) {
/* One right, then keep on going left... */
@ -581,10 +586,10 @@ rbtree_next (rbnode_t *node)
return node;
}
rbnode_t *
rbtree_previous(rbnode_t *node)
rbnode_type *
rbtree_previous(rbnode_type *node)
{
rbnode_t *parent;
rbnode_type *parent;
if (node->left != RBTREE_NULL) {
/* One left, then keep on going right... */
@ -602,7 +607,7 @@ rbtree_previous(rbnode_t *node)
/** recursive descent traverse */
static void
traverse_post(void (*func)(rbnode_t*, void*), void* arg, rbnode_t* node)
traverse_post(void (*func)(rbnode_type*, void*), void* arg, rbnode_type* node)
{
if(!node || node == RBTREE_NULL)
return;
@ -614,7 +619,8 @@ traverse_post(void (*func)(rbnode_t*, void*), void* arg, rbnode_t* node)
}
void
traverse_postorder(rbtree_t* tree, void (*func)(rbnode_t*, void*), void* arg)
traverse_postorder(rbtree_type* tree, void (*func)(rbnode_type*, void*),
void* arg)
{
traverse_post(func, arg, tree->root);
}

View file

@ -45,40 +45,40 @@
/**
* This structure must be the first member of the data structure in
* the rbtree. This allows easy casting between an rbnode_t and the
* the rbtree. This allows easy casting between an rbnode_type and the
* user data (poor man's inheritance).
*/
typedef struct rbnode_t rbnode_t;
typedef struct rbnode_type rbnode_type;
/**
* The rbnode_t struct definition.
* The rbnode_type struct definition.
*/
struct rbnode_t {
struct rbnode_type {
/** parent in rbtree, RBTREE_NULL for root */
rbnode_t *parent;
rbnode_type *parent;
/** left node (smaller items) */
rbnode_t *left;
rbnode_type *left;
/** right node (larger items) */
rbnode_t *right;
rbnode_type *right;
/** pointer to sorting key */
const void *key;
const void *key;
/** colour of this node */
uint8_t color;
uint8_t color;
};
/** The nullpointer, points to empty node */
#define RBTREE_NULL &rbtree_null_node
/** the global empty node */
extern rbnode_t rbtree_null_node;
extern rbnode_type rbtree_null_node;
/** An entire red black tree */
typedef struct rbtree_t rbtree_t;
typedef struct rbtree_type rbtree_type;
/** definition for tree struct */
struct rbtree_t {
struct rbtree_type {
/** The root of the red-black tree */
rbnode_t *root;
rbnode_type *root;
/** The number of the nodes in the tree */
size_t count;
size_t count;
/**
* Key compare function. <0,0,>0 like strcmp.
@ -92,14 +92,14 @@ struct rbtree_t {
* @param cmpf: compare function (like strcmp) takes pointers to two keys.
* @return: new tree, empty.
*/
rbtree_t *rbtree_create(int (*cmpf)(const void *, const void *));
rbtree_type *rbtree_create(int (*cmpf)(const void *, const void *));
/**
* Init a new tree (malloced by caller) with given key compare function.
* @param rbtree: uninitialised memory for new tree, returned empty.
* @param cmpf: compare function (like strcmp) takes pointers to two keys.
*/
void rbtree_init(rbtree_t *rbtree, int (*cmpf)(const void *, const void *));
void rbtree_init(rbtree_type *rbtree, int (*cmpf)(const void *, const void *));
/**
* Insert data into the tree.
@ -107,7 +107,7 @@ void rbtree_init(rbtree_t *rbtree, int (*cmpf)(const void *, const void *));
* @param data: element to insert.
* @return: data ptr or NULL if key already present.
*/
rbnode_t *rbtree_insert(rbtree_t *rbtree, rbnode_t *data);
rbnode_type *rbtree_insert(rbtree_type *rbtree, rbnode_type *data);
/**
* Delete element from tree.
@ -116,7 +116,7 @@ rbnode_t *rbtree_insert(rbtree_t *rbtree, rbnode_t *data);
* @return: node that is now unlinked from the tree. User to delete it.
* returns 0 if node not present
*/
rbnode_t *rbtree_delete(rbtree_t *rbtree, const void *key);
rbnode_type *rbtree_delete(rbtree_type *rbtree, const void *key);
/**
* Find key in tree. Returns NULL if not found.
@ -124,7 +124,7 @@ rbnode_t *rbtree_delete(rbtree_t *rbtree, const void *key);
* @param key: key that must match.
* @return: node that fits or NULL.
*/
rbnode_t *rbtree_search(rbtree_t *rbtree, const void *key);
rbnode_type *rbtree_search(rbtree_type *rbtree, const void *key);
/**
* Find, but match does not have to be exact.
@ -135,45 +135,45 @@ rbnode_t *rbtree_search(rbtree_t *rbtree, const void *key);
* @return: true if exact match in result. Else result points to <= element,
* or NULL if key is smaller than the smallest key.
*/
int rbtree_find_less_equal(rbtree_t *rbtree, const void *key,
rbnode_t **result);
int rbtree_find_less_equal(rbtree_type *rbtree, const void *key,
rbnode_type **result);
/**
* Returns first (smallest) node in the tree
* @param rbtree: tree
* @return: smallest element or NULL if tree empty.
*/
rbnode_t *rbtree_first(rbtree_t *rbtree);
rbnode_type *rbtree_first(rbtree_type *rbtree);
/**
* Returns last (largest) node in the tree
* @param rbtree: tree
* @return: largest element or NULL if tree empty.
*/
rbnode_t *rbtree_last(rbtree_t *rbtree);
rbnode_type *rbtree_last(rbtree_type *rbtree);
/**
* Returns next larger node in the tree
* @param rbtree: tree
* @return: next larger element or NULL if no larger in tree.
*/
rbnode_t *rbtree_next(rbnode_t *rbtree);
rbnode_type *rbtree_next(rbnode_type *rbtree);
/**
* Returns previous smaller node in the tree
* @param rbtree: tree
* @return: previous smaller element or NULL if no previous in tree.
*/
rbnode_t *rbtree_previous(rbnode_t *rbtree);
rbnode_type *rbtree_previous(rbnode_type *rbtree);
/**
* Call with node=variable of struct* with rbnode_t as first element.
* Call with node=variable of struct* with rbnode_type as first element.
* with type is the type of a pointer to that struct.
*/
#define RBTREE_FOR(node, type, rbtree) \
for(node=(type)rbtree_first(rbtree); \
(rbnode_t*)node != RBTREE_NULL; \
node = (type)rbtree_next((rbnode_t*)node))
(rbnode_type*)node != RBTREE_NULL; \
node = (type)rbtree_next((rbnode_type*)node))
/**
* Call function for all elements in the redblack tree, such that
@ -186,7 +186,7 @@ rbnode_t *rbtree_previous(rbnode_t *rbtree);
* The function must not alter the rbtree.
* @param arg: user argument.
*/
void traverse_postorder(rbtree_t* tree, void (*func)(rbnode_t*, void*),
void traverse_postorder(rbtree_type* tree, void (*func)(rbnode_type*, void*),
void* arg);
#endif /* UTIL_RBTREE_H_ */

View file

@ -0,0 +1,286 @@
/*
* util/shm_side/shm_main.c - SHM for statistics transport
*
* Copyright (c) 2017, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions for the SHM implementation.
*/
#include "config.h"
#include <ctype.h>
#include <stdarg.h>
#ifdef HAVE_SYS_IPC_H
#include <sys/ipc.h>
#endif
#ifdef HAVE_SYS_SHM_H
#include <sys/shm.h>
#endif
#include <sys/time.h>
#include <errno.h>
#include "shm_main.h"
#include "daemon/daemon.h"
#include "daemon/worker.h"
#include "daemon/stats.h"
#include "services/mesh.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "validator/validator.h"
#include "util/config_file.h"
#include "util/fptr_wlist.h"
#include "util/log.h"
#ifdef HAVE_SHMGET
/** subtract timers and the values do not overflow or become negative */
static void
timeval_subtract(struct timeval* d, const struct timeval* end,
const struct timeval* start)
{
#ifndef S_SPLINT_S
time_t end_usec = end->tv_usec;
d->tv_sec = end->tv_sec - start->tv_sec;
if(end_usec < start->tv_usec) {
end_usec += 1000000;
d->tv_sec--;
}
d->tv_usec = end_usec - start->tv_usec;
#endif
}
#endif /* HAVE_SHMGET */
int shm_main_init(struct daemon* daemon)
{
#ifdef HAVE_SHMGET
struct shm_stat_info *shm_stat;
size_t shm_size;
/* sanitize */
if(!daemon)
return 0;
if(!daemon->cfg->shm_enable)
return 1;
if(daemon->cfg->stat_interval == 0)
log_warn("shm-enable is yes but statistics-interval is 0");
/* Statistics to maintain the number of thread + total */
shm_size = (sizeof(struct stats_info) * (daemon->num + 1));
/* Allocation of needed memory */
daemon->shm_info = (struct shm_main_info*)calloc(1, shm_size);
/* Sanitize */
if(!daemon->shm_info) {
log_err("shm fail: malloc failure");
return 0;
}
daemon->shm_info->key = daemon->cfg->shm_key;
/* Check for previous create SHM */
daemon->shm_info->id_ctl = shmget(daemon->shm_info->key, sizeof(int), SHM_R);
daemon->shm_info->id_arr = shmget(daemon->shm_info->key + 1, sizeof(int), SHM_R);
/* Destroy previous SHM */
if (daemon->shm_info->id_ctl >= 0)
shmctl(daemon->shm_info->id_ctl, IPC_RMID, NULL);
/* Destroy previous SHM */
if (daemon->shm_info->id_arr >= 0)
shmctl(daemon->shm_info->id_arr, IPC_RMID, NULL);
/* SHM: Create the segment */
daemon->shm_info->id_ctl = shmget(daemon->shm_info->key, sizeof(struct shm_stat_info), IPC_CREAT | 0666);
if (daemon->shm_info->id_ctl < 0)
{
log_err("SHM failed(id_ctl) cannot shmget(key %d) %s",
daemon->shm_info->key, strerror(errno));
/* Just release memory unused */
free(daemon->shm_info);
return 0;
}
daemon->shm_info->id_arr = shmget(daemon->shm_info->key + 1, shm_size, IPC_CREAT | 0666);
if (daemon->shm_info->id_arr < 0)
{
log_err("SHM failed(id_arr) cannot shmget(key %d + 1) %s",
daemon->shm_info->key, strerror(errno));
/* Just release memory unused */
free(daemon->shm_info);
return 0;
}
/* SHM: attach the segment */
daemon->shm_info->ptr_ctl = (struct shm_stat_info*)
shmat(daemon->shm_info->id_ctl, NULL, 0);
if(daemon->shm_info->ptr_ctl == (void *) -1) {
log_err("SHM failed(ctl) cannot shmat(%d) %s",
daemon->shm_info->id_ctl, strerror(errno));
/* Just release memory unused */
free(daemon->shm_info);
return 0;
}
daemon->shm_info->ptr_arr = (struct stats_info*)
shmat(daemon->shm_info->id_arr, NULL, 0);
if (daemon->shm_info->ptr_arr == (void *) -1)
{
log_err("SHM failed(arr) cannot shmat(%d) %s",
daemon->shm_info->id_arr, strerror(errno));
/* Just release memory unused */
free(daemon->shm_info);
return 0;
}
/* Zero fill SHM to stand clean while is not filled by other events */
memset(daemon->shm_info->ptr_ctl, 0, sizeof(struct shm_stat_info));
memset(daemon->shm_info->ptr_arr, 0, shm_size);
shm_stat = daemon->shm_info->ptr_ctl;
shm_stat->num_threads = daemon->num;
#else
(void)daemon;
#endif /* HAVE_SHMGET */
return 1;
}
void shm_main_shutdown(struct daemon* daemon)
{
#ifdef HAVE_SHMGET
/* web are OK, just disabled */
if(!daemon->cfg->shm_enable)
return;
verbose(VERB_DETAIL, "SHM shutdown - KEY [%d] - ID CTL [%d] ARR [%d] - PTR CTL [%p] ARR [%p]",
daemon->shm_info->key, daemon->shm_info->id_ctl, daemon->shm_info->id_arr, daemon->shm_info->ptr_ctl, daemon->shm_info->ptr_arr);
/* Destroy previous SHM */
if (daemon->shm_info->id_ctl >= 0)
shmctl(daemon->shm_info->id_ctl, IPC_RMID, NULL);
if (daemon->shm_info->id_arr >= 0)
shmctl(daemon->shm_info->id_arr, IPC_RMID, NULL);
if (daemon->shm_info->ptr_ctl)
shmdt(daemon->shm_info->ptr_ctl);
if (daemon->shm_info->ptr_arr)
shmdt(daemon->shm_info->ptr_arr);
#else
(void)daemon;
#endif /* HAVE_SHMGET */
}
void shm_main_run(struct worker *worker)
{
#ifdef HAVE_SHMGET
struct shm_stat_info *shm_stat;
struct stats_info *stat_total;
struct stats_info *stat_info;
int modstack;
int offset;
verbose(VERB_DETAIL, "SHM run - worker [%d] - daemon [%p] - timenow(%u) - timeboot(%u)",
worker->thread_num, worker->daemon, (unsigned)worker->env.now_tv->tv_sec, (unsigned)worker->daemon->time_boot.tv_sec);
offset = worker->thread_num + 1;
stat_total = worker->daemon->shm_info->ptr_arr;
stat_info = worker->daemon->shm_info->ptr_arr + offset;
/* Copy data to the current position */
server_stats_compile(worker, stat_info, 0);
/* First thread, zero fill total, and copy general info */
if (worker->thread_num == 0) {
/* Copy data to the current position */
memset(stat_total, 0, sizeof(struct stats_info));
/* Point to data into SHM */
shm_stat = worker->daemon->shm_info->ptr_ctl;
shm_stat->time.now = *worker->env.now_tv;
timeval_subtract(&shm_stat->time.up, &shm_stat->time.now, &worker->daemon->time_boot);
timeval_subtract(&shm_stat->time.elapsed, &shm_stat->time.now, &worker->daemon->time_last_stat);
shm_stat->mem.msg = slabhash_get_mem(worker->env.msg_cache);
shm_stat->mem.rrset = slabhash_get_mem(&worker->env.rrset_cache->table);
shm_stat->mem.val = 0;
shm_stat->mem.iter = 0;
modstack = modstack_find(&worker->env.mesh->mods, "validator");
if(modstack != -1) {
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->mods.mod[modstack]->get_mem));
shm_stat->mem.val = (*worker->env.mesh->mods.mod[modstack]->get_mem)(&worker->env, modstack);
}
modstack = modstack_find(&worker->env.mesh->mods, "iterator");
if(modstack != -1) {
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->mods.mod[modstack]->get_mem));
shm_stat->mem.iter = (*worker->env.mesh->mods.mod[modstack]->get_mem)(&worker->env, modstack);
}
/* subnet mem value is available in shm, also when not enabled,
* to make the struct easier to memmap by other applications,
* independent of the configuration of unbound */
shm_stat->mem.subnet = 0;
#ifdef CLIENT_SUBNET
modstack = modstack_find(&worker->env.mesh->mods, "subnet");
if(modstack != -1) {
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->mods.mod[modstack]->get_mem));
shm_stat->mem.subnet = (*worker->env.mesh->mods.mod[modstack]->get_mem)(&worker->env, modstack);
}
#endif
}
server_stats_add(stat_total, stat_info);
/* print the thread statistics */
stat_total->mesh_time_median /= (double)worker->daemon->num;
#else
(void)worker;
#endif /* HAVE_SHMGET */
}

View file

@ -0,0 +1,86 @@
/*
* util/shm_side/shm_main.h - control the shared memory for unbound.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions for the SHM side.
*/
#ifndef UTIL_SHM_SIDE_MAIN_H
#define UTIL_SHM_SIDE_MAIN_H
struct daemon;
struct worker;
/** Some global statistics that are not in struct stats_info,
* this struct is shared on a shm segment */
struct shm_stat_info {
int num_threads;
struct {
struct timeval now;
struct timeval up;
struct timeval elapsed;
} time;
struct {
size_t msg;
size_t rrset;
size_t val;
size_t iter;
size_t subnet;
} mem;
};
/**
* The SHM info.
*/
struct shm_main_info {
/** stats_info array, shared memory segment.
* [0] is totals, [1..thread_num] are per-thread stats */
struct stats_info* ptr_arr;
/** the global stats block, shared memory segment */
struct shm_stat_info* ptr_ctl;
int key;
int id_ctl;
int id_arr;
};
int shm_main_init(struct daemon* daemon);
void shm_main_shutdown(struct daemon* daemon);
void shm_main_run(struct worker *worker);
#endif /* UTIL_SHM_SIDE_MAIN_H */

View file

@ -71,17 +71,17 @@ int addr_tree_compare(const void* k1, const void* k2)
return 0;
}
void name_tree_init(rbtree_t* tree)
void name_tree_init(rbtree_type* tree)
{
rbtree_init(tree, &name_tree_compare);
}
void addr_tree_init(rbtree_t* tree)
void addr_tree_init(rbtree_type* tree)
{
rbtree_init(tree, &addr_tree_compare);
}
int name_tree_insert(rbtree_t* tree, struct name_tree_node* node,
int name_tree_insert(rbtree_type* tree, struct name_tree_node* node,
uint8_t* name, size_t len, int labs, uint16_t dclass)
{
node->node.key = node;
@ -93,7 +93,7 @@ int name_tree_insert(rbtree_t* tree, struct name_tree_node* node,
return rbtree_insert(tree, &node->node) != NULL;
}
int addr_tree_insert(rbtree_t* tree, struct addr_tree_node* node,
int addr_tree_insert(rbtree_type* tree, struct addr_tree_node* node,
struct sockaddr_storage* addr, socklen_t addrlen, int net)
{
node->node.key = node;
@ -104,7 +104,7 @@ int addr_tree_insert(rbtree_t* tree, struct addr_tree_node* node,
return rbtree_insert(tree, &node->node) != NULL;
}
void addr_tree_init_parents(rbtree_t* tree)
void addr_tree_init_parents(rbtree_type* tree)
{
struct addr_tree_node* node, *prev = NULL, *p;
int m;
@ -130,7 +130,7 @@ void addr_tree_init_parents(rbtree_t* tree)
}
}
void name_tree_init_parents(rbtree_t* tree)
void name_tree_init_parents(rbtree_type* tree)
{
struct name_tree_node* node, *prev = NULL, *p;
int m;
@ -156,7 +156,7 @@ void name_tree_init_parents(rbtree_t* tree)
}
}
struct name_tree_node* name_tree_find(rbtree_t* tree, uint8_t* name,
struct name_tree_node* name_tree_find(rbtree_type* tree, uint8_t* name,
size_t len, int labs, uint16_t dclass)
{
struct name_tree_node key;
@ -168,10 +168,10 @@ struct name_tree_node* name_tree_find(rbtree_t* tree, uint8_t* name,
return (struct name_tree_node*)rbtree_search(tree, &key);
}
struct name_tree_node* name_tree_lookup(rbtree_t* tree, uint8_t* name,
struct name_tree_node* name_tree_lookup(rbtree_type* tree, uint8_t* name,
size_t len, int labs, uint16_t dclass)
{
rbnode_t* res = NULL;
rbnode_type* res = NULL;
struct name_tree_node *result;
struct name_tree_node key;
key.node.key = &key;
@ -200,10 +200,10 @@ struct name_tree_node* name_tree_lookup(rbtree_t* tree, uint8_t* name,
return result;
}
struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
struct addr_tree_node* addr_tree_lookup(rbtree_type* tree,
struct sockaddr_storage* addr, socklen_t addrlen)
{
rbnode_t* res = NULL;
rbnode_type* res = NULL;
struct addr_tree_node* result;
struct addr_tree_node key;
key.node.key = &key;
@ -231,11 +231,24 @@ struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
return result;
}
struct addr_tree_node* addr_tree_find(rbtree_type* tree,
struct sockaddr_storage* addr, socklen_t addrlen, int net)
{
rbnode_type* res = NULL;
struct addr_tree_node key;
key.node.key = &key;
memcpy(&key.addr, addr, addrlen);
key.addrlen = addrlen;
key.net = net;
res = rbtree_search(tree, &key);
return (struct addr_tree_node*)res;
}
int
name_tree_next_root(rbtree_t* tree, uint16_t* dclass)
name_tree_next_root(rbtree_type* tree, uint16_t* dclass)
{
struct name_tree_node key;
rbnode_t* n;
rbnode_type* n;
struct name_tree_node* p;
if(*dclass == 0) {
/* first root item is first item in tree */

View file

@ -49,12 +49,12 @@
* This is not sorted canonically, but fast.
* This can be looked up to obtain a closest encloser parent name.
*
* The tree itself is a rbtree_t.
* The tree itself is a rbtree_type.
* This is the element node put as first entry in the client structure.
*/
struct name_tree_node {
/** rbtree node, key is this struct : dclass and name */
rbnode_t node;
rbnode_type node;
/** parent in tree */
struct name_tree_node* parent;
/** name in uncompressed wireformat */
@ -71,12 +71,12 @@ struct name_tree_node {
* Tree of IP addresses. Sorted first by protocol, then by bits.
* This can be looked up to obtain the enclosing subnet.
*
* The tree itself is a rbtree_t.
* The tree itself is a rbtree_type.
* This is the element node put as first entry in the client structure.
*/
struct addr_tree_node {
/** rbtree node, key is this struct : proto and subnet */
rbnode_t node;
rbnode_type node;
/** parent in tree */
struct addr_tree_node* parent;
/** address */
@ -91,7 +91,7 @@ struct addr_tree_node {
* Init a name tree to be empty
* @param tree: to init.
*/
void name_tree_init(rbtree_t* tree);
void name_tree_init(rbtree_type* tree);
/**
* insert element into name tree.
@ -105,7 +105,7 @@ void name_tree_init(rbtree_t* tree);
* @param dclass: class of name
* @return false on error (duplicate element).
*/
int name_tree_insert(rbtree_t* tree, struct name_tree_node* node,
int name_tree_insert(rbtree_type* tree, struct name_tree_node* node,
uint8_t* name, size_t len, int labs, uint16_t dclass);
/**
@ -113,7 +113,7 @@ int name_tree_insert(rbtree_t* tree, struct name_tree_node* node,
* Should be performed after insertions are done, before lookups
* @param tree: name tree
*/
void name_tree_init_parents(rbtree_t* tree);
void name_tree_init_parents(rbtree_type* tree);
/**
* Lookup exact match in name tree
@ -124,7 +124,7 @@ void name_tree_init_parents(rbtree_t* tree);
* @param dclass: class of name
* @return node or NULL if not found.
*/
struct name_tree_node* name_tree_find(rbtree_t* tree, uint8_t* name,
struct name_tree_node* name_tree_find(rbtree_type* tree, uint8_t* name,
size_t len, int labs, uint16_t dclass);
/**
@ -136,7 +136,7 @@ struct name_tree_node* name_tree_find(rbtree_t* tree, uint8_t* name,
* @param dclass: class of name
* @return closest enclosing node (could be equal) or NULL if not found.
*/
struct name_tree_node* name_tree_lookup(rbtree_t* tree, uint8_t* name,
struct name_tree_node* name_tree_lookup(rbtree_type* tree, uint8_t* name,
size_t len, int labs, uint16_t dclass);
/**
@ -145,13 +145,13 @@ struct name_tree_node* name_tree_lookup(rbtree_t* tree, uint8_t* name,
* @param dclass: the class to look for next (or higher).
* @return false if no classes found, true means class put into c.
*/
int name_tree_next_root(rbtree_t* tree, uint16_t* dclass);
int name_tree_next_root(rbtree_type* tree, uint16_t* dclass);
/**
* Init addr tree to be empty.
* @param tree: to init.
*/
void addr_tree_init(rbtree_t* tree);
void addr_tree_init(rbtree_type* tree);
/**
* insert element into addr tree.
@ -163,7 +163,7 @@ void addr_tree_init(rbtree_t* tree);
* @param net: size of subnet.
* @return false on error (duplicate element).
*/
int addr_tree_insert(rbtree_t* tree, struct addr_tree_node* node,
int addr_tree_insert(rbtree_type* tree, struct addr_tree_node* node,
struct sockaddr_storage* addr, socklen_t addrlen, int net);
/**
@ -171,7 +171,7 @@ int addr_tree_insert(rbtree_t* tree, struct addr_tree_node* node,
* Should be performed after insertions are done, before lookups
* @param tree: addr tree
*/
void addr_tree_init_parents(rbtree_t* tree);
void addr_tree_init_parents(rbtree_type* tree);
/**
* Lookup closest encloser in addr tree.
@ -180,9 +180,20 @@ void addr_tree_init_parents(rbtree_t* tree);
* @param addrlen: length of addr
* @return closest enclosing node (could be equal) or NULL if not found.
*/
struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
struct addr_tree_node* addr_tree_lookup(rbtree_type* tree,
struct sockaddr_storage* addr, socklen_t addrlen);
/**
* Find element in addr tree. (search a netblock, not a match for an address)
* @param tree: addr tree
* @param addr: netblock to lookup.
* @param addrlen: length of addr
* @param net: size of subnet
* @return addr tree element, or NULL if not found.
*/
struct addr_tree_node* addr_tree_find(rbtree_type* tree,
struct sockaddr_storage* addr, socklen_t addrlen, int net);
/** compare name tree nodes */
int name_tree_compare(const void* k1, const void* k2);

View file

@ -820,7 +820,7 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval)
#ifdef SELF_TEST
/* used for timings */
void driver1()
void driver1(void)
{
uint8_t buf[256];
uint32_t i;
@ -842,7 +842,7 @@ void driver1()
#define HASHLEN 1
#define MAXPAIR 60
#define MAXLEN 70
void driver2()
void driver2(void)
{
uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
@ -912,7 +912,7 @@ void driver2()
}
/* Check for reading beyond the end of the buffer and alignment problems */
void driver3()
void driver3(void)
{
uint8_t buf[MAXLEN+20], *b;
uint32_t len;
@ -1003,7 +1003,7 @@ void driver3()
}
/* check for problems with nulls */
void driver4()
void driver4(void)
{
uint8_t buf[1];
uint32_t h,i,state[HASHSTATE];
@ -1020,7 +1020,7 @@ void driver3()
}
int main()
int main(void)
{
driver1(); /* test that the key is hashed: used for timings */
driver2(); /* test that whole key is hashed thoroughly */

View file

@ -59,9 +59,10 @@ bin_init(struct lruhash_bin* array, size_t size)
}
struct lruhash*
lruhash_create(size_t start_size, size_t maxmem, lruhash_sizefunc_t sizefunc,
lruhash_compfunc_t compfunc, lruhash_delkeyfunc_t delkeyfunc,
lruhash_deldatafunc_t deldatafunc, void* arg)
lruhash_create(size_t start_size, size_t maxmem,
lruhash_sizefunc_type sizefunc, lruhash_compfunc_type compfunc,
lruhash_delkeyfunc_type delkeyfunc,
lruhash_deldatafunc_type deldatafunc, void* arg)
{
struct lruhash* table = (struct lruhash*)calloc(1,
sizeof(struct lruhash));
@ -215,7 +216,7 @@ reclaim_space(struct lruhash* table, struct lruhash_entry** list)
struct lruhash_entry*
bin_find_entry(struct lruhash* table,
struct lruhash_bin* bin, hashvalue_t hash, void* key)
struct lruhash_bin* bin, hashvalue_type hash, void* key)
{
struct lruhash_entry* p = bin->overflow_list;
while(p) {
@ -296,7 +297,7 @@ lru_touch(struct lruhash* table, struct lruhash_entry* entry)
}
void
lruhash_insert(struct lruhash* table, hashvalue_t hash,
lruhash_insert(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
{
struct lruhash_bin* bin;
@ -352,7 +353,7 @@ lruhash_insert(struct lruhash* table, hashvalue_t hash,
}
struct lruhash_entry*
lruhash_lookup(struct lruhash* table, hashvalue_t hash, void* key, int wr)
lruhash_lookup(struct lruhash* table, hashvalue_type hash, void* key, int wr)
{
struct lruhash_entry* entry;
struct lruhash_bin* bin;
@ -374,7 +375,7 @@ lruhash_lookup(struct lruhash* table, hashvalue_t hash, void* key, int wr)
}
void
lruhash_remove(struct lruhash* table, hashvalue_t hash, void* key)
lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key)
{
struct lruhash_entry* entry;
struct lruhash_bin* bin;
@ -512,7 +513,7 @@ lruhash_get_mem(struct lruhash* table)
}
void
lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_t md)
lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md)
{
lock_quick_lock(&table->lock);
table->markdelfunc = md;
@ -542,3 +543,89 @@ lruhash_traverse(struct lruhash* h, int wr,
}
lock_quick_unlock(&h->lock);
}
/*
* Demote: the opposite of touch, move an entry to the bottom
* of the LRU pile.
*/
void
lru_demote(struct lruhash* table, struct lruhash_entry* entry)
{
log_assert(table && entry);
if (entry == table->lru_end)
return; /* nothing to do */
/* remove from current lru position */
lru_remove(table, entry);
/* add at end */
entry->lru_next = NULL;
entry->lru_prev = table->lru_end;
if (table->lru_end == NULL)
{
table->lru_start = entry;
}
else
{
table->lru_end->lru_next = entry;
}
table->lru_end = entry;
}
struct lruhash_entry*
lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
{
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist = NULL;
size_t need_size;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
need_size = table->sizefunc(entry->key, data);
if (cb_arg == NULL) cb_arg = table->cb_arg;
/* find bin */
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if ((found = bin_find_entry(table, bin, hash, entry->key)) != NULL) {
/* if so: keep the existing data - acquire a writelock */
lock_rw_wrlock(&found->lock);
}
else
{
/* if not: add to bin */
entry->overflow_next = bin->overflow_list;
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
table->space_used += need_size;
/* return the entry that was presented, and lock it */
found = entry;
lock_rw_wrlock(&found->lock);
}
lock_quick_unlock(&bin->lock);
if (table->space_used > table->space_max)
reclaim_space(table, &reclaimlist);
if (table->num >= table->size)
table_grow(table);
lock_quick_unlock(&table->lock);
/* finish reclaim if any (outside of critical region) */
while (reclaimlist) {
struct lruhash_entry* n = reclaimlist->overflow_next;
void* d = reclaimlist->data;
(*table->delkeyfunc)(reclaimlist->key, cb_arg);
(*table->deldatafunc)(d, cb_arg);
reclaimlist = n;
}
/* return the entry that was selected */
return found;
}

View file

@ -116,7 +116,7 @@ struct lruhash_entry;
#define HASH_DEFAULT_MAXMEM 4*1024*1024 /* bytes */
/** the type of a hash value */
typedef uint32_t hashvalue_t;
typedef uint32_t hashvalue_type;
/**
* Type of function that calculates the size of an entry.
@ -124,39 +124,39 @@ typedef uint32_t hashvalue_t;
* Keys that are identical must also calculate to the same size.
* size = func(key, data).
*/
typedef size_t (*lruhash_sizefunc_t)(void*, void*);
typedef size_t (*lruhash_sizefunc_type)(void*, void*);
/** type of function that compares two keys. return 0 if equal. */
typedef int (*lruhash_compfunc_t)(void*, void*);
typedef int (*lruhash_compfunc_type)(void*, void*);
/** old keys are deleted.
* The RRset type has to revoke its ID number, markdel() is used first.
* This function is called: func(key, userarg) */
typedef void (*lruhash_delkeyfunc_t)(void*, void*);
typedef void (*lruhash_delkeyfunc_type)(void*, void*);
/** old data is deleted. This function is called: func(data, userarg). */
typedef void (*lruhash_deldatafunc_t)(void*, void*);
typedef void (*lruhash_deldatafunc_type)(void*, void*);
/** mark a key as pending to be deleted (and not to be used by anyone).
* called: func(key) */
typedef void (*lruhash_markdelfunc_t)(void*);
typedef void (*lruhash_markdelfunc_type)(void*);
/**
* Hash table that keeps LRU list of entries.
*/
struct lruhash {
/** lock for exclusive access, to the lookup array */
lock_quick_t lock;
lock_quick_type lock;
/** the size function for entries in this table */
lruhash_sizefunc_t sizefunc;
lruhash_sizefunc_type sizefunc;
/** the compare function for entries in this table. */
lruhash_compfunc_t compfunc;
lruhash_compfunc_type compfunc;
/** how to delete keys. */
lruhash_delkeyfunc_t delkeyfunc;
lruhash_delkeyfunc_type delkeyfunc;
/** how to delete data. */
lruhash_deldatafunc_t deldatafunc;
lruhash_deldatafunc_type deldatafunc;
/** how to mark a key pending deletion */
lruhash_markdelfunc_t markdelfunc;
lruhash_markdelfunc_type markdelfunc;
/** user argument for user functions */
void* cb_arg;
@ -188,7 +188,7 @@ struct lruhash_bin {
* Lock for exclusive access to the linked list
* This lock makes deletion of items safe in this overflow list.
*/
lock_quick_t lock;
lock_quick_type lock;
/** linked list of overflow entries */
struct lruhash_entry* overflow_list;
};
@ -207,7 +207,7 @@ struct lruhash_entry {
* Even with a writelock, you cannot change hash and key.
* You need to delete it to change hash or key.
*/
lock_rw_t lock;
lock_rw_type lock;
/** next entry in overflow chain. Covered by hashlock and binlock. */
struct lruhash_entry* overflow_next;
/** next entry in lru chain. covered by hashlock. */
@ -215,7 +215,7 @@ struct lruhash_entry {
/** prev entry in lru chain. covered by hashlock. */
struct lruhash_entry* lru_prev;
/** hash value of the key. It may not change, until entry deleted. */
hashvalue_t hash;
hashvalue_type hash;
/** key */
void* key;
/** data */
@ -236,9 +236,9 @@ struct lruhash_entry {
* @return: new hash table or NULL on malloc failure.
*/
struct lruhash* lruhash_create(size_t start_size, size_t maxmem,
lruhash_sizefunc_t sizefunc, lruhash_compfunc_t compfunc,
lruhash_delkeyfunc_t delkeyfunc, lruhash_deldatafunc_t deldatafunc,
void* arg);
lruhash_sizefunc_type sizefunc, lruhash_compfunc_type compfunc,
lruhash_delkeyfunc_type delkeyfunc,
lruhash_deldatafunc_type deldatafunc, void* arg);
/**
* Delete hash table. Entries are all deleted.
@ -269,7 +269,7 @@ void lruhash_clear(struct lruhash* table);
* @param data: the data.
* @param cb_override: if not null overrides the cb_arg for the deletefunc.
*/
void lruhash_insert(struct lruhash* table, hashvalue_t hash,
void lruhash_insert(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_override);
/**
@ -285,8 +285,8 @@ void lruhash_insert(struct lruhash* table, hashvalue_t hash,
* @return: pointer to the entry or NULL. The entry is locked.
* The user must unlock the entry when done.
*/
struct lruhash_entry* lruhash_lookup(struct lruhash* table, hashvalue_t hash,
void* key, int wr);
struct lruhash_entry* lruhash_lookup(struct lruhash* table,
hashvalue_type hash, void* key, int wr);
/**
* Touch entry, so it becomes the most recently used in the LRU list.
@ -299,7 +299,39 @@ void lru_touch(struct lruhash* table, struct lruhash_entry* entry);
/**
* Set the markdelfunction (or NULL)
*/
void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_t md);
void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md);
/************************* getdns functions ************************/
/*** these are used by getdns only and not by unbound. ***/
/**
* Demote entry, so it becomes the least recently used in the LRU list.
* Caller must hold hash table lock. The entry must be inserted already.
* @param table: hash table.
* @param entry: entry to make last in LRU.
*/
void lru_demote(struct lruhash* table, struct lruhash_entry* entry);
/**
* Insert a new element into the hashtable, or retrieve the corresponding
* element of it exits.
*
* If key is already present data pointer in that entry is kept.
* If it is not present, a new entry is created. In that case,
* the space calculation function is called with the key, data.
* If necessary the least recently used entries are deleted to make space.
* If necessary the hash array is grown up.
*
* @param table: hash table.
* @param hash: hash value. User calculates the hash.
* @param entry: identifies the entry.
* @param data: the data.
* @param cb_arg: if not null overrides the cb_arg for the deletefunc.
* @return: pointer to the existing entry if the key was already present,
* or to the entry argument if it was not.
*/
struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg);
/************************* Internal functions ************************/
/*** these are only exposed for unit tests. ***/
@ -311,7 +343,7 @@ void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_t md);
* @param hash: hash of key.
* @param key: what to look for.
*/
void lruhash_remove(struct lruhash* table, hashvalue_t hash, void* key);
void lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key);
/** init the hash bins for the table */
void bin_init(struct lruhash_bin* array, size_t size);
@ -328,7 +360,7 @@ void bin_delete(struct lruhash* table, struct lruhash_bin* bin);
* @return: the entry or NULL if not found.
*/
struct lruhash_entry* bin_find_entry(struct lruhash* table,
struct lruhash_bin* bin, hashvalue_t hash, void* key);
struct lruhash_bin* bin, hashvalue_type hash, void* key);
/**
* Remove entry from bin overflow chain.

View file

@ -46,9 +46,9 @@
#include "util/storage/slabhash.h"
struct slabhash* slabhash_create(size_t numtables, size_t start_size,
size_t maxmem, lruhash_sizefunc_t sizefunc,
lruhash_compfunc_t compfunc, lruhash_delkeyfunc_t delkeyfunc,
lruhash_deldatafunc_t deldatafunc, void* arg)
size_t maxmem, lruhash_sizefunc_type sizefunc,
lruhash_compfunc_type compfunc, lruhash_delkeyfunc_type delkeyfunc,
lruhash_deldatafunc_type deldatafunc, void* arg)
{
size_t i;
struct slabhash* sl = (struct slabhash*)calloc(1,
@ -108,24 +108,24 @@ void slabhash_clear(struct slabhash* sl)
/** helper routine to calculate the slabhash index */
static unsigned int
slab_idx(struct slabhash* sl, hashvalue_t hash)
slab_idx(struct slabhash* sl, hashvalue_type hash)
{
return ((hash & sl->mask) >> sl->shift);
}
void slabhash_insert(struct slabhash* sl, hashvalue_t hash,
void slabhash_insert(struct slabhash* sl, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* arg)
{
lruhash_insert(sl->array[slab_idx(sl, hash)], hash, entry, data, arg);
}
struct lruhash_entry* slabhash_lookup(struct slabhash* sl,
hashvalue_t hash, void* key, int wr)
hashvalue_type hash, void* key, int wr)
{
return lruhash_lookup(sl->array[slab_idx(sl, hash)], hash, key, wr);
}
void slabhash_remove(struct slabhash* sl, hashvalue_t hash, void* key)
void slabhash_remove(struct slabhash* sl, hashvalue_type hash, void* key)
{
lruhash_remove(sl->array[slab_idx(sl, hash)], hash, key);
}
@ -163,7 +163,7 @@ size_t slabhash_get_mem(struct slabhash* sl)
return total;
}
struct lruhash* slabhash_gettable(struct slabhash* sl, hashvalue_t hash)
struct lruhash* slabhash_gettable(struct slabhash* sl, hashvalue_type hash)
{
return sl->array[slab_idx(sl, hash)];
}
@ -202,7 +202,7 @@ void test_slabhash_deldata(void* data, void* ATTR_UNUSED(arg))
deldata((struct slabhash_testdata*)data);
}
void slabhash_setmarkdel(struct slabhash* sl, lruhash_markdelfunc_t md)
void slabhash_setmarkdel(struct slabhash* sl, lruhash_markdelfunc_type md)
{
size_t i;
for(i=0; i<sl->size; i++) {

View file

@ -80,9 +80,9 @@ struct slabhash {
* @return: new hash table or NULL on malloc failure.
*/
struct slabhash* slabhash_create(size_t numtables, size_t start_size,
size_t maxmem, lruhash_sizefunc_t sizefunc,
lruhash_compfunc_t compfunc, lruhash_delkeyfunc_t delkeyfunc,
lruhash_deldatafunc_t deldatafunc, void* arg);
size_t maxmem, lruhash_sizefunc_type sizefunc,
lruhash_compfunc_type compfunc, lruhash_delkeyfunc_type delkeyfunc,
lruhash_deldatafunc_type deldatafunc, void* arg);
/**
* Delete hash table. Entries are all deleted.
@ -109,7 +109,7 @@ void slabhash_clear(struct slabhash* table);
* @param data: the data.
* @param cb_override: if not NULL overrides the cb_arg for deletfunc.
*/
void slabhash_insert(struct slabhash* table, hashvalue_t hash,
void slabhash_insert(struct slabhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_override);
/**
@ -126,7 +126,7 @@ void slabhash_insert(struct slabhash* table, hashvalue_t hash,
* The user must unlock the entry when done.
*/
struct lruhash_entry* slabhash_lookup(struct slabhash* table,
hashvalue_t hash, void* key, int wr);
hashvalue_type hash, void* key, int wr);
/**
* Remove entry from hashtable. Does nothing if not found in hashtable.
@ -135,7 +135,7 @@ struct lruhash_entry* slabhash_lookup(struct slabhash* table,
* @param hash: hash of key.
* @param key: what to look for.
*/
void slabhash_remove(struct slabhash* table, hashvalue_t hash, void* key);
void slabhash_remove(struct slabhash* table, hashvalue_type hash, void* key);
/**
* Output debug info to the log as to state of the hash table.
@ -165,14 +165,14 @@ size_t slabhash_get_mem(struct slabhash* table);
* @param hash: hash value.
* @return the lru hash table.
*/
struct lruhash* slabhash_gettable(struct slabhash* table, hashvalue_t hash);
struct lruhash* slabhash_gettable(struct slabhash* table, hashvalue_type hash);
/**
* Set markdel function
* @param table: slabbed hash table.
* @param md: markdel function ptr.
*/
void slabhash_setmarkdel(struct slabhash* table, lruhash_markdelfunc_t md);
void slabhash_setmarkdel(struct slabhash* table, lruhash_markdelfunc_type md);
/**
* Traverse a slabhash.

View file

@ -44,6 +44,7 @@
#include "util/net_help.h"
#include "util/netevent.h"
#include "util/fptr_wlist.h"
#include "util/ub_event.h"
#ifndef USE_WINSOCK
/* on unix */
@ -303,6 +304,8 @@ int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len,
d = r;
while(d != (ssize_t)sizeof(len)) {
if((r=write(fd, ((char*)&len)+d, sizeof(len)-d)) == -1) {
if(errno == EAGAIN)
continue; /* temporarily unavail: try again*/
log_err("tube msg write failed: %s", strerror(errno));
(void)fd_set_nonblock(fd);
return 0;
@ -312,6 +315,8 @@ int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len,
d = 0;
while(d != (ssize_t)len) {
if((r=write(fd, buf+d, len-d)) == -1) {
if(errno == EAGAIN)
continue; /* temporarily unavail: try again*/
log_err("tube msg write failed: %s", strerror(errno));
(void)fd_set_nonblock(fd);
return 0;
@ -421,7 +426,7 @@ int tube_read_fd(struct tube* tube)
}
int tube_setup_bg_listen(struct tube* tube, struct comm_base* base,
tube_callback_t* cb, void* arg)
tube_callback_type* cb, void* arg)
{
tube->listen_cb = cb;
tube->listen_arg = arg;
@ -537,7 +542,7 @@ void tube_close_write(struct tube* ATTR_UNUSED(tube))
void tube_remove_bg_listen(struct tube* tube)
{
verbose(VERB_ALGO, "tube remove_bg_listen");
winsock_unregister_wsaevent(&tube->ev_listen);
ub_winsock_unregister_wsaevent(tube->ev_listen);
}
void tube_remove_bg_write(struct tube* tube)
@ -662,14 +667,15 @@ tube_handle_write(struct comm_point* ATTR_UNUSED(c), void* ATTR_UNUSED(arg),
}
int tube_setup_bg_listen(struct tube* tube, struct comm_base* base,
tube_callback_t* cb, void* arg)
tube_callback_type* cb, void* arg)
{
tube->listen_cb = cb;
tube->listen_arg = arg;
if(!comm_base_internal(base))
return 1; /* ignore when no comm base - testing */
return winsock_register_wsaevent(comm_base_internal(base),
&tube->ev_listen, tube->event, &tube_handle_signal, tube);
tube->ev_listen = ub_winsock_register_wsaevent(
comm_base_internal(base), tube->event, &tube_handle_signal, tube);
return tube->ev_listen ? 1 : 0;
}
int tube_setup_bg_write(struct tube* ATTR_UNUSED(tube),

View file

@ -48,7 +48,6 @@ struct tube;
struct tube_res_list;
#ifdef USE_WINSOCK
#include "util/locks.h"
#include "util/winsock_event.h"
#endif
/**
@ -56,7 +55,7 @@ struct tube_res_list;
* void mycallback(tube, msg, len, error, user_argument);
* if error is true (NETEVENT_*), msg is probably NULL.
*/
typedef void tube_callback_t(struct tube*, uint8_t*, size_t, int, void*);
typedef void tube_callback_type(struct tube*, uint8_t*, size_t, int, void*);
/**
* A pipe
@ -71,7 +70,7 @@ struct tube {
/** listen commpoint */
struct comm_point* listen_com;
/** listen callback */
tube_callback_t* listen_cb;
tube_callback_type* listen_cb;
/** listen callback user arg */
void* listen_arg;
/** are we currently reading a command, 0 if not, else bytecount */
@ -93,16 +92,16 @@ struct tube {
#else /* USE_WINSOCK */
/** listen callback */
tube_callback_t* listen_cb;
tube_callback_type* listen_cb;
/** listen callback user arg */
void* listen_arg;
/** the windows sockets event (signaled if items in pipe) */
WSAEVENT event;
/** winsock event storage when registered with event base */
struct event ev_listen;
struct ub_event* ev_listen;
/** lock on the list of outstanding items */
lock_basic_t res_lock;
lock_basic_type res_lock;
/** list of outstanding results on pipe */
struct tube_res_list* res_list;
/** last in list */
@ -223,7 +222,7 @@ int tube_read_fd(struct tube* tube);
* @return true if successful, false on error.
*/
int tube_setup_bg_listen(struct tube* tube, struct comm_base* base,
tube_callback_t* cb, void* arg);
tube_callback_type* cb, void* arg);
/**
* Remove bg listen setup from event base.

444
external/unbound/util/ub_event.c vendored Normal file
View file

@ -0,0 +1,444 @@
/*
* util/ub_event.c - directly call libevent (compatability) functions
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains and implementation for the indirection layer for pluggable
* events that transparently passes it either directly to libevent, or calls
* the libevent compatibility layer functions.
*/
#include "config.h"
#include <sys/time.h>
#include "util/ub_event.h"
#include "util/log.h"
#include "util/netevent.h"
#include "util/tube.h"
/* We define libevent structures here to hide the libevent stuff. */
#ifdef USE_MINI_EVENT
# ifdef USE_WINSOCK
# include "util/winsock_event.h"
# else
# include "util/mini_event.h"
# endif /* USE_WINSOCK */
#else /* USE_MINI_EVENT */
/* we use libevent */
# ifdef HAVE_EVENT_H
# include <event.h>
# else
# include "event2/event.h"
# include "event2/event_struct.h"
# include "event2/event_compat.h"
# endif
#endif /* USE_MINI_EVENT */
#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
UB_EV_PERSIST != EV_PERSIST
/* Only necessary for libev */
# define NATIVE_BITS(b) ( \
(((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
| (((b) & UB_EV_READ ) ? EV_READ : 0) \
| (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \
| (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \
| (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
# define UB_EV_BITS(b) ( \
(((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
| (((b) & EV_READ ) ? UB_EV_READ : 0) \
| (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \
| (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \
| (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
# define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
{ (C)(fd, UB_EV_BITS(bits), arg); }
UB_EV_BITS_CB(comm_point_udp_callback);
UB_EV_BITS_CB(comm_point_udp_ancil_callback)
UB_EV_BITS_CB(comm_point_tcp_accept_callback)
UB_EV_BITS_CB(comm_point_tcp_handle_callback)
UB_EV_BITS_CB(comm_timer_callback)
UB_EV_BITS_CB(comm_signal_callback)
UB_EV_BITS_CB(comm_point_local_handle_callback)
UB_EV_BITS_CB(comm_point_raw_handle_callback)
UB_EV_BITS_CB(tube_handle_signal)
UB_EV_BITS_CB(comm_base_handle_slow_accept)
static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
{
if(cb == comm_point_udp_callback)
return my_comm_point_udp_callback;
else if(cb == comm_point_udp_ancil_callback)
return my_comm_point_udp_ancil_callback;
else if(cb == comm_point_tcp_accept_callback)
return my_comm_point_tcp_accept_callback;
else if(cb == comm_point_tcp_handle_callback)
return my_comm_point_tcp_handle_callback;
else if(cb == comm_timer_callback)
return my_comm_timer_callback;
else if(cb == comm_signal_callback)
return my_comm_signal_callback;
else if(cb == comm_point_local_handle_callback)
return my_comm_point_local_handle_callback;
else if(cb == comm_point_raw_handle_callback)
return my_comm_point_raw_handle_callback;
else if(cb == tube_handle_signal)
return my_tube_handle_signal;
else if(cb == comm_base_handle_slow_accept)
return my_comm_base_handle_slow_accept;
else
return NULL;
}
#else
# define NATIVE_BITS(b) (b)
# define NATIVE_BITS_CB(c) (c)
#endif
#ifndef EVFLAG_AUTO
#define EVFLAG_AUTO 0
#endif
#define AS_EVENT_BASE(x) ((struct event_base*)x)
#define AS_UB_EVENT_BASE(x) ((struct ub_event_base*)x)
#define AS_EVENT(x) ((struct event*)x)
#define AS_UB_EVENT(x) ((struct ub_event*)x)
const char* ub_event_get_version(void)
{
return event_get_version();
}
#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
static const char* ub_ev_backend2str(int b)
{
switch(b) {
case EVBACKEND_SELECT: return "select";
case EVBACKEND_POLL: return "poll";
case EVBACKEND_EPOLL: return "epoll";
case EVBACKEND_KQUEUE: return "kqueue";
case EVBACKEND_DEVPOLL: return "devpoll";
case EVBACKEND_PORT: return "evport";
}
return "unknown";
}
#endif
void
ub_get_event_sys(struct ub_event_base* base, const char** n, const char** s,
const char** m)
{
#ifdef USE_WINSOCK
(void)base;
*n = "event";
*s = "winsock";
*m = "WSAWaitForMultipleEvents";
#elif defined(USE_MINI_EVENT)
(void)base;
*n = "mini-event";
*s = "internal";
*m = "select";
#else
struct event_base* b = AS_EVENT_BASE(base);
*s = event_get_version();
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
*n = "libev";
if (!b)
b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
# ifdef EVBACKEND_SELECT
*m = ub_ev_backend2str(ev_backend((struct ev_loop*)b));
# else
*m = "not obtainable";
# endif
# elif defined(HAVE_EVENT_BASE_GET_METHOD)
*n = "libevent";
if (!b)
b = event_base_new();
*m = event_base_get_method(b);
# else
*n = "unknown";
*m = "not obtainable";
(void)b;
# endif
# ifdef HAVE_EVENT_BASE_FREE
if (b && b != AS_EVENT_BASE(base))
event_base_free(b);
# endif
#endif
}
struct ub_event_base*
ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
{
void* base;
(void)base;
#ifdef USE_MINI_EVENT
(void)sigs;
/* use mini event time-sharing feature */
base = event_init(time_secs, time_tv);
#else
(void)time_secs;
(void)time_tv;
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
/* libev */
if(sigs)
base = ev_default_loop(EVFLAG_AUTO);
else
base = ev_loop_new(EVFLAG_AUTO);
# else
(void)sigs;
# ifdef HAVE_EVENT_BASE_NEW
base = event_base_new();
# else
base = event_init();
# endif
# endif
#endif
return (struct ub_event_base*)base;
}
struct ub_event_base *
ub_libevent_event_base(struct event_base* libevent_base)
{
#ifdef USE_MINI_EVENT
(void)libevent_base;
return NULL;
#else
return AS_UB_EVENT_BASE(libevent_base);
#endif
}
struct event_base *
ub_libevent_get_event_base(struct ub_event_base* base)
{
#ifdef USE_MINI_EVENT
(void)base;
return NULL;
#else
return AS_EVENT_BASE(base);
#endif
}
void
ub_event_base_free(struct ub_event_base* base)
{
#ifdef USE_MINI_EVENT
event_base_free(AS_EVENT_BASE(base));
#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
/* only libevent 1.2+ has it, but in 1.2 it is broken -
assertion fails on signal handling ev that is not deleted
in libevent 1.3c (event_base_once appears) this is fixed. */
event_base_free(AS_EVENT_BASE(base));
#else
(void)base;
#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
}
int
ub_event_base_dispatch(struct ub_event_base* base)
{
return event_base_dispatch(AS_EVENT_BASE(base));
}
int
ub_event_base_loopexit(struct ub_event_base* base)
{
return event_base_loopexit(AS_EVENT_BASE(base), NULL);
}
struct ub_event*
ub_event_new(struct ub_event_base* base, int fd, short bits,
void (*cb)(int, short, void*), void* arg)
{
struct event *ev = (struct event*)calloc(1, sizeof(struct event));
if (!ev)
return NULL;
event_set(ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
free(ev);
return NULL;
}
return AS_UB_EVENT(ev);
}
struct ub_event*
ub_signal_new(struct ub_event_base* base, int fd,
void (*cb)(int, short, void*), void* arg)
{
struct event *ev = (struct event*)calloc(1, sizeof(struct event));
if (!ev)
return NULL;
signal_set(ev, fd, NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
free(ev);
return NULL;
}
return AS_UB_EVENT(ev);
}
struct ub_event*
ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
void (*cb)(int, short, void*), void* arg)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
struct event *ev = (struct event*)calloc(1, sizeof(struct event));
if (!ev)
return NULL;
if (winsock_register_wsaevent(AS_EVENT_BASE(base), ev, wsaevent, cb,
arg))
return AS_UB_EVENT(ev);
free(ev);
return NULL;
#else
(void)base;
(void)wsaevent;
(void)cb;
(void)arg;
return NULL;
#endif
}
void
ub_event_add_bits(struct ub_event* ev, short bits)
{
AS_EVENT(ev)->ev_events |= NATIVE_BITS(bits);
}
void
ub_event_del_bits(struct ub_event* ev, short bits)
{
AS_EVENT(ev)->ev_events &= ~NATIVE_BITS(bits);
}
void
ub_event_set_fd(struct ub_event* ev, int fd)
{
AS_EVENT(ev)->ev_fd = fd;
}
void
ub_event_free(struct ub_event* ev)
{
if (ev)
free(AS_EVENT(ev));
}
int
ub_event_add(struct ub_event* ev, struct timeval* tv)
{
return event_add(AS_EVENT(ev), tv);
}
int
ub_event_del(struct ub_event* ev)
{
return event_del(AS_EVENT(ev));
}
int
ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
void (*cb)(int, short, void*), void* arg, struct timeval* tv)
{
event_set(AS_EVENT(ev), -1, EV_TIMEOUT, NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), AS_EVENT(ev)) != 0)
return -1;
return evtimer_add(AS_EVENT(ev), tv);
}
int
ub_timer_del(struct ub_event* ev)
{
return evtimer_del(AS_EVENT(ev));
}
int
ub_signal_add(struct ub_event* ev, struct timeval* tv)
{
return signal_add(AS_EVENT(ev), tv);
}
int
ub_signal_del(struct ub_event* ev)
{
return signal_del(AS_EVENT(ev));
}
void
ub_winsock_unregister_wsaevent(struct ub_event* ev)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
winsock_unregister_wsaevent(AS_EVENT(ev));
free(AS_EVENT(ev));
#else
(void)ev;
#endif
}
void
ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
winsock_tcp_wouldblock(AS_EVENT(ev), NATIVE_BITS(eventbits));
#else
(void)ev;
(void)eventbits;
#endif
}
void ub_comm_base_now(struct comm_base* cb)
{
#ifdef USE_MINI_EVENT
/** minievent updates the time when it blocks. */
(void)cb; /* nothing to do */
#else /* !USE_MINI_EVENT */
/** fillup the time values in the event base */
time_t *tt;
struct timeval *tv;
comm_base_timept(cb, &tt, &tv);
if(gettimeofday(tv, NULL) < 0) {
log_err("gettimeofday: %s", strerror(errno));
}
*tt = tv->tv_sec;
#endif /* USE_MINI_EVENT */
}

127
external/unbound/util/ub_event.h vendored Normal file
View file

@ -0,0 +1,127 @@
/*
* util/ub_event.h - indirection layer for pluggable events
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains prototypes for event loop functions.
*
*/
#ifndef UB_EVENT_H
#define UB_EVENT_H
struct ub_event_base;
struct ub_event;
struct comm_base;
struct event_base;
/** event timeout */
#define UB_EV_TIMEOUT 0x01
/** event fd readable */
#define UB_EV_READ 0x02
/** event fd writable */
#define UB_EV_WRITE 0x04
/** event signal */
#define UB_EV_SIGNAL 0x08
/** event must persist */
#define UB_EV_PERSIST 0x10
/** Returns event-base type. Could be "mini-event", "winsock-event" for the
* daemon compile, and will be "pluggable-event<PACKAGE_VERSION>" for
* libunbound.
*/
const char* ub_event_get_version(void);
/** Return the name, system and method for the pluggable event base */
void ub_get_event_sys(struct ub_event_base*, const char** n, const char** s,
const char** m);
/** Return a default event base. In the deamon thess will be the only event
* bases used.
*/
struct ub_event_base* ub_default_event_base(int, time_t*, struct timeval*);
/** Return an ub_event_base constructed for the given libevent event base */
struct ub_event_base* ub_libevent_event_base(struct event_base*);
/** Return the libevent base underlying the given ub_event_base. Will return
* NULL when the ub_event_base does not have an underlying libevent event base
*/
struct event_base* ub_libevent_get_event_base(struct ub_event_base*);
/** Free event base. Free events yourself */
void ub_event_base_free(struct ub_event_base*);
/** Run the event base */
int ub_event_base_dispatch(struct ub_event_base*);
/** exit that loop */
int ub_event_base_loopexit(struct ub_event_base*);
/** Create a new ub_event for the event base */
struct ub_event* ub_event_new(struct ub_event_base*,
int fd, short bits, void (*cb)(int, short, void*), void* arg);
/** Create a new ub_event signal for the event base */
struct ub_event* ub_signal_new(struct ub_event_base*, int fd,
void (*cb)(int, short, void*), void* arg);
/** Create a new ub_event associated with the wsaevent for the event base */
struct ub_event* ub_winsock_register_wsaevent(struct ub_event_base*,
void* wsaevent, void (*cb)(int, short, void*), void* arg);
/** Add event bits for this event to fire on */
void ub_event_add_bits(struct ub_event*, short bits);
/** Configure the event so it will not longer fire on given bits */
void ub_event_del_bits(struct ub_event*, short bits);
/** Change or set the file descriptor on the event */
void ub_event_set_fd(struct ub_event*, int fd);
/** free the event */
void ub_event_free(struct ub_event*);
/** Activate the event. The given timeval is an timeout value. */
int ub_event_add(struct ub_event*, struct timeval*);
/** Deactivate the event */
int ub_event_del(struct ub_event*);
/** Reconfigure and activate a timeout event */
int ub_timer_add(struct ub_event*, struct ub_event_base*,
void (*cb)(int, short, void*), void* arg, struct timeval*);
/** Deactivate the timeout event */
int ub_timer_del(struct ub_event*);
/** Activate a signal event */
int ub_signal_add(struct ub_event*, struct timeval*);
/** Deactivate a signal event */
int ub_signal_del(struct ub_event*);
/** Free a with a wsaevent associated event */
void ub_winsock_unregister_wsaevent(struct ub_event* ev);
/** Signal the eventloop when a TCP windows socket will block on next read
* or write (given by the eventbits)
*/
void ub_winsock_tcp_wouldblock(struct ub_event*, int bits);
/** Equip the comm_base with the current time */
void ub_comm_base_now(struct comm_base* cb);
#endif /* UB_EVENT_H */

View file

@ -0,0 +1,692 @@
/*
* util/ub_event_pluggable.c - call registered pluggable event functions
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains an implementation for the indirection layer for pluggable
* events that calls the registered pluggable event loop. It also defines a
* default pluggable event loop based on the default libevent (compatibility)
* functions.
*/
#include "config.h"
#include <sys/time.h>
#include "util/ub_event.h"
#include "libunbound/unbound-event.h"
#include "util/netevent.h"
#include "util/log.h"
#include "util/fptr_wlist.h"
/* We define libevent structures here to hide the libevent stuff. */
#ifdef USE_MINI_EVENT
# ifdef USE_WINSOCK
# include "util/winsock_event.h"
# else
# include "util/mini_event.h"
# endif /* USE_WINSOCK */
#else /* USE_MINI_EVENT */
/* we use libevent */
# ifdef HAVE_EVENT_H
# include <event.h>
# else
# include "event2/event.h"
# include "event2/event_struct.h"
# include "event2/event_compat.h"
# endif
#endif /* USE_MINI_EVENT */
#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
UB_EV_PERSIST != EV_PERSIST
/* Only necessary for libev */
# define NATIVE_BITS(b) ( \
(((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
| (((b) & UB_EV_READ ) ? EV_READ : 0) \
| (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \
| (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \
| (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
# define UB_EV_BITS(b) ( \
(((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
| (((b) & EV_READ ) ? UB_EV_READ : 0) \
| (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \
| (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \
| (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
# define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
{ (C)(fd, UB_EV_BITS(bits), arg); }
UB_EV_BITS_CB(comm_point_udp_callback);
UB_EV_BITS_CB(comm_point_udp_ancil_callback)
UB_EV_BITS_CB(comm_point_tcp_accept_callback)
UB_EV_BITS_CB(comm_point_tcp_handle_callback)
UB_EV_BITS_CB(comm_timer_callback)
UB_EV_BITS_CB(comm_signal_callback)
UB_EV_BITS_CB(comm_point_local_handle_callback)
UB_EV_BITS_CB(comm_point_raw_handle_callback)
UB_EV_BITS_CB(tube_handle_signal)
UB_EV_BITS_CB(comm_base_handle_slow_accept)
static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
{
if(cb == comm_point_udp_callback)
return my_comm_point_udp_callback;
else if(cb == comm_point_udp_ancil_callback)
return my_comm_point_udp_ancil_callback;
else if(cb == comm_point_tcp_accept_callback)
return my_comm_point_tcp_accept_callback;
else if(cb == comm_point_tcp_handle_callback)
return my_comm_point_tcp_handle_callback;
else if(cb == comm_timer_callback)
return my_comm_timer_callback;
else if(cb == comm_signal_callback)
return my_comm_signal_callback;
else if(cb == comm_point_local_handle_callback)
return my_comm_point_local_handle_callback;
else if(cb == comm_point_raw_handle_callback)
return my_comm_point_raw_handle_callback;
else if(cb == tube_handle_signal)
return my_tube_handle_signal;
else if(cb == comm_base_handle_slow_accept)
return my_comm_base_handle_slow_accept;
else
return NULL;
}
#else
# define NATIVE_BITS(b) (b)
# define NATIVE_BITS_CB(c) (c)
#endif
#ifndef EVFLAG_AUTO
#define EVFLAG_AUTO 0
#endif
struct my_event_base {
struct ub_event_base super;
struct event_base* base;
};
struct my_event {
struct ub_event super;
struct event ev;
};
#define AS_MY_EVENT_BASE(x) ((struct my_event_base*)x)
#define AS_MY_EVENT(x) ((struct my_event*)x)
const char* ub_event_get_version(void)
{
return "pluggable-event"PACKAGE_VERSION;
}
static void
my_event_add_bits(struct ub_event* ev, short bits)
{
AS_MY_EVENT(ev)->ev.ev_events |= NATIVE_BITS(bits);
}
static void
my_event_del_bits(struct ub_event* ev, short bits)
{
AS_MY_EVENT(ev)->ev.ev_events &= ~NATIVE_BITS(bits);
}
static void
my_event_set_fd(struct ub_event* ev, int fd)
{
AS_MY_EVENT(ev)->ev.ev_fd = fd;
}
static void
my_event_free(struct ub_event* ev)
{
free(AS_MY_EVENT(ev));
}
static int
my_event_add(struct ub_event* ev, struct timeval* tv)
{
return event_add(&AS_MY_EVENT(ev)->ev, tv);
}
static int
my_event_del(struct ub_event* ev)
{
return event_del(&AS_MY_EVENT(ev)->ev);
}
static int
my_timer_add(struct ub_event* ev, struct ub_event_base* base,
void (*cb)(int, short, void*), void* arg, struct timeval* tv)
{
event_set(&AS_MY_EVENT(ev)->ev, -1, EV_TIMEOUT,NATIVE_BITS_CB(cb),arg);
if (event_base_set(AS_MY_EVENT_BASE(base)->base, &AS_MY_EVENT(ev)->ev)
!= 0)
return -1;
return evtimer_add(&AS_MY_EVENT(ev)->ev, tv);
}
static int
my_timer_del(struct ub_event* ev)
{
return evtimer_del(&AS_MY_EVENT(ev)->ev);
}
static int
my_signal_add(struct ub_event* ev, struct timeval* tv)
{
return signal_add(&AS_MY_EVENT(ev)->ev, tv);
}
static int
my_signal_del(struct ub_event* ev)
{
return signal_del(&AS_MY_EVENT(ev)->ev);
}
static void
my_winsock_unregister_wsaevent(struct ub_event* ev)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
winsock_unregister_wsaevent(&AS_MY_EVENT(ev)->ev);
free(AS_MY_EVENT(ev));
#else
(void)ev;
#endif
}
static void
my_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
winsock_tcp_wouldblock(&AS_MY_EVENT(ev)->ev, NATIVE_BITS(eventbits));
#else
(void)ev;
(void)eventbits;
#endif
}
static struct ub_event_vmt default_event_vmt = {
my_event_add_bits, my_event_del_bits, my_event_set_fd,
my_event_free, my_event_add, my_event_del,
my_timer_add, my_timer_del, my_signal_add, my_signal_del,
my_winsock_unregister_wsaevent, my_winsock_tcp_wouldblock
};
static void
my_event_base_free(struct ub_event_base* base)
{
#ifdef USE_MINI_EVENT
event_base_free(AS_MY_EVENT_BASE(base)->base);
#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
/* only libevent 1.2+ has it, but in 1.2 it is broken -
assertion fails on signal handling ev that is not deleted
in libevent 1.3c (event_base_once appears) this is fixed. */
event_base_free(AS_MY_EVENT_BASE(base)->base);
#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
free(AS_MY_EVENT_BASE(base));
}
static int
my_event_base_dispatch(struct ub_event_base* base)
{
return event_base_dispatch(AS_MY_EVENT_BASE(base)->base);
}
static int
my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv)
{
return event_base_loopexit(AS_MY_EVENT_BASE(base)->base, tv);
}
static struct ub_event*
my_event_new(struct ub_event_base* base, int fd, short bits,
void (*cb)(int, short, void*), void* arg)
{
struct my_event *my_ev = (struct my_event*)calloc(1,
sizeof(struct my_event));
if (!my_ev)
return NULL;
event_set(&my_ev->ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
free(my_ev);
return NULL;
}
my_ev->super.magic = UB_EVENT_MAGIC;
my_ev->super.vmt = &default_event_vmt;
return &my_ev->super;
}
static struct ub_event*
my_signal_new(struct ub_event_base* base, int fd,
void (*cb)(int, short, void*), void* arg)
{
struct my_event *my_ev = (struct my_event*)calloc(1,
sizeof(struct my_event));
if (!my_ev)
return NULL;
signal_set(&my_ev->ev, fd, NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
free(my_ev);
return NULL;
}
my_ev->super.magic = UB_EVENT_MAGIC;
my_ev->super.vmt = &default_event_vmt;
return &my_ev->super;
}
static struct ub_event*
my_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
void (*cb)(int, short, void*), void* arg)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
struct my_event *my_ev = (struct my_event*)calloc(1,
sizeof(struct my_event));
if (!my_ev)
return NULL;
if (!winsock_register_wsaevent(AS_MY_EVENT_BASE(base)->base,
&my_ev->ev, wsaevent, cb, arg)) {
free(my_ev);
return NULL;
}
my_ev->super.magic = UB_EVENT_MAGIC;
my_ev->super.vmt = &default_event_vmt;
return &my_ev->super;
#else
(void)base;
(void)wsaevent;
(void)cb;
(void)arg;
return NULL;
#endif
}
static struct ub_event_base_vmt default_event_base_vmt = {
my_event_base_free, my_event_base_dispatch,
my_event_base_loopexit, my_event_new, my_signal_new,
my_winsock_register_wsaevent
};
struct ub_event_base*
ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
{
struct my_event_base* my_base = (struct my_event_base*)calloc(1,
sizeof(struct my_event_base));
if (!my_base)
return NULL;
#ifdef USE_MINI_EVENT
(void)sigs;
/* use mini event time-sharing feature */
my_base->base = event_init(time_secs, time_tv);
#else
(void)time_secs;
(void)time_tv;
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
/* libev */
if(sigs)
my_base->base = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
else
my_base->base = (struct event_base*)ev_loop_new(EVFLAG_AUTO);
# else
(void)sigs;
# ifdef HAVE_EVENT_BASE_NEW
my_base->base = event_base_new();
# else
my_base->base = event_init();
# endif
# endif
#endif
if (!my_base->base) {
free(my_base);
return NULL;
}
my_base->super.magic = UB_EVENT_MAGIC;
my_base->super.vmt = &default_event_base_vmt;
return &my_base->super;
}
struct ub_event_base*
ub_libevent_event_base(struct event_base* base)
{
#ifdef USE_MINI_EVENT
(void)base;
return NULL;
#else
struct my_event_base* my_base = (struct my_event_base*)calloc(1,
sizeof(struct my_event_base));
if (!my_base)
return NULL;
my_base->super.magic = UB_EVENT_MAGIC;
my_base->super.vmt = &default_event_base_vmt;
my_base->base = base;
return &my_base->super;
#endif
}
struct event_base*
ub_libevent_get_event_base(struct ub_event_base* base)
{
#ifndef USE_MINI_EVENT
if (base->vmt == &default_event_base_vmt)
return AS_MY_EVENT_BASE(base)->base;
#else
(void)base;
#endif
return NULL;
}
#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
static const char* ub_ev_backend2str_pluggable(int b)
{
switch(b) {
case EVBACKEND_SELECT: return "select";
case EVBACKEND_POLL: return "poll";
case EVBACKEND_EPOLL: return "epoll";
case EVBACKEND_KQUEUE: return "kqueue";
case EVBACKEND_DEVPOLL: return "devpoll";
case EVBACKEND_PORT: return "evport";
}
return "unknown";
}
#endif
void
ub_get_event_sys(struct ub_event_base* ub_base, const char** n, const char** s,
const char** m)
{
#ifdef USE_WINSOCK
(void)ub_base;
*n = "pluggable-event";
*s = "winsock";
*m = "WSAWaitForMultipleEvents";
#elif defined(USE_MINI_EVENT)
(void)ub_base;
*n = "pluggable-event";
*s = "internal";
*m = "select";
#else
struct event_base* b = ub_libevent_get_event_base(ub_base);
/* This function is only called from comm_base_create, so
* ub_base is guaranteed to exist and to be the default
* event base.
*/
assert(b);
*n = "pluggable-event";
*s = event_get_version();
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
*n = "pluggable-libev";
# ifdef EVBACKEND_SELECT
*m = ub_ev_backend2str_pluggable(ev_backend((struct ev_loop*)b));
# else
*m = "not obtainable";
# endif
# elif defined(HAVE_EVENT_BASE_GET_METHOD)
*n = "pluggable-libevent";
*m = event_base_get_method(b);
# else
*m = "not obtainable";
# endif
#endif
}
void
ub_event_base_free(struct ub_event_base* base)
{
if (base && base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->free == my_event_base_free);
(*base->vmt->free)(base);
}
}
int
ub_event_base_dispatch(struct ub_event_base* base)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->dispatch == my_event_base_dispatch);
return (*base->vmt->dispatch)(base);
}
return -1;
}
int
ub_event_base_loopexit(struct ub_event_base* base)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->loopexit == my_event_base_loopexit);
return (*base->vmt->loopexit)(base, NULL);
}
return -1;
}
struct ub_event*
ub_event_new(struct ub_event_base* base, int fd, short bits,
void (*cb)(int, short, void*), void* arg)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->new_event == my_event_new);
return (*base->vmt->new_event)(base, fd, bits, cb, arg);
}
return NULL;
}
struct ub_event*
ub_signal_new(struct ub_event_base* base, int fd,
void (*cb)(int, short, void*), void* arg)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->new_signal == my_signal_new);
return (*base->vmt->new_signal)(base, fd, cb, arg);
}
return NULL;
}
struct ub_event*
ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
void (*cb)(int, short, void*), void* arg)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->winsock_register_wsaevent ==
my_winsock_register_wsaevent);
return (*base->vmt->winsock_register_wsaevent)(base, wsaevent, cb, arg);
}
return NULL;
}
void
ub_event_add_bits(struct ub_event* ev, short bits)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->add_bits == my_event_add_bits);
(*ev->vmt->add_bits)(ev, bits);
}
}
void
ub_event_del_bits(struct ub_event* ev, short bits)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->del_bits == my_event_del_bits);
(*ev->vmt->del_bits)(ev, bits);
}
}
void
ub_event_set_fd(struct ub_event* ev, int fd)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->set_fd == my_event_set_fd);
(*ev->vmt->set_fd)(ev, fd);
}
}
void
ub_event_free(struct ub_event* ev)
{
if (ev && ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->free == my_event_free);
(*ev->vmt->free)(ev);
}
}
int
ub_event_add(struct ub_event* ev, struct timeval* tv)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->add == my_event_add);
return (*ev->vmt->add)(ev, tv);
}
return -1;
}
int
ub_event_del(struct ub_event* ev)
{
if (ev && ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->del == my_event_del);
return (*ev->vmt->del)(ev);
}
return -1;
}
int
ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
void (*cb)(int, short, void*), void* arg, struct timeval* tv)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->add_timer == my_timer_add);
return (*ev->vmt->add_timer)(ev, base, cb, arg, tv);
}
return -1;
}
int
ub_timer_del(struct ub_event* ev)
{
if (ev && ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->del_timer == my_timer_del);
return (*ev->vmt->del_timer)(ev);
}
return -1;
}
int
ub_signal_add(struct ub_event* ev, struct timeval* tv)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->add_signal == my_signal_add);
return (*ev->vmt->add_signal)(ev, tv);
}
return -1;
}
int
ub_signal_del(struct ub_event* ev)
{
if (ev && ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->del_signal == my_signal_del);
return (*ev->vmt->del_signal)(ev);
}
return -1;
}
void
ub_winsock_unregister_wsaevent(struct ub_event* ev)
{
if (ev && ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->winsock_unregister_wsaevent ==
my_winsock_unregister_wsaevent);
(*ev->vmt->winsock_unregister_wsaevent)(ev);
}
}
void
ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->winsock_tcp_wouldblock ==
my_winsock_tcp_wouldblock);
(*ev->vmt->winsock_tcp_wouldblock)(ev, eventbits);
}
}
void ub_comm_base_now(struct comm_base* cb)
{
time_t *tt;
struct timeval *tv;
#ifdef USE_MINI_EVENT
/** minievent updates the time when it blocks. */
if (comm_base_internal(cb)->magic == UB_EVENT_MAGIC &&
comm_base_internal(cb)->vmt == &default_event_base_vmt)
return; /* Actually using mini event, so do not set time */
#endif /* USE_MINI_EVENT */
/** fillup the time values in the event base */
comm_base_timept(cb, &tt, &tv);
if(gettimeofday(tv, NULL) < 0) {
log_err("gettimeofday: %s", strerror(errno));
}
*tt = tv->tv_sec;
}

View file

@ -169,7 +169,7 @@ static void handle_timeouts(struct event_base* base, struct timeval* now,
#endif
verbose(VERB_CLIENT, "winsock_event handle_timeouts");
while((rbnode_t*)(p = (struct event*)rbtree_first(base->times))
while((rbnode_type*)(p = (struct event*)rbtree_first(base->times))
!=RBTREE_NULL) {
#ifndef S_SPLINT_S
if(p->ev_timeout.tv_sec > now->tv_sec ||
@ -262,8 +262,9 @@ static int handle_select(struct event_base* base, struct timeval* wait)
break; /* sanity check */
}
log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);
verbose(VERB_CLIENT, "winsock_event bmax=%d numwait=%d wait=%x "
"timeout=%d", base->max, numwait, (int)wait, (int)timeout);
verbose(VERB_CLIENT, "winsock_event bmax=%d numwait=%d wait=%s "
"timeout=%d", base->max, numwait, (wait?"<wait>":"<null>"),
(int)timeout);
/* do the wait */
if(numwait == 0) {

View file

@ -132,7 +132,7 @@
struct event_base
{
/** sorted by timeout (absolute), ptr */
rbtree_t* times;
rbtree_type* times;
/** array (first part in use) of handles to work on */
struct event** items;
/** number of items in use in array */
@ -169,7 +169,7 @@ struct event_base
*/
struct event {
/** node in timeout rbtree */
rbnode_t node;
rbnode_type node;
/** is event already added */
int added;