- Generalise inplace callback (de)registration

- (de)register inplace callbacks for module id
- No unbound-control set_option for ECS options
- Deprecated client-subnet-opcode config option
- Introduced client-subnet-always-forward config option
- Changed max-client-subnet-ipv6 default to 56 (as in RFC)
- Removed extern ECS config options
- module_restart_next now calls clear on all following modules
- Also create ECS module qstate on module_event_pass event


git-svn-id: file:///svn/unbound/trunk@4092 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Ralph Dolmans 2017-04-06 13:13:06 +00:00
parent bdac428d79
commit a2bc93547f
27 changed files with 2479 additions and 2836 deletions

View File

@ -711,7 +711,6 @@ daemon_delete(struct daemon* daemon)
rrset_cache_delete(daemon->env->rrset_cache);
infra_delete(daemon->env->infra_cache);
edns_known_options_delete(daemon->env);
inplace_cb_lists_delete(daemon->env);
}
ub_randfree(daemon->rand);
alloc_clear(&daemon->superalloc);

View File

@ -1,3 +1,14 @@
6 April 2017: Ralph
- Generalise inplace callback (de)registration
- (de)register inplace callbacks for module id
- No unbound-control set_option for ECS options
- Deprecated client-subnet-opcode config option
- Introduced client-subnet-always-forward config option
- Changed max-client-subnet-ipv6 default to 56 (as in RFC)
- Removed extern ECS config options
- module_restart_next now calls clear on all following modules
- Also create ECS module qstate on module_event_pass event
6 April 2017: Wouter
- Small fixup for documentation.
- iana portlist update

View File

@ -1504,12 +1504,17 @@ classless delegation netblock, for example like 10.2.3.4/24 or 2001::11/64. Can
be given multiple times. Authorities not listed will not receive edns-subnet
information.
.TP
.B client\-subnet\-opcode: \fI<number>\fR
Specify positive integer smaller than 65536. Defaults to 8.
.B client\-subnet\-always\-forward: \fI<yes or no>\fR
Specify whether the ECS whitelist check (configured using
\fBsend\-client\-subnet\fR) is applied for all queries, even if the triggering
query contains an ECS record, or only for queries for which the ECS record is
generated using the querier address (and therefore did not contain ECS data in
the client query). If enabled, the whitelist check is skipped when the client
query contains an ECS record. Default is no.
.TP
.B max\-client\-subnet\-ipv6: \fI<number>\fR
Specifies the maximum prefix length of the client source address we are willing
to expose to third parties for IPv6. Defaults to 64.
to expose to third parties for IPv6. Defaults to 56.
.TP
.B max\-client\-subnet\-ipv4: \fI<number>\fR
Specifies the maximum prefix length of the client source address we are willing

View File

