intermediate commit

This commit is contained in:
TCY16
2022-10-18 15:25:47 +02:00
parent 730b55c94a
commit eb85f34351
6 changed files with 162 additions and 81 deletions
+90 -3
View File
@@ -68,6 +68,7 @@
#include "sldns/str2wire.h"
#include "sldns/parseutil.h"
#include "sldns/sbuffer.h"
#include "daemon/worker.h"
/* in msec */
int UNKNOWN_SERVER_NICENESS = 376;
@@ -3872,6 +3873,82 @@ process_request(struct module_qstate* qstate, struct iter_qstate* iq,
iter_handle(qstate, iq, ie, id);
}
/** find the bound addr in the list of interfaces */
static int
get_bound_ip_if(struct outside_network* outnet,
struct sockaddr_storage *bound_addr, socklen_t bound_addrlen,
struct port_if* pif_return)
{
int i = 0;
struct port_if* pif_list;
int pif_list_len;
/* Get the list of interfaces and check that that list isn't just the
* "any" address */
if(addr_is_ip6(bound_addr, bound_addrlen)) {
pif_list = outnet->ip6_ifs;
pif_list_len = outnet->num_ip6;
// @TODO fix IPv6
} else {
pif_list = outnet->ip4_ifs;
pif_list_len = outnet->num_ip4;
struct sockaddr_storage addr_any;
socklen_t addr_any_len = 0;
struct sockaddr_storage addr_fake;
socklen_t addr_fake_len = 0;
if (!ipstrtoaddr("0.0.0.0", 0, &addr_any, &addr_any_len)) {
// @TODO do something
}
if (!ipstrtoaddr("10.10.1.1", 0, &addr_fake, &addr_fake_len)) {
// @TODO do something
}
log_addr(VERB_DETAIL, "!!!!! outnet->ip4_ifs->addr", &outnet->ip4_ifs->addr, bound_addrlen);
log_addr(VERB_DETAIL, "!!!!! addr_any", &addr_any, addr_any_len);
/* if we let the kernel decide the IP, fill in
* the previously used */
if (pif_list_len == 1 &&
sockaddr_cmp_addr(&outnet->ip4_ifs->addr, outnet->ip4_ifs->addrlen,
&addr_any, addr_any_len) == 0) {
/* return the interface from the list, but substitute the
* previously used address */
memcpy(pif_return, outnet->ip4_ifs, sizeof(struct port_if));
memcpy(&pif_return->addr, &addr_fake, addr_fake_len);
pif_return->addrlen = addr_fake_len;
log_addr(VERB_DETAIL, "!!!!! get_bound_ip_if: addr from ip4_ifs == 0.0.0.0, new is:", &pif_return->addr, outnet->ip4_ifs->addrlen);
return 1;
}
}
if (pif_list_len == 0) {
return 0;
}
for (i = 0; i < pif_list_len; i++) {
struct port_if *iface = &pif_list[i];
if (iface->addrlen == bound_addrlen &&
memcmp(&iface->addr, bound_addr, bound_addrlen)) {
memcpy(pif_return, iface, sizeof(struct port_if));
return 1;
}
}
return 0;
}
/** process authoritative server reply */
static void
process_response(struct module_qstate* qstate, struct iter_qstate* iq,
@@ -3940,19 +4017,29 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
goto handle_it;
}
/* handle the upstream response cookie if enabled*/
/* handle the upstream response cookie if enabled */
if(qstate->env->cfg->upstream_cookies) {
if (edns.opt_list_in &&
(cookie = edns_list_get_option(edns.opt_list_in,
LDNS_EDNS_COOKIE))){
struct sockaddr_storage bound_addr;
socklen_t bound_addrlen = sizeof(struct sockaddr);
struct port_if pif;
struct port_if *pif_ptr = &pif;
if(getsockname(qstate->reply->c->fd,
(struct sockaddr *) &bound_addr,
&bound_addrlen) != -1) {
log_addr(VERB_DETAIL, "!!!!! iterator:udp socket:", &bound_addr, bound_addrlen);
if (!(get_bound_ip_if(qstate->env->worker->back,
&bound_addr, bound_addrlen, pif_ptr))) {
bound_addrlen = 0;
}
log_addr(VERB_DETAIL, "!!!!! iterator:pif addr:", &pif.addr, pif.addrlen);
} else {
bound_addrlen = 0;
}
@@ -3964,8 +4051,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
if (cookie->opt_len == 24 &&
infra_set_server_cookie(qstate->env->infra_cache,
&qstate->reply->addr, qstate->reply->addrlen,
iq->dp->name, iq->dp->namelen, &bound_addr,
bound_addrlen, cookie) >= 0) {
iq->dp->name, iq->dp->namelen, pif_ptr,
cookie) >= 0) {
/* log_hex() uses the verbosity levels of verbose() */
log_hex("complete cookie: ", cookie->opt_data,
cookie->opt_len);
+30 -61
View File
@@ -383,18 +383,25 @@ infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr,
return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
}
/* helper function to fill in random data into the client cookie*/
void infra_fill_client_cookie_random(struct infra_cache* infra,
uint8_t* data) {
int i;
for (i = 0; i < 8; i++) {
data[i] = ub_random_max(infra->random_state, 256);
}
}
/** init the data elements */
static void
data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
time_t timenow)
{
int i;
struct infra_data* data;
uint8_t cookie[8] = {0,0,0,0,0,0,0,0};
uint8_t client_cookie_data[8] = {0,0,0,0,0,0,0,0};
for (i = 0; i < 8; i++) {
cookie[i] = ub_random_max(infra->random_state, 256);
}
infra_fill_client_cookie_random(infra, client_cookie_data);
data = (struct infra_data*)e->data;
data->ttl = timenow + infra->host_ttl;
@@ -404,7 +411,8 @@ data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
data->probedelay = 0;
/* set EDNS cookie to zero, as this also sets the starting state*/
memset(&data->cookie, 0, sizeof(struct edns_cookie));
memcpy(data->cookie.data.cookie, cookie, 8);
data->cookie.pif.out = NULL;
memcpy(data->cookie.data.cookie, client_cookie_data, 8);
data->isdnsseclame = 0;
data->rec_lame = 0;
data->lame_type_A = 0;
@@ -705,41 +713,10 @@ infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
return 1;
}
/** find the bound addr in the list of interfaces */
static int
get_bound_ip_if(struct outside_network* outnet,
struct sockaddr_storage bound_addr, socklen_t bound_addrlen,
struct port_if** pif_return)
{
int i = 0;
struct port_if* pif_list;
int pif_list_len;
if(addr_is_ip6(&bound_addr, bound_addrlen)) {
pif_list = outnet->ip6_ifs;
pif_list_len = outnet->num_ip6;
} else {
pif_list = outnet->ip4_ifs;
pif_list_len = outnet->num_ip4;
}
for (i = 0; i < pif_list_len; i++) {
struct port_if *iface = &pif_list[i];
if (iface->addrlen == bound_addrlen &&
memcmp(&iface->addr, &bound_addr, bound_addrlen)) {
*pif_return = iface;
return 1;
}
}
return 0;
}
int
infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen,
time_t timenow, struct outside_network* outnet, struct port_if** pif,
struct edns_cookie* cookie)
time_t timenow, struct edns_cookie* cookie)
{
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
name, namelen, 1);
@@ -763,21 +740,11 @@ infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
data = (struct infra_data*) e->data;
if (data->cookie.state == SERVER_COOKIE_LEARNED) {
// lookup bound interface
log_err("!!!!! infra_get_cookie:bound_addrlen: %d", data->cookie.bound_addrlen);
log_addr(VERB_OPS, "!!!!! infra_get_cookie:bound_addr, len:", &data->cookie.bound_addr,
data->cookie.bound_addrlen);
if (!(get_bound_ip_if(outnet, data->cookie.bound_addr,
data->cookie.bound_addrlen, pif))) {
log_err("!!!!!!!! creating new cookie for changed interface");
data_entry_init(infra, e, timenow);
}
}
// @TODO uggo: data has changed
data = (struct infra_data*) e->data;
// @TODO fix this logic. does the cookie status matter?
/* renew cookie if the address isn't available isn't stored */
// if (data->cookie->addrlen == 0) {
// infra_fill_client_cookie_random(infra, &data->cookie->data);
// }
memcpy(cookie, &data->cookie, sizeof(struct edns_cookie));
@@ -790,10 +757,9 @@ infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
return 1;
}
int
int
infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen,
struct sockaddr_storage* bound_addr, socklen_t bound_addrlen,
socklen_t addrlen, uint8_t* name, size_t namelen, struct port_if *pif,
struct edns_option* cookie)
{
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
@@ -832,8 +798,8 @@ infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr
return -1;
}
if (!(data->cookie.bound_addrlen == bound_addrlen) &&
memcpy(&data->cookie.bound_addr, bound_addr, bound_addrlen)){
if (!(data->cookie.pif.addrlen == pif->addrlen) &&
memcmp(&data->cookie.pif.addr, &pif->addr, pif->addrlen)){
// @TODO do something? this _should_ only happen on reloads?
}
@@ -872,9 +838,12 @@ infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr
/* store the server cookie */
memcpy(data->cookie.data.cookie, cookie->opt_data, 24);
data->cookie.state = SERVER_COOKIE_LEARNED;
if (bound_addrlen > 0) {
memcpy(&data->cookie.bound_addr, bound_addr, bound_addrlen);
data->cookie.bound_addrlen = bound_addrlen;
/* store the inbound interface we receive this cookie on */
if (pif->addrlen > 0) {
memcpy(&data->cookie.pif,
pif, sizeof(struct port_if));
data->cookie.pif.addrlen = pif->addrlen;
}
verbose(VERB_QUERY, "storing received server cookie from upstream");
lock_rw_unlock(&e->lock);
+7 -8
View File
@@ -90,8 +90,9 @@ enum edns_cookie_state
struct edns_cookie {
enum edns_cookie_state state;
struct edns_cookie_data data;
struct sockaddr_storage bound_addr;
socklen_t bound_addrlen;
struct port_if pif;
// struct sockaddr_storage bound_addr;
// socklen_t bound_addrlen;
};
@@ -375,13 +376,13 @@ int infra_edns_update(struct infra_cache* infra,
* @param name: name of zone
* @param namelen: length of name
* @param timenow: what time it is now.
* @param pif: the interface which contains the outgoing address that we bind to
* @param cookie: the cookie that is retrieved from cache on success.
* @return: 0 on error, cookie pointer remains unchanged then.
*/
int infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen,
time_t timenow, struct outside_network* outnet, struct port_if** pif,
struct edns_cookie* cookie);
time_t timenow, struct edns_cookie* cookie);
/**
* Find the cookie entry in the cache and update it with to make a 'complete cookie'
@@ -394,16 +395,14 @@ int infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
* @param name: name of zone
* @param namelen: length of name
* @param timenow: what time it is now.
* @param bound_addr: the outgoing address that we bind to this cookie
* @param bound_addr: the length of the bound address
* @param pif: the interface which contains the outgoing address that we bind to
* @param cookie: the EDNS cookie option we want to store.
* @return -1 if the wrong client cookie is found, 0 if the entry isn't found in
* the cache and a new one is inserted, 1 if the complete cookie is inserted
* or unchanged.
*/
int infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen,
struct sockaddr_storage* bound_addr, socklen_t bound_addrlen,
socklen_t addrlen, uint8_t* name, size_t namelen, struct port_if *pif,
struct edns_option* cookie);
/**
+4 -4
View File
@@ -630,7 +630,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
&& !(errno == EADDRNOTAVAIL && verbosity < 4 && !listen)
#endif
) {
log_err_addr("can't bind socket", strerror(errno),
log_err_addr("1can't bind socket", strerror(errno),
(struct sockaddr_storage*)addr, addrlen);
}
#endif /* EADDRINUSE */
@@ -638,7 +638,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
if(WSAGetLastError() != WSAEADDRINUSE &&
WSAGetLastError() != WSAEADDRNOTAVAIL &&
!(WSAGetLastError() == WSAEACCES && verbosity < 4 && !listen)) {
log_err_addr("can't bind socket",
log_err_addr("2can't bind socket",
wsa_strerror(WSAGetLastError()),
(struct sockaddr_storage*)addr, addrlen);
}
@@ -824,12 +824,12 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
if(addr->ai_family==AF_INET6 && errno==EINVAL)
*noproto = 1;
else {
log_err_addr("can't bind socket", strerror(errno),
log_err_addr("3can't bind socket", strerror(errno),
(struct sockaddr_storage*)addr->ai_addr,
addr->ai_addrlen);
}
#else
log_err_addr("can't bind socket",
log_err_addr("4can't bind socket",
wsa_strerror(WSAGetLastError()),
(struct sockaddr_storage*)addr->ai_addr,
addr->ai_addrlen);
+30 -4
View File
@@ -1407,6 +1407,11 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
struct pending* p;
verbose(VERB_ALGO, "answer cb");
log_err("!!!!! outnet_udp_cb: HERE, error: %d", error);
// @TODO this is the function where we find the failed kernel call
if(error != NETEVENT_NOERROR) {
verbose(VERB_QUERY, "outnetudp got udp error %d", error);
return 0;
@@ -1939,6 +1944,9 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
int port, int* inuse, struct ub_randstate* rnd, int dscp)
{
int fd, noproto;
log_err("!!!!! udp_sockport: HERE!");
if(addr_is_ip6(addr, addrlen)) {
int freebind = 0;
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
@@ -2032,6 +2040,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
"outgoing interfaces of that family");
return 0;
}
log_assert(outnet->unused_fds);
tries = 0;
while(1) {
@@ -2069,7 +2078,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
}
}
log_err("!!!!! pif->inuse: %d, pif->maxout: %d", pif->inuse, pif->maxout);
log_err("!!!!! select_ifport:pif->inuse: %d, pif->maxout: %d", pif->inuse, pif->maxout);
/* try to open new port, if fails, loop to try again */
log_assert(pif->inuse < pif->maxout);
@@ -2080,6 +2089,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
portno, &inuse, outnet->rnd, outnet->ip_dscp);
if(fd == -1 && !inuse) {
log_err("!!!! select_ifport:nonrecoverable error making socket");
/* nonrecoverable error making socket */
return 0;
}
@@ -2616,7 +2626,17 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
sq->status = serviced_initial;
sq->retry = 0;
sq->to_be_deleted = 0;
sq->bound_interface = bound_interface;
if (bound_interface != NULL) {
sq->bound_interface = regional_alloc_init(region,
bound_interface, sizeof(struct port_if));
if (!sq->bound_interface) {
alloc_reg_release(alloc, region);
free(sq);
return NULL;
}
} else {
sq->bound_interface = NULL;
}
sq->padding_block_size = pad_queries_block_size;
#ifdef UNBOUND_DEBUG
ins =
@@ -3377,7 +3397,7 @@ outnet_serviced_query(struct outside_network* outnet,
struct edns_option* backed_up_opt_list = qstate->edns_opts_back_out;
struct edns_option* per_upstream_opt_list = NULL;
time_t timenow = 0;
struct port_if* pif;
struct port_if* pif = NULL;
/* If we have an already populated EDNS option list make a copy since
* we may now add upstream specific EDNS options. */
@@ -3416,12 +3436,18 @@ outnet_serviced_query(struct outside_network* outnet,
if (env->cfg->upstream_cookies &&
infra_get_cookie(env->infra_cache, addr, addrlen, zone, zonelen,
*env->now, outnet, &pif, &cookie)) {
*env->now, &cookie)) {
if (cookie.state == SERVER_COOKIE_LEARNED) {
/* We known the complete cookie, so we attach it */
edns_opt_list_append(&per_upstream_opt_list, LDNS_EDNS_COOKIE,
24, cookie.data.cookie, region);
if (cookie.pif.addrlen > 0) {
pif = &cookie.pif;
log_addr(VERB_DETAIL, "!!!!! outnet_serviced_query:pif addr:", &cookie.pif.addr, cookie.pif.addrlen);
}
} else if (cookie.state == SERVER_COOKIE_UNKNOWN) {
/* We know just client cookie, so we attach it */
edns_opt_list_append(&per_upstream_opt_list, LDNS_EDNS_COOKIE,
+1 -1
View File
@@ -527,7 +527,7 @@ struct serviced_query {
struct comm_timer* timer;
/** true if serviced_query is currently doing net I/O and may block */
int busy;
/** Interface bound to the EDNS cookie @TODO fix this */
/** interface bound to the EDNS cookie @TODO fix this */
struct port_if* bound_interface;
};