sync code with last fixes and improvements from OpenBSD

This commit is contained in:
purplerain 2023-07-27 09:35:44 +00:00
parent 58df21ce75
commit f960599e67
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
399 changed files with 7016 additions and 6902 deletions

View file

@ -5,22 +5,22 @@
* Copyright (c) 2013, 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
@ -59,7 +59,7 @@
#include "iterator/iter_utils.h"
/** externally called */
void
void
subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
{
struct subnet_msg_cache_data *r;
@ -70,12 +70,12 @@ subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
}
/** externally called */
size_t
size_t
msg_cache_sizefunc(void *k, void *d)
{
struct msgreply_entry *q = (struct msgreply_entry*)k;
struct subnet_msg_cache_data *r = (struct subnet_msg_cache_data*)d;
size_t s = sizeof(struct msgreply_entry)
size_t s = sizeof(struct msgreply_entry)
+ sizeof(struct subnet_msg_cache_data)
+ q->key.qname_len + lock_get_mem(&q->entry.lock);
s += addrtree_size(r->tree4);
@ -89,7 +89,7 @@ subnet_new_qstate(struct module_qstate *qstate, int id)
{
struct subnet_qstate *sq = (struct subnet_qstate*)regional_alloc(
qstate->region, sizeof(struct subnet_qstate));
if(!sq)
if(!sq)
return 0;
qstate->minfo[id] = sq;
memset(sq, 0, sizeof(*sq));
@ -107,26 +107,26 @@ subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
sldns_buffer* buf = qstate->env->scratch_buffer;
if(ecs->subnet_validdata) {
log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 ||
log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 ||
ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6);
log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 ||
log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 ||
ecs->subnet_source_mask <= INET_SIZE*8);
log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 ||
log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 ||
ecs->subnet_source_mask <= INET6_SIZE*8);
sn_octs = ecs->subnet_source_mask / 8;
sn_octs_remainder =
(size_t)((ecs->subnet_source_mask % 8)>0?1:0);
log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE);
sldns_buffer_clear(buf);
sldns_buffer_write_u16(buf, ecs->subnet_addr_fam);
sldns_buffer_write_u8(buf, ecs->subnet_source_mask);
sldns_buffer_write_u8(buf, ecs->subnet_scope_mask);
sldns_buffer_write(buf, ecs->subnet_addr, sn_octs);
if(sn_octs_remainder)
sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] &
sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] &
~(0xFF >> (ecs->subnet_source_mask % 8)));
sldns_buffer_flip(buf);
@ -145,7 +145,7 @@ int ecs_whitelist_check(struct query_info* qinfo,
{
struct subnet_qstate *sq;
struct subnet_env *sn_env;
if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
return 1;
sn_env = (struct subnet_env*)qstate->env->modinfo[id];
@ -158,7 +158,7 @@ int ecs_whitelist_check(struct query_info* qinfo,
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
qstate->env->cfg->client_subnet_always_forward) ||
ecs_is_whitelisted(sn_env->whitelist,
ecs_is_whitelisted(sn_env->whitelist,
addr, addrlen, qinfo->qname, qinfo->qname_len,
qinfo->qclass))) {
/* Address on whitelist or client query contains ECS option, we
@ -299,8 +299,8 @@ sizefunc(void *elemptr) {
* Select tree from cache entry based on edns data.
* If for address family not present it will create a new one.
* NULL on failure to create. */
static struct addrtree*
get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
static struct addrtree*
get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
struct subnet_env *env, struct config_file* cfg)
{
struct addrtree *tree;
@ -385,7 +385,7 @@ update_cache(struct module_qstate *qstate, int id)
log_err("subnetcache: cache insertion failed");
return;
}
/* store RRsets */
for(i=0; i<rep->rrset_count; i++) {
rep->ref[i].key = rep->rrsets[i];
@ -397,7 +397,7 @@ update_cache(struct module_qstate *qstate, int id)
if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
only_match_scope_zero = 1;
else only_match_scope_zero = 0;
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
edns->subnet_source_mask, sq->max_scope, rep,
rep->ttl, *qstate->env->now, only_match_scope_zero);
@ -437,7 +437,7 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
lock_rw_unlock(&e->lock);
return 0;
}
node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
ecs->subnet_source_mask, *env->now);
if (!node) { /* plain old cache miss */
lock_rw_unlock(&e->lock);
@ -449,11 +449,11 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
env->scratch);
scope = (uint8_t)node->scope;
lock_rw_unlock(&e->lock);
if (!qstate->return_msg) { /* Failed allocation or expired TTL */
return 0;
}
if (sq->subnet_downstream) { /* relay to interested client */
sq->ecs_client_out.subnet_scope_mask = scope;
sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
@ -473,7 +473,7 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
* @param net: Number of bits to test.
* @return: 1 if equal, 0 otherwise.
*/
static int
static int
common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
{
size_t n = (size_t)net / 8;
@ -498,7 +498,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
* module_finished */
return module_finished;
}
/* We have not asked for subnet data */
if (!sq->subnet_sent) {
if (s_in->subnet_validdata)
@ -507,7 +507,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
cp_edns_bad_response(c_out, c_in);
return module_finished;
}
/* subnet sent but nothing came back */
if (!s_in->subnet_validdata) {
/* The authority indicated no support for edns subnet. As a
@ -524,15 +524,15 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
cp_edns_bad_response(c_out, c_in);
return module_finished;
}
/* Being here means we have asked for and got a subnet specific
* answer. Also, the answer from the authority is not yet cached
/* Being here means we have asked for and got a subnet specific
* answer. Also, the answer from the authority is not yet cached
* anywhere. */
/* can we accept response? */
if(s_out->subnet_addr_fam != s_in->subnet_addr_fam ||
s_out->subnet_source_mask != s_in->subnet_source_mask ||
!common_prefix(s_out->subnet_addr, s_in->subnet_addr,
!common_prefix(s_out->subnet_addr, s_in->subnet_addr,
s_out->subnet_source_mask))
{
/* we can not accept, restart query without option */
@ -550,7 +550,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
}
sne->num_msg_nocache++;
lock_rw_unlock(&sne->biglock);
if (sq->subnet_downstream) {
/* Client wants to see the answer, echo option back
* and adjust the scope. */
@ -588,7 +588,7 @@ parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
ecs->subnet_source_mask = ecs_option->opt_data[2];
ecs->subnet_scope_mask = ecs_option->opt_data[3];
/* remaining bytes indicate address */
/* validate input*/
/* option length matches calculated length? */
if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4))
@ -604,9 +604,9 @@ parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
return 0;
} else
return 0;
/* valid ECS data, write to ecs_data */
if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4,
if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4,
ecs_option->opt_len - 4, ecs->subnet_source_mask))
return 0;
ecs->subnet_validdata = 1;
@ -651,7 +651,7 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
int id, void* ATTR_UNUSED(cbargs))
{
struct subnet_qstate *sq;
if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id]))
return 1;
@ -703,7 +703,7 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
{
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(
@ -728,14 +728,14 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
}
void
subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
int id, struct outbound_entry* outbound)
{
struct subnet_env *sne = qstate->env->modinfo[id];
struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
verbose(VERB_QUERY, "subnetcache[module %d] operate: extstate:%s "
"event:%s", id, strextstate(qstate->ext_state[id]),
"event:%s", id, strextstate(qstate->ext_state[id]),
strmodulevent(event));
log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo);
@ -768,7 +768,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
&qstate->mesh_info->reply_list->query_reply.client_addr,
&sq->ecs_client_in, qstate->env->cfg);
}
if(sq->ecs_client_in.subnet_validdata == 0) {
/* No clients are interested in result or we could not
* parse it, we don't do client subnet */
@ -811,18 +811,18 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
}
lock_rw_unlock(&sne->biglock);
}
sq->ecs_server_out.subnet_addr_fam =
sq->ecs_client_in.subnet_addr_fam;
sq->ecs_server_out.subnet_source_mask =
sq->ecs_client_in.subnet_source_mask;
/* Limit source prefix to configured maximum */
if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4
if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4
&& sq->ecs_server_out.subnet_source_mask >
qstate->env->cfg->max_client_subnet_ipv4)
sq->ecs_server_out.subnet_source_mask =
qstate->env->cfg->max_client_subnet_ipv4;
else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6
else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6
&& sq->ecs_server_out.subnet_source_mask >
qstate->env->cfg->max_client_subnet_ipv6)
sq->ecs_server_out.subnet_source_mask =
@ -840,7 +840,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
/* ECS specific data required, do not look at the global
* cache in other modules. */
qstate->no_cache_lookup = 1;
/* pass request to next module */
verbose(VERB_ALGO,
"subnetcache: not found in cache. pass to next module");
@ -906,13 +906,13 @@ subnetmod_get_mem(struct module_env *env, int id)
{
struct subnet_env *sn_env = env->modinfo[id];
if (!sn_env) return 0;
return sizeof(*sn_env) +
return sizeof(*sn_env) +
slabhash_get_mem(sn_env->subnet_msg_cache) +
ecs_whitelist_get_mem(sn_env->whitelist);
}
/**
* The module function block
* The module function block
*/
static struct module_func_block subnetmod_block = {
"subnetcache", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,