@ -43,11 +43,6 @@
#include "edns-subnet/edns-subnet.h"
#include <string.h>
/** Opcode for edns subnet option, as assigned by IANA. */
uint16_t EDNSSUBNET_OPCODE = 8;
uint8_t EDNSSUBNET_MAX_SUBNET_IP4 = 24;
uint8_t EDNSSUBNET_MAX_SUBNET_IP6 = 64;
int
copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n)
{

View File

@ -46,12 +46,6 @@
#define EDNSSUBNET_ADDRFAM_IP4 1
#define EDNSSUBNET_ADDRFAM_IP6 2
/** Opcode for edns subnet option */
extern uint16_t EDNSSUBNET_OPCODE;
/** Maximum number of bits we are willing to expose */
extern uint8_t EDNSSUBNET_MAX_SUBNET_IP4;
extern uint8_t EDNSSUBNET_MAX_SUBNET_IP6;
/**
* ECS option
*/

View File

@ -128,7 +128,8 @@ ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
~(0xFF >> (ecs->subnet_source_mask % 8)));
sldns_buffer_flip(buf);
edns_opt_list_append(list, EDNSSUBNET_OPCODE,
edns_opt_list_append(list,
qstate->env->cfg->client_subnet_opcode,
sn_octs + sn_octs_remainder + 4,
sldns_buffer_begin(buf), qstate->region);
}
@ -138,9 +139,8 @@ int ecs_whitelist_check(struct query_info* ATTR_UNUSED(qinfo),
uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
struct regional* ATTR_UNUSED(region), void* cbargs)
struct regional* ATTR_UNUSED(region), int id, void* cbargs)
{
int id = *((int*)cbargs);
struct subnet_qstate *sq;
struct subnet_env *sn_env;
@ -152,7 +152,8 @@ int ecs_whitelist_check(struct query_info* ATTR_UNUSED(qinfo),
* received from nameserver. */
qstate->no_cache_store = 0;
if(sq->ecs_server_out.subnet_validdata && (sq->subnet_downstream ||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
qstate->env->cfg->client_subnet_always_forward) ||
upstream_is_whitelisted(sn_env->edns_subnet_upstreams,
addr, addrlen))) {
/* Address on whitelist or client query contains ECS option, we
@ -168,7 +169,7 @@ int ecs_whitelist_check(struct query_info* ATTR_UNUSED(qinfo),
/* Outgoing ECS option is set, but we don't want to sent it to
* this address, remove option. */
edns_opt_list_remove(&qstate->edns_opts_back_out,
EDNSSUBNET_OPCODE);
qstate->env->cfg->client_subnet_opcode);
sq->subnet_sent = 0;
}
return 1;
@ -208,11 +209,13 @@ subnetmod_init(struct module_env *env, int id)
return 0;
}
verbose(VERB_QUERY, "subnet: option registered (%d)", EDNSSUBNET_OPCODE);
verbose(VERB_QUERY, "subnet: option registered (%d)",
env->cfg->client_subnet_opcode);
/* Create new mesh state for all queries. */
env->unique_mesh = 1;
if(!edns_register_option(EDNSSUBNET_OPCODE,
1 /* bypass cache */, 0 /* no aggregation */, env)) {
if(!edns_register_option(env->cfg->client_subnet_opcode,
env->cfg->client_subnet_always_forward /* bypass cache */,
0 /* no aggregation */, env)) {
log_err("subnet: could not register opcode");
upstream_delete(sn_env->edns_subnet_upstreams);
slabhash_delete(sn_env->subnet_msg_cache);
@ -220,9 +223,10 @@ subnetmod_init(struct module_env *env, int id)
env->modinfo[id] = NULL;
return 0;
}
inplace_cb_query_register(ecs_whitelist_check, &id, sizeof(id), env);
inplace_cb_edns_back_parsed_register(ecs_edns_back_parsed, &id,
sizeof(id), env);
inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL,
0, env, id);
inplace_cb_register((void*)ecs_edns_back_parsed,
inplace_cb_edns_back_parsed, NULL, 0, env, id);
lock_rw_init(&sn_env->biglock);
return 1;
}
@ -235,8 +239,8 @@ subnetmod_deinit(struct module_env *env, int id)
return;
sn_env = (struct subnet_env*)env->modinfo[id];
lock_rw_destroy(&sn_env->biglock);
inplace_cb_edns_back_parsed_delete(env);
inplace_cb_query_delete(env);
inplace_cb_delete(env, inplace_cb_edns_back_parsed, id);
inplace_cb_delete(env, inplace_cb_query, id);
upstream_delete(sn_env->edns_subnet_upstreams);
slabhash_delete(sn_env->subnet_msg_cache);
alloc_clear(&sn_env->alloc);
@ -276,18 +280,20 @@ sizefunc(void *elemptr) {
* NULL on failure to create. */
static struct addrtree*
get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
struct subnet_env *env)
struct subnet_env *env, struct config_file* cfg)
{
struct addrtree *tree;
if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
if (!data->tree4)
data->tree4 = addrtree_create(EDNSSUBNET_MAX_SUBNET_IP4,
&delfunc, &sizefunc, env, ECS_MAX_TREESIZE);
data->tree4 = addrtree_create(
cfg->max_client_subnet_ipv4, &delfunc,
&sizefunc, env, ECS_MAX_TREESIZE);
tree = data->tree4;
} else {
if (!data->tree6)
data->tree6 = addrtree_create(EDNSSUBNET_MAX_SUBNET_IP6,
&delfunc, &sizefunc, env, ECS_MAX_TREESIZE);
data->tree6 = addrtree_create(
cfg->max_client_subnet_ipv6, &delfunc,
&sizefunc, env, ECS_MAX_TREESIZE);
tree = data->tree6;
}
return tree;
@ -337,7 +343,7 @@ update_cache(struct module_qstate *qstate, int id)
}
}
/* Step 2, find the correct tree */
if (!(tree = get_tree(lru_entry->data, edns, sne))) {
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
log_err("Subnet cache insertion failed");
return;
@ -490,9 +496,9 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
verbose(VERB_QUERY, "subnet: forged data");
s_out->subnet_validdata = 0;
(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
EDNSSUBNET_OPCODE);
qstate->env->cfg->client_subnet_opcode);
sq->subnet_sent = 0;
return module_wait_module;
return module_restart_next;
}
lock_rw_wrlock(&sne->biglock);
@ -550,28 +556,30 @@ parse_subnet_option(struct edns_option* ecs_option,
}
static void
subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs)
subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
struct config_file* cfg)
{
void* sinaddr;
/* Construct subnet option from original query */
if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
ecs->subnet_source_mask = EDNSSUBNET_MAX_SUBNET_IP4;
ecs->subnet_source_mask = cfg->max_client_subnet_ipv4;
ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4;
sinaddr = &((struct sockaddr_in*)ss)->sin_addr;
if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
(uint8_t *)sinaddr, INET_SIZE,
EDNSSUBNET_MAX_SUBNET_IP4)) {
ecs->subnet_source_mask)) {
ecs->subnet_validdata = 1;
}
}
#ifdef INET6
else {
ecs->subnet_source_mask = EDNSSUBNET_MAX_SUBNET_IP6;
ecs->subnet_source_mask = cfg->max_client_subnet_ipv6;
ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6;
sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr;
if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
(uint8_t *)sinaddr, INET6_SIZE,
EDNSSUBNET_MAX_SUBNET_IP6)) {
ecs->subnet_source_mask)) {
ecs->subnet_validdata = 1;
}
}
@ -581,16 +589,16 @@ subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs)
}
int
ecs_edns_back_parsed(struct module_qstate* qstate, void* cbargs)
ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs)
{
int id = *((int*)cbargs);
struct subnet_qstate *sq;
struct edns_option* ecs_opt;
if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
return 1;
if((ecs_opt = edns_opt_list_find(
qstate->edns_opts_back_in, EDNSSUBNET_OPCODE))) {
qstate->edns_opts_back_in,
qstate->env->cfg->client_subnet_opcode))) {
if(parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
sq->subnet_sent && sq->ecs_server_in.subnet_validdata)
/* Only skip global cache store if we sent an ECS option
@ -616,7 +624,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
strmodulevent(event));
log_query_info(VERB_QUERY, "subnet operate: query", &qstate->qinfo);
if(event == module_event_new && sq == NULL) {
if((event == module_event_new || event == module_event_pass) &&
sq == NULL) {
struct edns_option* ecs_opt;
if(!subnet_new_qstate(qstate, id)) {
qstate->return_msg = NULL;
@ -627,7 +636,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
sq = (struct subnet_qstate*)qstate->minfo[id];
if((ecs_opt = edns_opt_list_find(
qstate->edns_opts_front_in, EDNSSUBNET_OPCODE))) {
qstate->edns_opts_front_in,
qstate->env->cfg->client_subnet_opcode))) {
if(parse_subnet_option(ecs_opt, &sq->ecs_client_in)) {
sq->subnet_downstream = 1;
}
@ -635,7 +645,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
else if(qstate->mesh_info->reply_list) {
subnet_option_from_ss(
&qstate->mesh_info->reply_list->query_reply.addr,
&sq->ecs_client_in);
&sq->ecs_client_in, qstate->env->cfg);
}
if(sq->ecs_client_in.subnet_validdata == 0) {

View File

@ -117,10 +117,10 @@ size_t unittest_wrapper_subnetmod_sizefunc(void *elemptr);
int ecs_whitelist_check(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, void* cbargs);
struct regional* region, int id, void* cbargs);
/** Check whether reponse from server contains ECS record, if so, skip cache
* store. Called just after parsing EDNS data from server. */
int ecs_edns_back_parsed(struct module_qstate* qstate, void* cbargs);
int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs);
#endif /* SUBNETMOD_H */

View File

@ -310,7 +310,6 @@ ub_ctx_delete(struct ub_ctx* ctx)
infra_delete(ctx->env->infra_cache);
config_delete(ctx->env->cfg);
edns_known_options_delete(ctx->env);
inplace_cb_lists_delete(ctx->env);
free(ctx->env);
}
ub_randfree(ctx->seed_rnd);

View File

@ -1315,11 +1315,16 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
return mesh_continue(mesh, mstate, module_error, ev);
}
if(s == module_restart_next) {
fptr_ok(fptr_whitelist_mod_clear(
mesh->mods.mod[mstate->s.curmod]->clear));
(*mesh->mods.mod[mstate->s.curmod]->clear)
(&mstate->s, mstate->s.curmod);
mstate->s.minfo[mstate->s.curmod] = NULL;
int curmod = mstate->s.curmod;
for(; mstate->s.curmod < mesh->mods.num;
mstate->s.curmod++) {
fptr_ok(fptr_whitelist_mod_clear(
mesh->mods.mod[mstate->s.curmod]->clear));
(*mesh->mods.mod[mstate->s.curmod]->clear)
(&mstate->s, mstate->s.curmod);
mstate->s.minfo[mstate->s.curmod] = NULL;
}
mstate->s.curmod = curmod;
}
*ev = module_event_pass;
return 1;

View File

@ -6,7 +6,6 @@ server:
val-override-date: "20070916134226"
target-fetch-policy: "0 0 0 0 0"
send-client-subnet: 1.2.3.4
client-subnet-opcode: 20730
max-client-subnet-ipv4: 17
module-config: "subnetcache validator iterator"
verbosity: 3
@ -138,7 +137,7 @@ RANGE_BEGIN 0 100
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
@ -159,7 +158,7 @@ ENTRY_BEGIN
01 00 00 29 10 00 00 00
80 00 00 0b
50 fa 00 07 ; OPC, optlen
00 08 00 07 ; OPC, optlen
00 01 11 00 ; ip4, scope 17, source 0
7f 00 00 ;127.0.0.0/17
HEX_ANSWER_END
@ -180,7 +179,7 @@ ENTRY_BEGIN
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 11 ; source mask, scopemask
@ -201,7 +200,7 @@ ENTRY_BEGIN
01 00 00 29 10 00 00 00
80 00 00 0b
50 fa 00 07 ; OPC, optlen
00 08 00 07 ; OPC, optlen
00 01 12 00 ; ip4, scope 18, source 0
7f 00 00 ;127.0.0.0/18
HEX_ANSWER_END
@ -222,7 +221,7 @@ ENTRY_BEGIN
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
12 11 ; source mask, scopemask

View File

@ -1,7 +1,6 @@
server:
send-client-subnet: 5.0.15.10
send-client-subnet: 193.0.14.129
client-subnet-opcode: 20730
max-client-subnet-ipv4: 21
verbosity: 3
module-config: "subnetcache validator iterator"
@ -56,7 +55,7 @@ RANGE_BEGIN 0 100
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
15 00 ; source mask, scopemask
@ -128,7 +127,7 @@ RANGE_BEGIN 0 100
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
15 00 ; source mask, scopemask

View File

@ -1,6 +1,5 @@
server:
send-client-subnet: 5.0.15.10
client-subnet-opcode: 20730
max-client-subnet-ipv4: 21
verbosity: 3
module-config: "subnetcache validator iterator"
@ -125,7 +124,7 @@ RANGE_BEGIN 0 100
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
15 00 ; source mask, scopemask

View File

@ -1,161 +0,0 @@
server:
send-client-subnet: 5.0.15.10
client-subnet-opcode: 99
max-client-subnet-ipv4: 21
verbosity: 3
module-config: "subnetcache validator iterator"
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Works for other than default OPC
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
a.gtld-servers.net. IN AAAA
SECTION AUTHORITY
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode subdomain ednsdata
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN A
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ns.example.com. IN A 5.0.15.10
ENTRY_END
RANGE_END
RANGE_BEGIN 0 100
ADDRESS 5.0.15.10
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ns.example.com. IN A 5.0.15.10
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION ANSWER
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain ednsdata
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 4.3.2.1
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 63 ; OPC
00 07 ; option length
00 01 ; Family
15 00 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ENTRY_END
RANGE_END
;; ----------------------------------------
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 4.3.2.1
SECTION AUTHORITY
SECTION ADDITIONAL
ENTRY_END
SCENARIO_END

View File

@ -5,7 +5,6 @@ server:
val-override-date: "20070916134226"
target-fetch-policy: "0 0 0 0 0"
send-client-subnet: 1.2.3.4
client-subnet-opcode: 20730
max-client-subnet-ipv4: 17
module-config: "subnetcache validator iterator"
verbosity: 3
@ -142,7 +141,7 @@ RANGE_BEGIN 0 100
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask

View File

@ -6,7 +6,6 @@ server:
val-override-date: "20070916134226"
target-fetch-policy: "0 0 0 0 0"
send-client-subnet: 1.2.3.4
client-subnet-opcode: 20730
max-client-subnet-ipv4: 17
module-config: "subnetcache validator iterator"
verbosity: 3
@ -137,7 +136,7 @@ RANGE_BEGIN 0 100
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
@ -158,7 +157,7 @@ ENTRY_BEGIN
01 00 00 29 10 00 00 00
80 00 00 0b
50 fa 00 07 ; OPC, optlen
00 08 00 07 ; OPC, optlen
00 01 11 00 ; ip4, scope 17, source 0
7f 00 00 ;127.0.0.0/17
HEX_ANSWER_END
@ -182,7 +181,7 @@ ENTRY_BEGIN
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask

View File

@ -1,6 +1,5 @@
server:
send-client-subnet: 5.0.15.10
client-subnet-opcode: 20730
max-client-subnet-ipv4: 21
verbosity: 3
module-config: "subnetcache iterator"
@ -125,7 +124,7 @@ RANGE_BEGIN 0 100
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
50 fa ; OPC
00 08 ; OPC
00 07 ; option length
00 01 ; Family
15 00 ; source mask, scopemask

View File

@ -179,8 +179,9 @@ config_create(void)
#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 = 64;
cfg->max_client_subnet_ipv6 = 56;
#endif
cfg->views = NULL;
cfg->acls = NULL;
@ -517,10 +518,10 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("python-script:", python_script)
else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
#ifdef CLIENT_SUBNET
else S_STRLIST("send-client-subnet", client_subnet)
else S_NUMBER_OR_ZERO("max-client-subnet-ipv4:", max_client_subnet_ipv4)
else S_NUMBER_OR_ZERO("max-client-subnet-ipv6:", max_client_subnet_ipv6)
else S_NUMBER_OR_ZERO("client-subnet-opcode:", client_subnet_opcode)
/* 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);
@ -565,7 +566,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
* stub-ssl-upstream, forward-zone,
* name, forward-addr, forward-host,
* ratelimit-for-domain, ratelimit-below-domain,
* local-zone-tag, access-control-view */
* 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;
@ -841,7 +844,8 @@ config_get_option(struct config_file* cfg, const char* opt,
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_DEC(opt, "client-subnet-opcode", client_subnet_opcode)
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)
@ -1624,11 +1628,6 @@ config_apply(struct config_file* config)
MAX_NEG_TTL = (time_t)config->max_negative_ttl;
RTT_MIN_TIMEOUT = config->infra_cache_min_rtt;
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
#ifdef CLIENT_SUBNET
EDNSSUBNET_OPCODE = (uint16_t)config->client_subnet_opcode;
EDNSSUBNET_MAX_SUBNET_IP4 = (uint8_t)config->max_client_subnet_ipv4;
EDNSSUBNET_MAX_SUBNET_IP6 = (uint8_t)config->max_client_subnet_ipv6;
#endif
MINIMAL_RESPONSES = config->minimal_responses;
RRSET_ROUNDROBIN = config->rrset_roundrobin;
log_set_time_asc(config->log_time_ascii);

View File

@ -177,10 +177,12 @@ struct config_file {
* accept option from, linked list */
struct config_strlist* client_subnet;
/** opcode assigned by IANA for edns0-client-subnet option */
int client_subnet_opcode;
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 */
int max_client_subnet_ipv4;
int max_client_subnet_ipv6;
uint8_t max_client_subnet_ipv4;
uint8_t max_client_subnet_ipv6;
#endif
/** list of access control entries, linked list */
struct config_str2list* acls;
@ -440,9 +442,9 @@ struct config_file {
/** minimise QNAME in strict mode, minimise according to RFC.
* Do not apply fallback */
int qname_minimisation_strict;
/* SHM data - true if shm is enabled */
/** SHM data - true if shm is enabled */
int shm_enable;
/* SHM data - key for the shm */
/** SHM data - key for the shm */
int shm_key;
/** DNSCrypt */
@ -481,7 +483,7 @@ struct config_stub {
int isprime;
/** if forward-first is set (failover to without if fails) */
int isfirst;
/* use SSL for queries to this stub */
/** use SSL for queries to this stub */
int ssl_upstream;
};

File diff suppressed because it is too large Load Diff

View File

@ -301,6 +301,7 @@ 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) }

File diff suppressed because it is too large Load Diff

View File

@ -217,38 +217,39 @@ extern int yydebug;
VAR_IP_RATELIMIT_FACTOR = 427,
VAR_RATELIMIT_FACTOR = 428,
VAR_SEND_CLIENT_SUBNET = 429,
VAR_CLIENT_SUBNET_OPCODE = 430,
VAR_MAX_CLIENT_SUBNET_IPV4 = 431,
VAR_MAX_CLIENT_SUBNET_IPV6 = 432,
VAR_CAPS_WHITELIST = 433,
VAR_CACHE_MAX_NEGATIVE_TTL = 434,
VAR_PERMIT_SMALL_HOLDDOWN = 435,
VAR_QNAME_MINIMISATION = 436,
VAR_QNAME_MINIMISATION_STRICT = 437,
VAR_IP_FREEBIND = 438,
VAR_DEFINE_TAG = 439,
VAR_LOCAL_ZONE_TAG = 440,
VAR_ACCESS_CONTROL_TAG = 441,
VAR_LOCAL_ZONE_OVERRIDE = 442,
VAR_ACCESS_CONTROL_TAG_ACTION = 443,
VAR_ACCESS_CONTROL_TAG_DATA = 444,
VAR_VIEW = 445,
VAR_ACCESS_CONTROL_VIEW = 446,
VAR_VIEW_FIRST = 447,
VAR_SERVE_EXPIRED = 448,
VAR_FAKE_DSA = 449,
VAR_FAKE_SHA1 = 450,
VAR_LOG_IDENTITY = 451,
VAR_HIDE_TRUSTANCHOR = 452,
VAR_USE_SYSTEMD = 453,
VAR_SHM_ENABLE = 454,
VAR_SHM_KEY = 455,
VAR_DNSCRYPT = 456,
VAR_DNSCRYPT_ENABLE = 457,
VAR_DNSCRYPT_PORT = 458,
VAR_DNSCRYPT_PROVIDER = 459,
VAR_DNSCRYPT_SECRET_KEY = 460,
VAR_DNSCRYPT_PROVIDER_CERT = 461
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. */
@ -424,38 +425,39 @@ extern int yydebug;
#define VAR_IP_RATELIMIT_FACTOR 427
#define VAR_RATELIMIT_FACTOR 428
#define VAR_SEND_CLIENT_SUBNET 429
#define VAR_CLIENT_SUBNET_OPCODE 430
#define VAR_MAX_CLIENT_SUBNET_IPV4 431
#define VAR_MAX_CLIENT_SUBNET_IPV6 432
#define VAR_CAPS_WHITELIST 433
#define VAR_CACHE_MAX_NEGATIVE_TTL 434
#define VAR_PERMIT_SMALL_HOLDDOWN 435
#define VAR_QNAME_MINIMISATION 436
#define VAR_QNAME_MINIMISATION_STRICT 437
#define VAR_IP_FREEBIND 438
#define VAR_DEFINE_TAG 439
#define VAR_LOCAL_ZONE_TAG 440
#define VAR_ACCESS_CONTROL_TAG 441
#define VAR_LOCAL_ZONE_OVERRIDE 442
#define VAR_ACCESS_CONTROL_TAG_ACTION 443
#define VAR_ACCESS_CONTROL_TAG_DATA 444
#define VAR_VIEW 445
#define VAR_ACCESS_CONTROL_VIEW 446
#define VAR_VIEW_FIRST 447
#define VAR_SERVE_EXPIRED 448
#define VAR_FAKE_DSA 449
#define VAR_FAKE_SHA1 450
#define VAR_LOG_IDENTITY 451
#define VAR_HIDE_TRUSTANCHOR 452
#define VAR_USE_SYSTEMD 453
#define VAR_SHM_ENABLE 454
#define VAR_SHM_KEY 455
#define VAR_DNSCRYPT 456
#define VAR_DNSCRYPT_ENABLE 457
#define VAR_DNSCRYPT_PORT 458
#define VAR_DNSCRYPT_PROVIDER 459
#define VAR_DNSCRYPT_SECRET_KEY 460
#define VAR_DNSCRYPT_PROVIDER_CERT 461
#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
@ -466,7 +468,7 @@ union YYSTYPE
char* str;
#line 470 "util/configparser.h" /* yacc.c:1909 */
#line 472 "util/configparser.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;

View File

@ -131,7 +131,8 @@ extern struct config_parser_state* cfg_parser;
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
%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_OPCODE
%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 VAR_QNAME_MINIMISATION_STRICT VAR_IP_FREEBIND
@ -213,8 +214,9 @@ content_server: server_num_threads | server_verbosity | server_port |
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_opcode |
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 |
@ -368,15 +370,27 @@ server_send_client_subnet: VAR_SEND_CLIENT_SUBNET STRING_ARG
#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));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("option code expected");
else if(atoi($2) > 65535 || atoi($2) < 0)
yyerror("option code must be in interval [0, 65535]");
else cfg_parser->cfg->client_subnet_opcode = atoi($2);
OUTYY(("P(Depricated option, ignoring)\n"));
#else
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
#endif
@ -393,7 +407,7 @@ server_max_client_subnet_ipv4: VAR_MAX_CLIENT_SUBNET_IPV4 STRING_ARG
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 = atoi($2);
else cfg_parser->cfg->max_client_subnet_ipv4 = (uint8_t)atoi($2);
#else
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
#endif
@ -410,7 +424,7 @@ server_max_client_subnet_ipv6: VAR_MAX_CLIENT_SUBNET_IPV6 STRING_ARG
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 = atoi($2);
else cfg_parser->cfg->max_client_subnet_ipv6 = (uint8_t)atoi($2);
#else
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
#endif

View File

@ -983,19 +983,20 @@ int edns_opt_list_remove(struct edns_option** list, uint16_t code)
}
static int inplace_cb_reply_call_generic(
struct inplace_cb_reply* callback_list, enum inplace_cb_list_type type,
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_reply* cb;
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(cb->cb, type));
(void)(*cb->cb)(qinfo, qstate, rep, rcode, edns, &opt_list_out, region,
cb->cb_arg);
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;
@ -1048,11 +1049,13 @@ int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
struct regional* region)
{
struct inplace_cb_query* cb = env->inplace_cb_lists[inplace_cb_query];
struct inplace_cb* cb = env->inplace_cb_lists[inplace_cb_query];
for(; cb; cb=cb->next) {
fptr_ok(fptr_whitelist_inplace_cb_query(cb->cb));
(void)(*cb->cb)(qinfo, flags, qstate, addr, addrlen, zone, zonelen,
region, cb->cb_arg);
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;
}
@ -1060,11 +1063,13 @@ int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
int inplace_cb_edns_back_parsed_call(struct module_env* env,
struct module_qstate* qstate)
{
struct inplace_cb_edns_back_parsed* cb =
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(cb->cb));
(void)(*cb->cb)(qstate, cb->cb_arg);
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;
}

View File

@ -496,7 +496,7 @@ int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_type* fptr,
return 0;
}
int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* ATTR_UNUSED(fptr))
int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* fptr)
{
#ifdef CLIENT_SUBNET
if(fptr == &ecs_whitelist_check)
@ -506,7 +506,7 @@ int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* ATTR_UNUSED(fptr
}
int fptr_whitelist_inplace_cb_edns_back_parsed(
inplace_cb_edns_back_parsed_func_type* ATTR_UNUSED(fptr))
inplace_cb_edns_back_parsed_func_type* fptr)
{
#ifdef CLIENT_SUBNET
if(fptr == &ecs_edns_back_parsed)

View File

@ -123,115 +123,24 @@ edns_register_option(uint16_t opt_code, int bypass_cache_stage,
return 1;
}
static int
inplace_cb_reply_register_generic(inplace_cb_reply_func_type* cb,
enum inplace_cb_list_type type, void* cb_arg, struct module_env* env)
int
inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
size_t cbarg_len, struct module_env* env, int id)
{
struct inplace_cb_reply* callback;
struct inplace_cb_reply** prevp;
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_reply*)calloc(1, sizeof(*callback));
if(callback == NULL) {
log_err("out of memory during edns callback registration.");
return 0;
}
callback->next = NULL;
callback->cb = cb;
callback->cb_arg = cb_arg;
prevp = (struct inplace_cb_reply**) &env->inplace_cb_lists[type];
/* append at end of list */
while(*prevp != NULL)
prevp = &((*prevp)->next);
*prevp = callback;
return 1;
}
int
inplace_cb_reply_register(inplace_cb_reply_func_type* cb, void* cb_arg,
struct module_env* env)
{
return inplace_cb_reply_register_generic(cb, inplace_cb_reply, cb_arg,
env);
}
int
inplace_cb_reply_cache_register(inplace_cb_reply_func_type* cb, void* cb_arg,
struct module_env* env)
{
return inplace_cb_reply_register_generic(cb, inplace_cb_reply_cache,
cb_arg, env);
}
int
inplace_cb_reply_local_register(inplace_cb_reply_func_type* cb, void* cb_arg,
struct module_env* env)
{
return inplace_cb_reply_register_generic(cb, inplace_cb_reply_local,
cb_arg, env);
}
int
inplace_cb_reply_servfail_register(inplace_cb_reply_func_type* cb, void* cb_arg,
struct module_env* env)
{
return inplace_cb_reply_register_generic(cb, inplace_cb_reply_servfail,
cb_arg, env);
}
static void
inplace_cb_reply_delete_generic(struct module_env* env,
enum inplace_cb_list_type type)
{
struct inplace_cb_reply* curr = env->inplace_cb_lists[type];
struct inplace_cb_reply* tmp;
/* delete list */
while(curr) {
tmp = curr->next;
free(curr);
curr = tmp;
}
/* update head pointer */
env->inplace_cb_lists[type] = NULL;
}
void inplace_cb_reply_delete(struct module_env* env)
{
inplace_cb_reply_delete_generic(env, inplace_cb_reply);
}
void inplace_cb_reply_cache_delete(struct module_env* env)
{
inplace_cb_reply_delete_generic(env, inplace_cb_reply_cache);
}
void inplace_cb_reply_servfail_delete(struct module_env* env)
{
inplace_cb_reply_delete_generic(env, inplace_cb_reply_servfail);
}
int
inplace_cb_query_register(inplace_cb_query_func_type* cb, void* cbarg,
size_t cbarg_len, struct module_env* env)
{
struct inplace_cb_query* callback;
struct inplace_cb_query** prevp;
if(env->worker) {
log_err("invalid edns callback registration: "
"trying to register callback after module init phase");
return 0;
}
callback = (struct inplace_cb_query*)calloc(1, sizeof(*callback));
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;
if(cbarg) {
@ -244,8 +153,7 @@ inplace_cb_query_register(inplace_cb_query_func_type* cb, void* cbarg,
memcpy(callback->cb_arg, cbarg, cbarg_len);
}
prevp = (struct inplace_cb_query**)
&env->inplace_cb_lists[inplace_cb_query];
prevp = (struct inplace_cb**) &env->inplace_cb_lists[type];
/* append at end of list */
while(*prevp != NULL)
prevp = &((*prevp)->next);
@ -254,83 +162,30 @@ inplace_cb_query_register(inplace_cb_query_func_type* cb, void* cbarg,
}
void
inplace_cb_query_delete(struct module_env* env)
inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
int id)
{
struct inplace_cb_query* curr = env->inplace_cb_lists[inplace_cb_query];
struct inplace_cb_query* tmp;
/* delete list */
while(curr) {
tmp = curr->next;
free(curr->cb_arg);
free(curr);
curr = tmp;
}
/* update head pointer */
env->inplace_cb_lists[inplace_cb_query] = NULL;
}
struct inplace_cb* temp = env->inplace_cb_lists[type];
struct inplace_cb* prev = NULL;
int
inplace_cb_edns_back_parsed_register(inplace_cb_edns_back_parsed_func_type* cb,
void* cbarg, size_t cbarg_len, struct module_env* env)
{
struct inplace_cb_edns_back_parsed* callback;
struct inplace_cb_edns_back_parsed** prevp;
if(env->worker) {
log_err("invalid edns callback registration: "
"trying to register callback after module init phase");
return 0;
}
callback = (struct inplace_cb_edns_back_parsed*)calloc(1, sizeof(*callback));
if(callback == NULL) {
log_err("out of memory during edns callback registration.");
return 0;
}
callback->next = NULL;
callback->cb = cb;
if(cbarg) {
if(!(callback->cb_arg = calloc(1, cbarg_len))){
log_err("out of memory during edns callback argument"
"registration.");
free(callback);
return 0;
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;
}
memcpy(callback->cb_arg, cbarg, cbarg_len);
}
prevp = (struct inplace_cb_edns_back_parsed**)
&env->inplace_cb_lists[inplace_cb_edns_back_parsed];
/* append at end of list */
while(*prevp != NULL)
prevp = &((*prevp)->next);
*prevp = callback;
return 1;
}
void
inplace_cb_edns_back_parsed_delete(struct module_env* env)
{
struct inplace_cb_edns_back_parsed* curr =
env->inplace_cb_lists[inplace_cb_edns_back_parsed];
struct inplace_cb_edns_back_parsed* tmp;
/* delete list */
while(curr) {
tmp = curr->next;
free(curr->cb_arg);
free(curr);
curr = tmp;
}
/* update head pointer */
env->inplace_cb_lists[inplace_cb_edns_back_parsed] = NULL;
}
void
inplace_cb_lists_delete(struct module_env* env)
{
inplace_cb_reply_delete(env);
inplace_cb_reply_cache_delete(env);
inplace_cb_reply_servfail_delete(env);
inplace_cb_query_delete(env);
}
struct edns_known_option*

View File

@ -215,6 +215,19 @@ struct edns_known_option {
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,
@ -234,24 +247,7 @@ struct edns_known_option {
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, void* python_callback);
/**
* Inplace callback list of registered routines to be called before replying
* with a resolved query.
*/
struct inplace_cb_reply {
/** next in list */
struct inplace_cb_reply* next;
/**
* Inplace callback routine for cache stage response.
* called as cb(qinfo, qstate, qinfo, reply_info, rcode, edns,
* opt_list_out, region, python_callback);
* python_callback is only used for registering a python callback function.
*/
inplace_cb_reply_func_type* cb;
void* cb_arg;
};
struct regional* region, int id, void* callback);
/**
* Inplace callback function called before sending the query to a nameserver.
@ -273,24 +269,7 @@ struct inplace_cb_reply {
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,
void* python_callback);
/**
* Inplace callback list of registered routines to be called before quering a
* nameserver.
*/
struct inplace_cb_query {
/** next in list */
struct inplace_cb_query* next;
/**
* Inplace callback routine for cache stage response.
* called as cb(qinfo, flags, qstate, addr, addrlen, zone, zonelen,
* region, python_callback);
* python_callback is only used for registering a python callback function.
*/
inplace_cb_query_func_type* cb;
void* cb_arg;
};
int id, void* callback);
/**
* Inplace callback function called after receiving reply from back.
@ -300,22 +279,8 @@ struct inplace_cb_query {
* cb_args: argument passed when registering callback.
*/
typedef int inplace_cb_edns_back_parsed_func_type(struct module_qstate* qstate,
void* cb_args);
int id, void* cb_args);
/**
* Inplace callback list of registered routines to be called after receiving a
* reply from back.
*/
struct inplace_cb_edns_back_parsed {
/** next in list */
struct inplace_cb_edns_back_parsed* next;
/**
* Inplace callback routine for cache stage response.
* called as cb(qstate, cb_args);
*/
inplace_cb_edns_back_parsed_func_type* cb;
void* cb_arg;
};
/**
* Module environment.
* Services and data provided to the module.
@ -471,7 +436,7 @@ struct module_env {
void* modinfo[MAX_MODULE];
/* Shared linked list of inplace callback functions */
void* inplace_cb_lists[inplace_cb_types_total];
struct inplace_cb* inplace_cb_lists[inplace_cb_types_total];
/**
* Shared array of known edns options (size MAX_KNOWN_EDNS_OPTS).
@ -727,107 +692,29 @@ int edns_register_option(uint16_t opt_code, int bypass_cache_stage,
int no_aggregation, struct module_env* env);
/**
* Register an inplace callback function called before replying with a resolved
* query.
* Register an inplace callback function.
* @param cb: pointer to the callback function.
* @param cb_arg: optional argument for the callback function.
* @param type: inplace callback type.
* @param cbarg: argument for the callback function, or NULL.
* @param cbarg_len: size of cbars, or 0.
* @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_reply_register(inplace_cb_reply_func_type* cb, void* cb_arg,
struct module_env* env);
int
inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
size_t cbarg_len, struct module_env* env, int id);
/**
* Register an inplace callback function called before replying from the cache.
* @param cb: pointer to the callback function.
* @param cb_arg: optional argument for the callback function.
* Delete callback for specified type and module id.
* @param env: the module environment.
* @return true on success, false on failure (out of memory or trying to
* register after the environment is copied to the threads.)
* @param type: inplace callback type.
* @param id: module id.
*/
int inplace_cb_reply_cache_register(inplace_cb_reply_func_type* cb, void* cb_arg,
struct module_env* env);
/**
* Register an inplace callback function called before replying with local
* data or Chaos reply.
* @param cb: pointer to the callback function.
* @param cb_arg: optional argument for the callback function.
* @param env: the module environment.
* @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_reply_local_register(inplace_cb_reply_func_type* cb, void* cb_arg,
struct module_env* env);
/**
* Register an inplace callback function called before replying with servfail.
* @param cb: pointer to the callback function.
* @param cb_arg: optional argument for the callback function.
* @param env: the module environment.
* @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_reply_servfail_register(inplace_cb_reply_func_type* cb,
void* cb_arg, struct module_env* env);
/**
* Delete the inplace_cb_reply callback linked list.
* @param env: the module environment.
*/
void inplace_cb_reply_delete(struct module_env* env);
/**
* Delete the inplace_cb_reply_cache callback linked list.
* @param env: the module environment.
*/
void inplace_cb_reply_cache_delete(struct module_env* env);
/**
* Delete the inplace_cb_reply_servfail callback linked list.
* @param env: the module environment.
*/
void inplace_cb_reply_servfail_delete(struct module_env* env);
/**
* Register an inplace callback function called before quering a nameserver.
* @param cb: pointer to the callback function.
* @param cbarg: optional argument for the callback function.
* @param cbarg_len: length of the argument for the callback function, 0 if
* empty.
* @param env: the module environment.
* @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_query_register(inplace_cb_query_func_type* cb, void* cbarg,
size_t cbarg_len, struct module_env* env);
/**
* Delete the inplace_cb_query callback linked list.
* @param env: the module environment.
*/
void inplace_cb_query_delete(struct module_env* env);
/**
* Register an inplace callback function called after receiving an reply from a
* namerserver.
* @param cb: pointer to the callback function.
* @param cbarg: optional argument for the callback function.
* @param cbarg_len: length of the argument for the callback function, 0 if
* empty.
* @param env: the module environment.
* @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_edns_back_parsed_register(inplace_cb_edns_back_parsed_func_type* cb,
void* cbarg, size_t cbarg_len, struct module_env* env);
/**
* Delete the inplace_cb_edns_back_parsed callback linked list.
* @param env: the module environment.
*/
void inplace_cb_edns_back_parsed_delete(struct module_env* env);
void
inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
int id);
/**
* Delete all the inplace callback linked lists.