mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-10-14 12:35:11 +02:00
Compare commits
43
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd0a585fbe | ||
|
|
7c624d1dcd | ||
|
|
e23010c18e | ||
|
|
ddcbc291fe | ||
|
|
a119b1abc6 | ||
|
|
f62214e714 | ||
|
|
3d1aaae57a | ||
|
|
614dcbf675 | ||
|
|
add0065c43 | ||
|
|
3d53f08bd8 | ||
|
|
0dcd4cd2e8 | ||
|
|
b449d6f713 | ||
|
|
6932ae18f5 | ||
|
|
e2537840ba | ||
|
|
b425be8e10 | ||
|
|
bb408e503c | ||
|
|
8942d11bb3 | ||
|
|
cb027ae649 | ||
|
|
48d0aea60a | ||
|
|
17bbcac979 | ||
|
|
fd8ebbb19c | ||
|
|
2adbbea365 | ||
|
|
156c00a727 | ||
|
|
d753f95956 | ||
|
|
61d6c0e766 | ||
|
|
b4daa2d0fa | ||
|
|
425b701fb9 | ||
|
|
0a5cde80f1 | ||
|
|
58ede90fdb | ||
|
|
55ae8da032 | ||
|
|
6bd86df72e | ||
|
|
0efd3605cc | ||
|
|
a2f2f53ef9 | ||
|
|
b5a03093f6 | ||
|
|
8eba898135 | ||
|
|
56f66de89f | ||
|
|
2fbaee2255 | ||
|
|
a122490461 | ||
|
|
7826b4f306 | ||
|
|
380994219f | ||
|
|
153accb8de | ||
|
|
7bb1c62263 | ||
|
|
1578b6e180 |
+4
-2
@@ -125,7 +125,7 @@ services/localzone.c services/mesh.c services/modstack.c services/view.c \
|
|||||||
services/rpz.c util/rfc_1982.c \
|
services/rpz.c util/rfc_1982.c \
|
||||||
services/outbound_list.c services/outside_network.c util/alloc.c \
|
services/outbound_list.c services/outside_network.c util/alloc.c \
|
||||||
util/config_file.c util/configlexer.c util/configparser.c \
|
util/config_file.c util/configlexer.c util/configparser.c \
|
||||||
util/shm_side/shm_main.c services/authzone.c \
|
util/shm_side/shm_main.c services/authzone.c services/authload.c \
|
||||||
util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
|
util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
|
||||||
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
|
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
|
||||||
util/rtt.c util/siphash.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \
|
util/rtt.c util/siphash.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \
|
||||||
@@ -152,7 +152,8 @@ autotrust.lo val_anchor.lo rpz.lo rfc_1982.lo proxy_protocol.lo \
|
|||||||
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
|
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
|
||||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo \
|
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo \
|
||||||
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
|
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
|
||||||
$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo timeval_func.lo
|
$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo timeval_func.lo \
|
||||||
|
authload.lo
|
||||||
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
|
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
|
||||||
outside_network.lo
|
outside_network.lo
|
||||||
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
|
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
|
||||||
@@ -721,6 +722,7 @@ depend:
|
|||||||
ipset.lo ipset.o: $(srcdir)/ipset/ipset.c
|
ipset.lo ipset.o: $(srcdir)/ipset/ipset.c
|
||||||
doqclient.lo doqclient.o: $(srcdir)/testcode/doqclient.c
|
doqclient.lo doqclient.o: $(srcdir)/testcode/doqclient.c
|
||||||
unitdoq.lo unitdoq.o: $(srcdir)/testcode/unitdoq.c
|
unitdoq.lo unitdoq.o: $(srcdir)/testcode/unitdoq.c
|
||||||
|
authload.lo authload.o: $(srcdir)/services/authload.c
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
|
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
|
||||||
|
|||||||
@@ -86,6 +86,7 @@
|
|||||||
#include "services/view.h"
|
#include "services/view.h"
|
||||||
#include "services/modstack.h"
|
#include "services/modstack.h"
|
||||||
#include "services/authzone.h"
|
#include "services/authzone.h"
|
||||||
|
#include "services/authload.h"
|
||||||
#include "util/module.h"
|
#include "util/module.h"
|
||||||
#include "util/random.h"
|
#include "util/random.h"
|
||||||
#include "util/tube.h"
|
#include "util/tube.h"
|
||||||
@@ -590,6 +591,17 @@ daemon_init(void)
|
|||||||
free(daemon);
|
free(daemon);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if(!(daemon->auth_load_info = auth_load_info_create())) {
|
||||||
|
edns_strings_delete(daemon->env->edns_strings);
|
||||||
|
auth_zones_delete(daemon->env->auth_zones);
|
||||||
|
acl_list_delete(daemon->acl_interface);
|
||||||
|
acl_list_delete(daemon->acl);
|
||||||
|
tcl_list_delete(daemon->tcl);
|
||||||
|
edns_known_options_delete(daemon->env);
|
||||||
|
free(daemon->env);
|
||||||
|
free(daemon);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return daemon;
|
return daemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1164,6 +1176,7 @@ daemon_fork(struct daemon* daemon)
|
|||||||
|
|
||||||
/* we exited! a signal happened! Stop other threads */
|
/* we exited! a signal happened! Stop other threads */
|
||||||
daemon_stop_others(daemon);
|
daemon_stop_others(daemon);
|
||||||
|
auth_load_stop_threads(daemon);
|
||||||
|
|
||||||
/* Shutdown SHM */
|
/* Shutdown SHM */
|
||||||
shm_main_shutdown(daemon);
|
shm_main_shutdown(daemon);
|
||||||
@@ -1262,6 +1275,7 @@ daemon_delete(struct daemon* daemon)
|
|||||||
edns_strings_delete(daemon->env->edns_strings);
|
edns_strings_delete(daemon->env->edns_strings);
|
||||||
auth_zones_delete(daemon->env->auth_zones);
|
auth_zones_delete(daemon->env->auth_zones);
|
||||||
}
|
}
|
||||||
|
auth_load_info_delete(daemon->auth_load_info);
|
||||||
ub_randfree(daemon->rand);
|
ub_randfree(daemon->rand);
|
||||||
alloc_clear(&daemon->superalloc);
|
alloc_clear(&daemon->superalloc);
|
||||||
acl_list_delete(daemon->acl);
|
acl_list_delete(daemon->acl);
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ struct doq_table;
|
|||||||
struct cookie_secrets;
|
struct cookie_secrets;
|
||||||
struct fast_reload_thread;
|
struct fast_reload_thread;
|
||||||
struct fast_reload_printq;
|
struct fast_reload_printq;
|
||||||
|
struct auth_load_general_info;
|
||||||
struct shared_ports;
|
struct shared_ports;
|
||||||
|
|
||||||
#include "dnstap/dnstap_config.h"
|
#include "dnstap/dnstap_config.h"
|
||||||
@@ -191,6 +192,8 @@ struct daemon {
|
|||||||
int fast_reload_tcl_has_changes;
|
int fast_reload_tcl_has_changes;
|
||||||
/** config file name */
|
/** config file name */
|
||||||
char* cfgfile;
|
char* cfgfile;
|
||||||
|
/** Auth load threads, the number of active threads. */
|
||||||
|
struct auth_load_general_info* auth_load_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+11
-369
@@ -73,6 +73,7 @@
|
|||||||
#include "services/mesh.h"
|
#include "services/mesh.h"
|
||||||
#include "services/localzone.h"
|
#include "services/localzone.h"
|
||||||
#include "services/authzone.h"
|
#include "services/authzone.h"
|
||||||
|
#include "services/authload.h"
|
||||||
#include "services/rpz.h"
|
#include "services/rpz.h"
|
||||||
#include "util/storage/slabhash.h"
|
#include "util/storage/slabhash.h"
|
||||||
#include "util/fptr_wlist.h"
|
#include "util/fptr_wlist.h"
|
||||||
@@ -115,9 +116,6 @@
|
|||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_POLL_H
|
|
||||||
#include <poll.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* just for portability */
|
/* just for portability */
|
||||||
#ifdef SQ
|
#ifdef SQ
|
||||||
@@ -4466,92 +4464,6 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine polls a socket for readiness.
|
|
||||||
* @param fd: file descriptor, -1 uses no fd for a timer only.
|
|
||||||
* @param timeout: time in msec to wait. 0 means nonblocking test,
|
|
||||||
* -1 waits blocking for events.
|
|
||||||
* @param pollin: check for input event.
|
|
||||||
* @param pollout: check for output event.
|
|
||||||
* @param event: output variable, set to true if the event happens.
|
|
||||||
* It is false if there was an error or timeout.
|
|
||||||
* @return false is system call failure, also logged.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
|
|
||||||
{
|
|
||||||
int loopcount = 0;
|
|
||||||
/* Loop if the system call returns an errno to do so, like EINTR. */
|
|
||||||
log_assert(pollin || pollout);
|
|
||||||
while(1) {
|
|
||||||
struct pollfd p, *fds;
|
|
||||||
int nfds, ret;
|
|
||||||
if(++loopcount > IPC_LOOP_MAX) {
|
|
||||||
log_err("sock_poll_timeout: loop");
|
|
||||||
if(event)
|
|
||||||
*event = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(fd == -1) {
|
|
||||||
fds = NULL;
|
|
||||||
nfds = 0;
|
|
||||||
} else {
|
|
||||||
fds = &p;
|
|
||||||
nfds = 1;
|
|
||||||
memset(&p, 0, sizeof(p));
|
|
||||||
p.fd = fd;
|
|
||||||
#ifndef USE_WINSOCK
|
|
||||||
p.events = POLLERR
|
|
||||||
| POLLHUP
|
|
||||||
;
|
|
||||||
#endif
|
|
||||||
if(pollin)
|
|
||||||
p.events |= POLLIN;
|
|
||||||
if(pollout)
|
|
||||||
p.events |= POLLOUT;
|
|
||||||
}
|
|
||||||
#ifndef USE_WINSOCK
|
|
||||||
ret = poll(fds, nfds, timeout);
|
|
||||||
#else
|
|
||||||
if(fds == NULL) {
|
|
||||||
Sleep(timeout);
|
|
||||||
ret = 0;
|
|
||||||
} else {
|
|
||||||
ret = WSAPoll(fds, nfds, timeout);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(ret == -1) {
|
|
||||||
#ifndef USE_WINSOCK
|
|
||||||
if(
|
|
||||||
errno == EINTR || errno == EAGAIN
|
|
||||||
# ifdef EWOULDBLOCK
|
|
||||||
|| errno == EWOULDBLOCK
|
|
||||||
# endif
|
|
||||||
) continue; /* Try again. */
|
|
||||||
#endif
|
|
||||||
/* For WSAPoll we only get errors here:
|
|
||||||
* o WSAENETDOWN
|
|
||||||
* o WSAEFAULT
|
|
||||||
* o WSAEINVAL
|
|
||||||
* o WSAENOBUFS
|
|
||||||
*/
|
|
||||||
log_err("poll: %s", sock_strerror(errno));
|
|
||||||
if(event)
|
|
||||||
*event = 0;
|
|
||||||
return 0;
|
|
||||||
} else if(ret == 0) {
|
|
||||||
/* Timeout */
|
|
||||||
if(event)
|
|
||||||
*event = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(event)
|
|
||||||
*event = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** fast reload convert fast reload notification status to string */
|
/** fast reload convert fast reload notification status to string */
|
||||||
static const char*
|
static const char*
|
||||||
fr_notification_to_string(enum fast_reload_notification status)
|
fr_notification_to_string(enum fast_reload_notification status)
|
||||||
@@ -6365,6 +6277,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
|
|||||||
COPY_VAR_ptr(acls);
|
COPY_VAR_ptr(acls);
|
||||||
COPY_VAR_int(donotquery_localhost);
|
COPY_VAR_int(donotquery_localhost);
|
||||||
COPY_VAR_ptr(tcp_connection_limits);
|
COPY_VAR_ptr(tcp_connection_limits);
|
||||||
|
COPY_VAR_int(auth_task_threads);
|
||||||
COPY_VAR_int(harden_short_bufsize);
|
COPY_VAR_int(harden_short_bufsize);
|
||||||
COPY_VAR_int(harden_large_queries);
|
COPY_VAR_int(harden_large_queries);
|
||||||
COPY_VAR_int(harden_glue);
|
COPY_VAR_int(harden_glue);
|
||||||
@@ -7156,286 +7069,6 @@ done_error:
|
|||||||
}
|
}
|
||||||
#endif /* !THREADS_DISABLED */
|
#endif /* !THREADS_DISABLED */
|
||||||
|
|
||||||
/** create a socketpair for bidirectional communication, false on failure */
|
|
||||||
static int
|
|
||||||
create_socketpair(int* pair, struct ub_randstate* rand)
|
|
||||||
{
|
|
||||||
#ifndef USE_WINSOCK
|
|
||||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
|
|
||||||
log_err("socketpair: %s", strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
(void)rand;
|
|
||||||
#else
|
|
||||||
struct sockaddr_in addr, baddr, accaddr, connaddr;
|
|
||||||
socklen_t baddrlen, accaddrlen, connaddrlen;
|
|
||||||
uint8_t localhost[] = {127, 0, 0, 1};
|
|
||||||
uint8_t nonce[16], recvnonce[16];
|
|
||||||
size_t i;
|
|
||||||
int lst, pollin_event, bcount, loopcount;
|
|
||||||
int connect_poll_timeout = 200; /* msec to wait for connection */
|
|
||||||
ssize_t ret;
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
for(i=0; i<sizeof(nonce); i++) {
|
|
||||||
nonce[i] = ub_random_max(rand, 256);
|
|
||||||
}
|
|
||||||
lst = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if(lst == -1) {
|
|
||||||
log_err("create_socketpair: socket: %s", sock_strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = 0;
|
|
||||||
memcpy(&addr.sin_addr, localhost, 4);
|
|
||||||
if(bind(lst, (struct sockaddr*)&addr, (socklen_t)sizeof(addr))
|
|
||||||
== -1) {
|
|
||||||
log_err("create socketpair: bind: %s", sock_strerror(errno));
|
|
||||||
sock_close(lst);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(listen(lst, 12) == -1) {
|
|
||||||
log_err("create socketpair: listen: %s", sock_strerror(errno));
|
|
||||||
sock_close(lst);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pair[1] = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if(pair[1] == -1) {
|
|
||||||
log_err("create socketpair: socket: %s", sock_strerror(errno));
|
|
||||||
sock_close(lst);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
baddrlen = (socklen_t)sizeof(baddr);
|
|
||||||
if(getsockname(lst, (struct sockaddr*)&baddr, &baddrlen) == -1) {
|
|
||||||
log_err("create socketpair: getsockname: %s",
|
|
||||||
sock_strerror(errno));
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(baddrlen > (socklen_t)sizeof(baddr)) {
|
|
||||||
log_err("create socketpair: getsockname returned addr too big");
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* the socket is blocking */
|
|
||||||
if(connect(pair[1], (struct sockaddr*)&baddr, baddrlen) == -1) {
|
|
||||||
log_err("create socketpair: connect: %s",
|
|
||||||
sock_strerror(errno));
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!sock_poll_timeout(lst, connect_poll_timeout, 1, 0, &pollin_event)) {
|
|
||||||
log_err("create socketpair: poll for accept failed: %s",
|
|
||||||
sock_strerror(errno));
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!pollin_event) {
|
|
||||||
log_err("create socketpair: poll timeout for accept");
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
accaddrlen = (socklen_t)sizeof(accaddr);
|
|
||||||
pair[0] = accept(lst, (struct sockaddr*)&accaddr, &accaddrlen);
|
|
||||||
if(pair[0] == -1) {
|
|
||||||
log_err("create socketpair: accept: %s", sock_strerror(errno));
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(accaddrlen > (socklen_t)sizeof(accaddr)) {
|
|
||||||
log_err("create socketpair: accept returned addr too big");
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(accaddr.sin_family != AF_INET ||
|
|
||||||
memcmp(localhost, &accaddr.sin_addr, 4) != 0) {
|
|
||||||
log_err("create socketpair: accept from wrong address");
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
connaddrlen = (socklen_t)sizeof(connaddr);
|
|
||||||
if(getsockname(pair[1], (struct sockaddr*)&connaddr, &connaddrlen)
|
|
||||||
== -1) {
|
|
||||||
log_err("create socketpair: getsockname connectedaddr: %s",
|
|
||||||
sock_strerror(errno));
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(connaddrlen > (socklen_t)sizeof(connaddr)) {
|
|
||||||
log_err("create socketpair: getsockname connectedaddr returned addr too big");
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(connaddr.sin_family != AF_INET ||
|
|
||||||
memcmp(localhost, &connaddr.sin_addr, 4) != 0) {
|
|
||||||
log_err("create socketpair: getsockname connectedaddr returned wrong address");
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(accaddr.sin_port != connaddr.sin_port) {
|
|
||||||
log_err("create socketpair: accept from wrong port");
|
|
||||||
sock_close(lst);
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sock_close(lst);
|
|
||||||
|
|
||||||
loopcount = 0;
|
|
||||||
bcount = 0;
|
|
||||||
while(1) {
|
|
||||||
if(++loopcount > IPC_LOOP_MAX) {
|
|
||||||
log_err("create socketpair: send failed due to loop");
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ret = send(pair[1], (void*)(nonce+bcount),
|
|
||||||
sizeof(nonce)-bcount, 0);
|
|
||||||
if(ret == -1) {
|
|
||||||
if(
|
|
||||||
#ifndef USE_WINSOCK
|
|
||||||
errno == EINTR || errno == EAGAIN
|
|
||||||
# ifdef EWOULDBLOCK
|
|
||||||
|| errno == EWOULDBLOCK
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
WSAGetLastError() == WSAEINTR ||
|
|
||||||
WSAGetLastError() == WSAEINPROGRESS ||
|
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
continue; /* Try again. */
|
|
||||||
log_err("create socketpair: send: %s", sock_strerror(errno));
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
} else if(ret+(ssize_t)bcount != sizeof(nonce)) {
|
|
||||||
bcount += ret;
|
|
||||||
if((size_t)bcount < sizeof(nonce))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!sock_poll_timeout(pair[0], connect_poll_timeout, 1, 0, &pollin_event)) {
|
|
||||||
log_err("create socketpair: poll failed: %s",
|
|
||||||
sock_strerror(errno));
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!pollin_event) {
|
|
||||||
log_err("create socketpair: poll timeout for recv");
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
loopcount = 0;
|
|
||||||
bcount = 0;
|
|
||||||
while(1) {
|
|
||||||
if(++loopcount > IPC_LOOP_MAX) {
|
|
||||||
log_err("create socketpair: recv failed due to loop");
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ret = recv(pair[0], (void*)(recvnonce+bcount),
|
|
||||||
sizeof(nonce)-bcount, 0);
|
|
||||||
if(ret == -1) {
|
|
||||||
if(
|
|
||||||
#ifndef USE_WINSOCK
|
|
||||||
errno == EINTR || errno == EAGAIN
|
|
||||||
# ifdef EWOULDBLOCK
|
|
||||||
|| errno == EWOULDBLOCK
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
WSAGetLastError() == WSAEINTR ||
|
|
||||||
WSAGetLastError() == WSAEINPROGRESS ||
|
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
continue; /* Try again. */
|
|
||||||
log_err("create socketpair: recv: %s", sock_strerror(errno));
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
} else if(ret == 0) {
|
|
||||||
log_err("create socketpair: stream closed");
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
} else if(ret+(ssize_t)bcount != sizeof(nonce)) {
|
|
||||||
bcount += ret;
|
|
||||||
if((size_t)bcount < sizeof(nonce))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(memcmp(nonce, recvnonce, sizeof(nonce)) != 0) {
|
|
||||||
log_err("create socketpair: recv wrong nonce");
|
|
||||||
sock_close(pair[0]);
|
|
||||||
sock_close(pair[1]);
|
|
||||||
pair[0] = -1;
|
|
||||||
pair[1] = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** fast reload thread. setup the thread info */
|
/** fast reload thread. setup the thread info */
|
||||||
static int
|
static int
|
||||||
fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause,
|
fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause,
|
||||||
@@ -7812,6 +7445,13 @@ auth_zone_zonemd_stop_lookup(struct auth_zone* z, struct mesh_area* mesh)
|
|||||||
{
|
{
|
||||||
struct query_info qinfo;
|
struct query_info qinfo;
|
||||||
uint16_t qflags = BIT_RD;
|
uint16_t qflags = BIT_RD;
|
||||||
|
if(z->zonemd_transfer_active) {
|
||||||
|
auth_load_info_release_transfer_in_progress(
|
||||||
|
z->zonemd_callback_env);
|
||||||
|
auth_load_schedule_waiting_pickup(z->zonemd_callback_env);
|
||||||
|
z->zonemd_transfer_active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
qinfo.qname_len = z->namelen;
|
qinfo.qname_len = z->namelen;
|
||||||
qinfo.qname = z->name;
|
qinfo.qname = z->name;
|
||||||
qinfo.qclass = z->dclass;
|
qinfo.qclass = z->dclass;
|
||||||
@@ -7893,6 +7533,8 @@ fr_worker_auth_del(struct worker* worker, struct fast_reload_auth_change* item,
|
|||||||
released = 1;
|
released = 1;
|
||||||
xfr_disown_tasks(xfr, worker);
|
xfr_disown_tasks(xfr, worker);
|
||||||
}
|
}
|
||||||
|
auth_load_del_zone_tasks(worker, xfr->name, xfr->namelen,
|
||||||
|
xfr->dclass);
|
||||||
lock_basic_unlock(&xfr->lock);
|
lock_basic_unlock(&xfr->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
#include "services/cache/infra.h"
|
#include "services/cache/infra.h"
|
||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
#include "services/authzone.h"
|
#include "services/authzone.h"
|
||||||
|
#include "services/authload.h"
|
||||||
#include "services/mesh.h"
|
#include "services/mesh.h"
|
||||||
#include "services/localzone.h"
|
#include "services/localzone.h"
|
||||||
#include "services/rpz.h"
|
#include "services/rpz.h"
|
||||||
@@ -2262,6 +2263,7 @@ worker_create(struct daemon* daemon, int id)
|
|||||||
free(worker);
|
free(worker);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
rbtree_init(&worker->auth_load_tree, auth_load_tree_cmp);
|
||||||
explicit_bzero(&seed, sizeof(seed));
|
explicit_bzero(&seed, sizeof(seed));
|
||||||
return worker;
|
return worker;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "util/netevent.h"
|
#include "util/netevent.h"
|
||||||
#include "util/locks.h"
|
#include "util/locks.h"
|
||||||
#include "util/alloc.h"
|
#include "util/alloc.h"
|
||||||
|
#include "util/rbtree.h"
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
#include "util/data/msgparse.h"
|
#include "util/data/msgparse.h"
|
||||||
#include "daemon/stats.h"
|
#include "daemon/stats.h"
|
||||||
@@ -135,6 +136,8 @@ struct worker {
|
|||||||
#endif
|
#endif
|
||||||
/** reuse existing cache on reload if other conditions allow it. */
|
/** reuse existing cache on reload if other conditions allow it. */
|
||||||
int reuse_cache;
|
int reuse_cache;
|
||||||
|
/** tree of auth load threads, attached to this worker. */
|
||||||
|
rbtree_type auth_load_tree;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1171,6 +1171,8 @@ server:
|
|||||||
# Timeout in milliseconds for TCP queries to auth servers.
|
# Timeout in milliseconds for TCP queries to auth servers.
|
||||||
# tcp-auth-query-timeout: 3000
|
# tcp-auth-query-timeout: 3000
|
||||||
|
|
||||||
|
# Number of threads to use to load auth-zones (and RPZ). 0 disables.
|
||||||
|
# auth-task-threads: 0
|
||||||
|
|
||||||
# Python config section. To enable:
|
# Python config section. To enable:
|
||||||
# o use --with-pythonmodule to configure before compiling.
|
# o use --with-pythonmodule to configure before compiling.
|
||||||
|
|||||||
@@ -3520,6 +3520,24 @@ These options are part of the ``server:`` section.
|
|||||||
|
|
||||||
Default: no
|
Default: no
|
||||||
|
|
||||||
|
|
||||||
|
@@UAHL@unbound.conf@auth-task-threads@@: *<number of threads>*
|
||||||
|
If nonzero, the number of threads to start to process zone transfers
|
||||||
|
for authority zones, and also RPZ zones.
|
||||||
|
The zone transfer is processed in a thread, that does not interrupt
|
||||||
|
the resolver.
|
||||||
|
For RPZ zones that means the old RPZ zone continues to be used, while
|
||||||
|
the task is processed.
|
||||||
|
The thread allocates the new zone data, and this keeps another copy of
|
||||||
|
the zone data in memory during processing.
|
||||||
|
The result is swapped into the resolver when the thread is done.
|
||||||
|
|
||||||
|
The value 0 disables the threading, one of the worker threads performs
|
||||||
|
the processing. Without threading enabled, use the value 0.
|
||||||
|
|
||||||
|
Default: 0
|
||||||
|
|
||||||
|
|
||||||
.. _unbound.conf.remote:
|
.. _unbound.conf.remote:
|
||||||
|
|
||||||
Remote Control Options
|
Remote Control Options
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* libunbound/authload.h - prototypes for auth load methods.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026, 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 declares the methods that must be implemented to use the
|
||||||
|
* auth load service.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBUNBOUND_AUTHLOAD_H
|
||||||
|
#define LIBUNBOUND_AUTHLOAD_H
|
||||||
|
|
||||||
|
/** The worker routine that services the auth load connection. */
|
||||||
|
void worker_auth_load_service_cb(int fd, short bits, void* arg);
|
||||||
|
|
||||||
|
#endif /* LIBUNBOUND_AUTHLOAD_H */
|
||||||
+1542
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,301 @@
|
|||||||
|
/*
|
||||||
|
* services/authload.h - authoritative zone load thread
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026, 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 the auth load thread. This loads authority zone
|
||||||
|
* and RPZ zone information in a thread, in a separate memory structure.
|
||||||
|
* When it is done, the information is swapped over to the running server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERVICES_AUTHLOAD_H
|
||||||
|
#define SERVICES_AUTHLOAD_H
|
||||||
|
#include "util/locks.h"
|
||||||
|
#include "util/rbtree.h"
|
||||||
|
struct worker;
|
||||||
|
struct daemon;
|
||||||
|
struct auth_xfer;
|
||||||
|
struct module_env;
|
||||||
|
struct auth_load_task;
|
||||||
|
struct comm_timer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General information for auth load threads. The number of active threads.
|
||||||
|
*/
|
||||||
|
struct auth_load_general_info {
|
||||||
|
/** lock on this structure. It is after the auth_zones lock, and
|
||||||
|
* after the auth_xfer locks. */
|
||||||
|
lock_basic_type lock;
|
||||||
|
/** The number of active auth load threads. */
|
||||||
|
int num_auth_load_threads;
|
||||||
|
/** The number of active downloads, zone transfers in progress.
|
||||||
|
* These are going to need an auth load thread when done. The counter
|
||||||
|
* is decremented when the thread and transfer have completed. */
|
||||||
|
int num_auth_transfers;
|
||||||
|
/** The auth zone xfer transfer wait list */
|
||||||
|
struct auth_xfer* wait_transfer_list;
|
||||||
|
/** The last item of the wait_transfer list. */
|
||||||
|
struct auth_xfer* wait_transfer_last;
|
||||||
|
/** To resume from a waiting item, the callback, at zero timeout is
|
||||||
|
* used. That breaks out of callbacks and handles the items there.
|
||||||
|
* If the timer is set, this is true. */
|
||||||
|
int resume_timer_enabled;
|
||||||
|
/** The resume timer for the wait_transfer list. */
|
||||||
|
struct comm_timer* resume_timer;
|
||||||
|
/** The worker env for the resume timer. It is set in the event base
|
||||||
|
* of that worker. */
|
||||||
|
struct module_env* resume_env;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of notifications that the auth load thread sends around.
|
||||||
|
*/
|
||||||
|
enum auth_load_notification_type {
|
||||||
|
/** This is sent to make the auth load thread perform exit */
|
||||||
|
auth_load_notification_exit
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The auth load thread. The thread runs to load authority zone information
|
||||||
|
* and RPZ information into memory. It loads into a copy. Then that is swapped
|
||||||
|
* over to the running server. This keeps the server responsive while the
|
||||||
|
* information is loaded.
|
||||||
|
*/
|
||||||
|
struct auth_load_thread {
|
||||||
|
/** the thread number for the thread,
|
||||||
|
* must be first to cast thread arg to int* in checklock code. */
|
||||||
|
int threadnum;
|
||||||
|
/** thread id, of the io thread */
|
||||||
|
ub_thread_type tid;
|
||||||
|
#ifdef HAVE_GETTID
|
||||||
|
/** thread tid, the LWP id */
|
||||||
|
pid_t thread_tid;
|
||||||
|
/** if logging should include the LWP id */
|
||||||
|
int thread_tid_log;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** communication socket pair, that sends commands */
|
||||||
|
int commpair[2];
|
||||||
|
/** if the thread has to quit */
|
||||||
|
int need_to_quit;
|
||||||
|
/** the event that listens on the worker to commpair,
|
||||||
|
* it receives content from the auth load thread. */
|
||||||
|
void* service_event;
|
||||||
|
/** if the event that listens on the worker has
|
||||||
|
* been added to the comm base. */
|
||||||
|
int service_event_is_added;
|
||||||
|
|
||||||
|
/** the worker that the auth load is connected to */
|
||||||
|
struct worker* worker;
|
||||||
|
/** if the thread is inserted in the tree at the worker. */
|
||||||
|
int tree_inserted;
|
||||||
|
/** the rbtree node for the worker tree of auth load threads. */
|
||||||
|
rbnode_type node;
|
||||||
|
|
||||||
|
/** The task that the thread is working on */
|
||||||
|
struct auth_load_task* task;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of tasks that the auth load can perform.
|
||||||
|
*/
|
||||||
|
enum auth_load_task_type {
|
||||||
|
AUTH_LOAD_TASK_TRANSFER,
|
||||||
|
AUTH_LOAD_TASK_ZONEFILE_READ,
|
||||||
|
AUTH_LOAD_TASK_ZONEFILE_WRITE,
|
||||||
|
AUTH_LOAD_TASK_HTTPCHUNKS
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The task for the auth load. The task can be to load a zone transfer, AXFR,
|
||||||
|
* IXFR, from zonefile, and from a http read, from chunks.
|
||||||
|
*/
|
||||||
|
struct auth_load_task {
|
||||||
|
/** The type of the task */
|
||||||
|
enum auth_load_task_type task_type;
|
||||||
|
/** The task is connected with this worker */
|
||||||
|
struct worker* worker;
|
||||||
|
|
||||||
|
/** The zone name */
|
||||||
|
uint8_t* name;
|
||||||
|
/** The zone namelen */
|
||||||
|
size_t namelen;
|
||||||
|
/** The zone class */
|
||||||
|
uint16_t dclass;
|
||||||
|
|
||||||
|
/** name of the host that the transfer comes from. */
|
||||||
|
char* host;
|
||||||
|
/** file part of the url that the transfer comes from, or NULL. */
|
||||||
|
char* file;
|
||||||
|
/** Set if the host is http transfer, if false it is AXFR or IXFR. */
|
||||||
|
int on_http;
|
||||||
|
/** Set if the transfer is doing IXFR */
|
||||||
|
int on_ixfr;
|
||||||
|
/** Set if the transfer is an IXFR but we detected an AXFR contents */
|
||||||
|
int on_ixfr_is_axfr;
|
||||||
|
/** The zone is an rpz zone. */
|
||||||
|
int is_rpz;
|
||||||
|
|
||||||
|
/** Set if the ixfr failed. (So that there can be backoff to AXFR). */
|
||||||
|
int ixfr_fail;
|
||||||
|
|
||||||
|
/** current serial (from SOA), if we have no zone, 0
|
||||||
|
* This is for checking the IXFR result. */
|
||||||
|
uint32_t serial;
|
||||||
|
|
||||||
|
/** the data chunks, or NULL, to process. */
|
||||||
|
struct auth_chunk* chunks_first;
|
||||||
|
/** last data chunk */
|
||||||
|
struct auth_chunk* chunks_last;
|
||||||
|
/** size of data in data chunks. */
|
||||||
|
size_t chunks_total;
|
||||||
|
|
||||||
|
/** time taken for the task */
|
||||||
|
struct timeval time_taken;
|
||||||
|
/** time taken for the reload part of the task */
|
||||||
|
struct timeval time_reload;
|
||||||
|
/** memory used for the task */
|
||||||
|
size_t mem_used;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new task to be performed by the auth load thread.
|
||||||
|
* It starts a thread.
|
||||||
|
* @param xfr: zone transfer to start for.
|
||||||
|
* @param worker: worker that is connected to the task.
|
||||||
|
* @return false on failure.
|
||||||
|
*/
|
||||||
|
int auth_load_add_task_xfr(struct auth_xfer* xfr, struct worker* worker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new task to be performed by the auth load thread.
|
||||||
|
* It starts a thread. This writes to zonefile.
|
||||||
|
* @param name: name of zone, wireformat.
|
||||||
|
* @param namelen: length of name.
|
||||||
|
* @param dclass: class of the zone.
|
||||||
|
* @param env: the module env.
|
||||||
|
* @param chunk_list: for writes after http, the chunk list with data.
|
||||||
|
* @return false on failure to create the thread.
|
||||||
|
*/
|
||||||
|
int auth_load_add_task_write(uint8_t* name, size_t namelen, uint16_t dclass,
|
||||||
|
struct module_env* env, struct auth_chunk* chunk_list);
|
||||||
|
|
||||||
|
/** See if there is a quit signal, true if so. */
|
||||||
|
int auth_load_thread_poll_for_quit(struct auth_load_thread* thr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create auth load info structure.
|
||||||
|
* @return NULL on failure.
|
||||||
|
*/
|
||||||
|
struct auth_load_general_info* auth_load_info_create(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete auth load info structure.
|
||||||
|
* @param auth_load_info: to delete.
|
||||||
|
*/
|
||||||
|
void auth_load_info_delete(struct auth_load_general_info* auth_load_info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab a new thread from the auth load count.
|
||||||
|
* @param env: with auth_load_info with the active thread count.
|
||||||
|
* and config file, with configured maximum.
|
||||||
|
* @return false on failure, like too many active, true if successful.
|
||||||
|
*/
|
||||||
|
int auth_load_info_grab_thread(struct module_env* env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release thread from auth load count. It is done.
|
||||||
|
* @param env: with auth_load_info with the active thread count.
|
||||||
|
*/
|
||||||
|
void auth_load_info_release_thread(struct module_env* env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab a new transfer in progress, this is limited by the auth load count.
|
||||||
|
* @param env: with auth_load_info with the active transfer number.
|
||||||
|
* and config file, with configured maximum.
|
||||||
|
* @return false on failure, like too many active, true if successful.
|
||||||
|
*/
|
||||||
|
int auth_load_info_grab_transfer_in_progress(struct module_env* env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release transfer from active count. It is done.
|
||||||
|
* @param env: with auth_load_info with the active transfer count.
|
||||||
|
*/
|
||||||
|
void auth_load_info_release_transfer_in_progress(struct module_env* env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make transfer active in the in progress transfer count.
|
||||||
|
* @param xfr: the xfr is in progress
|
||||||
|
* @return false if not possible.
|
||||||
|
*/
|
||||||
|
int xfr_transfer_grab_active(struct auth_xfer* xfr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release active transfer from in progress transfer count.
|
||||||
|
* @param xfr: the xfr is no longer in progress.
|
||||||
|
*/
|
||||||
|
void xfr_transfer_release_active(struct auth_xfer* xfr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add transfer to wait_transfer list. It can not become active right now.
|
||||||
|
* @param xfr: the xfr is put on the wait_transfer list.
|
||||||
|
*/
|
||||||
|
void xfr_transfer_wait_active(struct auth_xfer* xfr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove xfr from wait_transfer list
|
||||||
|
* @param xfr: the xfr is removed from the wait_transfer list.
|
||||||
|
*/
|
||||||
|
void xfr_transfer_remove_wait_transfer_list(struct auth_xfer* xfr);
|
||||||
|
|
||||||
|
/** The timer callback for the wait_transfer resume timer. */
|
||||||
|
void auth_load_resume_timer_cb(void* arg);
|
||||||
|
|
||||||
|
/** Schedule pick up of waiting transfers. */
|
||||||
|
void auth_load_schedule_waiting_pickup(struct module_env* env);
|
||||||
|
|
||||||
|
/** Compare auth load tree entries, in the worker auth load tree. */
|
||||||
|
int auth_load_tree_cmp(const void* a, const void* b);
|
||||||
|
|
||||||
|
/** Delete tasks for the zone. The write and xfr tasks for that name, class
|
||||||
|
* are sent a quit signal, and the thread is joined, as it exits. */
|
||||||
|
void auth_load_del_zone_tasks(struct worker* worker, uint8_t* name,
|
||||||
|
size_t namelen, uint16_t dclass);
|
||||||
|
|
||||||
|
/** Stop all the auth load threads. */
|
||||||
|
void auth_load_stop_threads(struct daemon* daemon);
|
||||||
|
|
||||||
|
#endif /* SERVICES_AUTHLOAD_H */
|
||||||
+567
-143
File diff suppressed because it is too large
Load Diff
+66
-1
@@ -65,6 +65,7 @@ struct auth_probe;
|
|||||||
struct auth_transfer;
|
struct auth_transfer;
|
||||||
struct auth_master;
|
struct auth_master;
|
||||||
struct auth_chunk;
|
struct auth_chunk;
|
||||||
|
struct auth_load_thread;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authoritative zones, shared.
|
* Authoritative zones, shared.
|
||||||
@@ -150,6 +151,8 @@ struct auth_zone {
|
|||||||
int zonemd_callback_perform_write;
|
int zonemd_callback_perform_write;
|
||||||
/** chunklist to write for chunked transfer. */
|
/** chunklist to write for chunked transfer. */
|
||||||
struct auth_chunk* perform_write_chunk_list;
|
struct auth_chunk* perform_write_chunk_list;
|
||||||
|
/** The zonemd transfer is an active transfer (for auth load info) */
|
||||||
|
int zonemd_transfer_active;
|
||||||
/** zone has been deleted */
|
/** zone has been deleted */
|
||||||
int zone_deleted;
|
int zone_deleted;
|
||||||
/** deletelist pointer, unused normally except during delete */
|
/** deletelist pointer, unused normally except during delete */
|
||||||
@@ -404,6 +407,15 @@ struct auth_transfer {
|
|||||||
size_t chunks_total;
|
size_t chunks_total;
|
||||||
/** start time of the transfer */
|
/** start time of the transfer */
|
||||||
struct timeval start_time;
|
struct timeval start_time;
|
||||||
|
/** if the transfer is active and in the in progress count. */
|
||||||
|
int active_transfer;
|
||||||
|
/** if the transfer is on the wait_transfer list (it waits to
|
||||||
|
* become active). */
|
||||||
|
int on_wait_transfer_list;
|
||||||
|
/** If on the wait_transfer list, the previous list item. */
|
||||||
|
struct auth_xfer* wait_transfer_prev;
|
||||||
|
/** If on the wait_transfer list, the next list item. */
|
||||||
|
struct auth_xfer* wait_transfer_next;
|
||||||
|
|
||||||
/** list of upstream masters for this zone, from config */
|
/** list of upstream masters for this zone, from config */
|
||||||
struct auth_master* masters;
|
struct auth_master* masters;
|
||||||
@@ -545,7 +557,15 @@ void auth_zones_delete(struct auth_zones* az);
|
|||||||
/**
|
/**
|
||||||
* Write auth zone data to file, in zonefile format.
|
* Write auth zone data to file, in zonefile format.
|
||||||
*/
|
*/
|
||||||
int auth_zone_write_file(struct auth_zone* z, const char* fname);
|
int auth_zone_write_file(struct auth_zone* z, const char* fname,
|
||||||
|
struct auth_load_thread* thr);
|
||||||
|
|
||||||
|
/** write to zonefile after zone has updated, reacquires z readlock.
|
||||||
|
* The chunk list is freed on return.
|
||||||
|
* If the zone is gone, chunk_list is freed (if non NULL). */
|
||||||
|
void zone_write_after_update_reacq(uint8_t* name, size_t namelen,
|
||||||
|
uint16_t dclass, struct module_env* env,
|
||||||
|
struct auth_chunk* chunk_list, struct auth_load_thread* thr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use auth zones to lookup the answer to a query.
|
* Use auth zones to lookup the answer to a query.
|
||||||
@@ -861,4 +881,49 @@ int chunkline_count_parens(struct sldns_buffer* buf, size_t start);
|
|||||||
/** Clear data in auth zone */
|
/** Clear data in auth zone */
|
||||||
void auth_zone_clear_data(struct auth_zone* z);
|
void auth_zone_clear_data(struct auth_zone* z);
|
||||||
|
|
||||||
|
/** Get memory usage of auth zone */
|
||||||
|
size_t auth_zone_get_mem(struct auth_zone* z);
|
||||||
|
|
||||||
|
/** create domain with the given name */
|
||||||
|
struct auth_data* az_domain_create(struct auth_zone* z, uint8_t* nm,
|
||||||
|
size_t nmlen);
|
||||||
|
|
||||||
|
/** helper traverse to delete zones */
|
||||||
|
void auth_data_del(rbnode_type* n, void* arg);
|
||||||
|
|
||||||
|
/** Pick up xfr task from wait_transfer resumption. xfr is locked on entry,
|
||||||
|
* unlocked at return. */
|
||||||
|
void xfr_pick_up_transfer(struct auth_xfer* xfr, struct module_env* env);
|
||||||
|
|
||||||
|
/** Handle the end of an auth load task. */
|
||||||
|
void xfr_process_load_end_transfer(struct auth_xfer* xfr,
|
||||||
|
struct module_env* env, uint8_t status, int ixfr_fail,
|
||||||
|
struct timeval* time_taken, struct timeval* time_reload,
|
||||||
|
size_t mem_used, size_t chunks_total, struct auth_chunk* chunk_list);
|
||||||
|
|
||||||
|
/** Handle the end of an auth load task to write. */
|
||||||
|
void auth_zone_process_load_end_write(struct module_env* env);
|
||||||
|
|
||||||
|
/** Log preview of http transfer */
|
||||||
|
void xfr_http_preview(const char* file, struct auth_chunk* chunk_list);
|
||||||
|
|
||||||
|
/** Check syntax of first part of the http download */
|
||||||
|
int xfr_http_syntax_check(uint8_t* name, size_t namelen, uint16_t dclass,
|
||||||
|
const char* host, const char* file, struct auth_chunk* chunk_list,
|
||||||
|
struct sldns_buffer* scratch_buffer);
|
||||||
|
|
||||||
|
/** Apply http transfer to auth_zone */
|
||||||
|
int xfr_apply_http(uint8_t* name, size_t namelen, const char* host,
|
||||||
|
const char* file, struct auth_chunk* chunk_list, struct auth_zone* z,
|
||||||
|
struct sldns_buffer* scratch_buffer, struct auth_load_thread* thr);
|
||||||
|
|
||||||
|
/** Apply IXFR transfer to auth_zone */
|
||||||
|
int xfr_apply_ixfr(struct auth_chunk* chunk_list, uint32_t xfr_serial,
|
||||||
|
struct auth_zone* z, struct sldns_buffer* scratch_buffer,
|
||||||
|
struct auth_load_thread* thr);
|
||||||
|
|
||||||
|
/** Apply AXFR transfer to auth_zone */
|
||||||
|
int xfr_apply_axfr(struct auth_chunk* chunk_list, struct auth_zone* z,
|
||||||
|
struct sldns_buffer* scratch_buffer, struct auth_load_thread* thr);
|
||||||
|
|
||||||
#endif /* SERVICES_AUTHZONE_H */
|
#endif /* SERVICES_AUTHZONE_H */
|
||||||
|
|||||||
+33
-8
@@ -588,16 +588,11 @@ rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct rpz*
|
struct rpz*
|
||||||
rpz_create(struct config_auth* p)
|
rpz_create_empty(void)
|
||||||
{
|
{
|
||||||
struct rpz* r = calloc(1, sizeof(*r));
|
struct rpz* r = calloc(1, sizeof(*r));
|
||||||
if(!r)
|
if(!r)
|
||||||
goto err;
|
return NULL;
|
||||||
|
|
||||||
r->region = regional_create_custom(sizeof(struct regional));
|
|
||||||
if(!r->region) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(r->local_zones = local_zones_create())){
|
if(!(r->local_zones = local_zones_create())){
|
||||||
goto err;
|
goto err;
|
||||||
@@ -621,6 +616,35 @@ rpz_create(struct config_auth* p)
|
|||||||
if(r->ns_set == NULL) {
|
if(r->ns_set == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
return r;
|
||||||
|
err:
|
||||||
|
if(r) {
|
||||||
|
if(r->local_zones)
|
||||||
|
local_zones_delete(r->local_zones);
|
||||||
|
if(r->nsdname_zones)
|
||||||
|
local_zones_delete(r->nsdname_zones);
|
||||||
|
if(r->respip_set)
|
||||||
|
respip_set_delete(r->respip_set);
|
||||||
|
if(r->client_set != NULL)
|
||||||
|
rpz_clientip_synthesized_set_delete(r->client_set);
|
||||||
|
if(r->ns_set != NULL)
|
||||||
|
rpz_clientip_synthesized_set_delete(r->ns_set);
|
||||||
|
free(r);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rpz*
|
||||||
|
rpz_create(struct config_auth* p)
|
||||||
|
{
|
||||||
|
struct rpz* r = rpz_create_empty();
|
||||||
|
if(!r)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
r->region = regional_create_custom(sizeof(struct regional));
|
||||||
|
if(!r->region) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if(!rpz_apply_cfg_elements(r, p))
|
if(!rpz_apply_cfg_elements(r, p))
|
||||||
goto err;
|
goto err;
|
||||||
@@ -2870,7 +2894,8 @@ size_t rpz_get_mem(struct rpz* r)
|
|||||||
m += r->taglistlen;
|
m += r->taglistlen;
|
||||||
if(r->log_name)
|
if(r->log_name)
|
||||||
m += strlen(r->log_name) + 1;
|
m += strlen(r->log_name) + 1;
|
||||||
m += regional_get_mem(r->region);
|
if(r->region)
|
||||||
|
m += regional_get_mem(r->region);
|
||||||
m += local_zones_get_mem(r->local_zones);
|
m += local_zones_get_mem(r->local_zones);
|
||||||
m += local_zones_get_mem(r->nsdname_zones);
|
m += local_zones_get_mem(r->nsdname_zones);
|
||||||
m += respip_set_get_mem(r->respip_set);
|
m += respip_set_get_mem(r->respip_set);
|
||||||
|
|||||||
@@ -219,6 +219,9 @@ void rpz_delete(struct rpz* r);
|
|||||||
*/
|
*/
|
||||||
int rpz_clear(struct rpz* r);
|
int rpz_clear(struct rpz* r);
|
||||||
|
|
||||||
|
/** Create empty RPZ structure, useful as a proxy for entering data. */
|
||||||
|
struct rpz* rpz_create_empty(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create RPZ. RPZ must be added to linked list after creation.
|
* Create RPZ. RPZ must be added to linked list after creation.
|
||||||
* @return: the newly created RPZ
|
* @return: the newly created RPZ
|
||||||
|
|||||||
@@ -264,6 +264,9 @@ setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
|
|||||||
fprintf(cfg, " pidfile: \"\"\n");
|
fprintf(cfg, " pidfile: \"\"\n");
|
||||||
fprintf(cfg, " val-log-level: 2\n");
|
fprintf(cfg, " val-log-level: 2\n");
|
||||||
fprintf(cfg, " log-servfail: yes\n");
|
fprintf(cfg, " log-servfail: yes\n");
|
||||||
|
/* the extra thread needs pipe communication that is not available
|
||||||
|
* from fake_event calls. So auth-task-threads: 0 disables them. */
|
||||||
|
fprintf(cfg, " auth-task-threads: 0\n");
|
||||||
fprintf(cfg, "remote-control: control-enable: no\n");
|
fprintf(cfg, "remote-control: control-enable: no\n");
|
||||||
while(fgets(line, MAX_LINE_LEN-1, in)) {
|
while(fgets(line, MAX_LINE_LEN-1, in)) {
|
||||||
parse = line;
|
parse = line;
|
||||||
|
|||||||
+1
-1
@@ -735,7 +735,7 @@ check_read_exact(const char* name, const char* zone)
|
|||||||
z = authtest_addzone(az, name, fname);
|
z = authtest_addzone(az, name, fname);
|
||||||
unit_assert(z);
|
unit_assert(z);
|
||||||
outf = create_tmp_file(NULL);
|
outf = create_tmp_file(NULL);
|
||||||
if(!auth_zone_write_file(z, outf)) {
|
if(!auth_zone_write_file(z, outf, NULL)) {
|
||||||
fatal_exit("write file failed for %s", fname);
|
fatal_exit("write file failed for %s", fname);
|
||||||
}
|
}
|
||||||
checkfile(fname, outf);
|
checkfile(fname, outf);
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
server:
|
||||||
|
verbosity: 8
|
||||||
|
# num-threads: 1
|
||||||
|
interface: 127.0.0.1
|
||||||
|
port: @PORT@
|
||||||
|
use-syslog: no
|
||||||
|
directory: ""
|
||||||
|
pidfile: "unbound.pid"
|
||||||
|
chroot: ""
|
||||||
|
username: ""
|
||||||
|
do-not-query-localhost: no
|
||||||
|
auth-task-threads: 1
|
||||||
|
auth-zone:
|
||||||
|
name: "example.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
BaseName: auth_load
|
||||||
|
Version: 1.0
|
||||||
|
Description: Perform AXFR for authority zone with auth load thread
|
||||||
|
CreationDate: Thu 2 Jul 09:35:40 CEST 2026
|
||||||
|
Maintainer: dr. W.C.A. Wijngaards
|
||||||
|
Category:
|
||||||
|
Component:
|
||||||
|
CmdDepends:
|
||||||
|
Depends:
|
||||||
|
Help:
|
||||||
|
Pre: auth_load.pre
|
||||||
|
Post: auth_load.post
|
||||||
|
Test: auth_load.test
|
||||||
|
AuxFiles:
|
||||||
|
Passed:
|
||||||
|
Failure:
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
# #-- auth_load.post --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# source the test var file when it's there
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
#
|
||||||
|
# do your teardown here
|
||||||
|
. ../common.sh
|
||||||
|
kill_pid $FWD_PID
|
||||||
|
kill_pid $UNBOUND_PID
|
||||||
|
cat fwd.log
|
||||||
|
cat unbound.log
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
# #-- auth_load.pre--#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
. ../common.sh
|
||||||
|
# if no threads; exit
|
||||||
|
if grep -e "define HAVE_PTHREAD 1" -e "define HAVE_SOLARIS_THREADS 1" -e "define HAVE_WINDOWS_THREADS 1" $PRE/config.h; then
|
||||||
|
echo "have threads"
|
||||||
|
else
|
||||||
|
skip_test "no threads"
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_random_port 2
|
||||||
|
UNBOUND_PORT=$RND_PORT
|
||||||
|
FWD_PORT=$(($RND_PORT + 1))
|
||||||
|
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
|
||||||
|
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
|
||||||
|
|
||||||
|
# start forwarder
|
||||||
|
get_ldns_testns
|
||||||
|
$LDNS_TESTNS -p $FWD_PORT auth_load.testns >fwd.log 2>&1 &
|
||||||
|
FWD_PID=$!
|
||||||
|
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
# make config file
|
||||||
|
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < auth_load.conf > ub.conf
|
||||||
|
# start unbound in the background
|
||||||
|
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
#valgrind --leak-check=full --show-reachable=yes $PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
UNBOUND_PID=$!
|
||||||
|
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
cat .tpkg.var.test
|
||||||
|
wait_ldns_testns_up fwd.log
|
||||||
|
wait_unbound_up unbound.log
|
||||||
|
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
# #-- auth_load.test --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
# do the test
|
||||||
|
echo "> dig www.example.com."
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
echo "> check answer"
|
||||||
|
if grep "1.2.3.4" outfile; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep "auth zone example.com. details" unbound.log; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
example.com. IN SOA
|
||||||
|
SECTION ANSWER
|
||||||
|
example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
example.com. IN AXFR
|
||||||
|
SECTION ANSWER
|
||||||
|
example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
example.com. IN NS ns.example.net.
|
||||||
|
EXTRA_PACKET
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
example.com. IN AXFR
|
||||||
|
SECTION ANSWER
|
||||||
|
www.example.com. IN A 1.2.3.4
|
||||||
|
example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
ENTRY_END
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
example.com. IN NS ns.example.net.
|
||||||
|
www.example.com. IN A 1.2.3.4
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
server:
|
||||||
|
verbosity: 8
|
||||||
|
# num-threads: 1
|
||||||
|
interface: 127.0.0.1
|
||||||
|
port: @PORT@
|
||||||
|
use-syslog: no
|
||||||
|
directory: ""
|
||||||
|
pidfile: "unbound.pid"
|
||||||
|
chroot: ""
|
||||||
|
username: ""
|
||||||
|
do-not-query-localhost: no
|
||||||
|
auth-task-threads: 1
|
||||||
|
auth-zone:
|
||||||
|
name: "example.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
url: "https://127.0.0.1:@TOPORT@/example.com.zone"
|
||||||
|
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
BaseName: auth_load_http
|
||||||
|
Version: 1.0
|
||||||
|
Description: Perform http transfer for authority zone with auth load thread
|
||||||
|
CreationDate: Tue 11 Aug 16:00:00 CEST 2026
|
||||||
|
Maintainer: dr. W.C.A. Wijngaards
|
||||||
|
Category:
|
||||||
|
Component:
|
||||||
|
CmdDepends:
|
||||||
|
Depends:
|
||||||
|
Help:
|
||||||
|
Pre: auth_load_http.pre
|
||||||
|
Post: auth_load_http.post
|
||||||
|
Test: auth_load_http.test
|
||||||
|
AuxFiles:
|
||||||
|
Passed:
|
||||||
|
Failure:
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# #-- auth_load_http.post --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# source the test var file when it's there
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
#
|
||||||
|
# do your teardown here
|
||||||
|
. ../common.sh
|
||||||
|
kill_pid $UNBOUND_PID
|
||||||
|
kill_pid $PETAL_PID
|
||||||
|
cat petal.log
|
||||||
|
cat unbound.log
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
# #-- auth_load_http.pre--#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
. ../common.sh
|
||||||
|
# if no threads; exit
|
||||||
|
if grep -e "define HAVE_PTHREAD 1" -e "define HAVE_SOLARIS_THREADS 1" -e "define HAVE_WINDOWS_THREADS 1" $PRE/config.h; then
|
||||||
|
echo "have threads"
|
||||||
|
else
|
||||||
|
skip_test "no threads"
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_random_port 2
|
||||||
|
UNBOUND_PORT=$RND_PORT
|
||||||
|
PETAL_PORT=$(($RND_PORT + 1))
|
||||||
|
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
|
||||||
|
echo "PETAL_PORT=$PETAL_PORT" >> .tpkg.var.test
|
||||||
|
|
||||||
|
get_make
|
||||||
|
(cd $PRE; $MAKE petal)
|
||||||
|
|
||||||
|
# start https daemon
|
||||||
|
$PRE/petal -v -a "127.0.0.1" -p $PETAL_PORT >petal.log 2>&1 &
|
||||||
|
PETAL_PID=$!
|
||||||
|
echo "PETAL_PID=$PETAL_PID" >> .tpkg.var.test
|
||||||
|
wait_petal_up petal.log
|
||||||
|
|
||||||
|
# make config file
|
||||||
|
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$PETAL_PORT'/' < auth_load_http.conf > ub.conf
|
||||||
|
# start unbound in the background
|
||||||
|
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
#valgrind --leak-check=full --show-reachable=yes $PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
UNBOUND_PID=$!
|
||||||
|
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
cat .tpkg.var.test
|
||||||
|
wait_unbound_up unbound.log
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# #-- auth_load_http.test --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
# do the test
|
||||||
|
echo "> dig www.example.com."
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
echo "> check answer"
|
||||||
|
if grep "1.2.3.4" outfile; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep "auth zone example.com. details" unbound.log; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIDfQIBAAKBwQC1xQ/Kca6zszZbcCtdOTIH2Uy2gOy/DfabMUU7TmNPm0dVE0NJ
|
||||||
|
RuN+Rm304SonpwghfP2/ULZNnuDgpG03/32yI7k/VzG6iA4hiF7tT/KAAWC/+2l1
|
||||||
|
QCsawCV2bSrFK0VhcZr7ALqXd8vkDaQ867K029ypjOQtAJ85qdO3mERy7TGtdUcu
|
||||||
|
O6hLeVet419YeQ2F8cfNxn63d7bOzNGLPW5xwaCd3UcgD+Ib0k4xfFvbinvPQUeU
|
||||||
|
J/i4YDWexFYSL+ECAwEAAQKBwCLXXQl+9O+5AEhSnd1Go1Jh0pSA7eBJOuXQcebG
|
||||||
|
Rb7ykp+6C4G2NtDziwwPRNdI6wQQQ0sym18RfyVQHydGr78/nbiIbB3HCn5e92Mh
|
||||||
|
mefzW6ow9Kvm2txLzGKA1lvoyRbNm81jnG/eygi3u7Nqd5PNv+4dHj2RkTlmxOeh
|
||||||
|
qnDMVP5md8uZPv6lYNnrnIzvLCR5vnPNdVwn89AqzI85IcDZdy0R9ZX4NBbsDgAU
|
||||||
|
6ig6uXuRXvSGiyJ/OUXSrnogaQJhAOjvkHUhVZQkPOxO90TNH4j0GdKKtbSWxIdz
|
||||||
|
lKfuJeBAEqs0TL+C6vbS81Xw3W1alyDdUBk3rJMOBqW6Ryq5HNL+j5H+Jfsh7fvc
|
||||||
|
Yle+5wHGci0P9zCFZCrY8It7n9XFIwJhAMfEi6oJa2G8waPJ1bQhxka82Tf9pnKM
|
||||||
|
XCn/1BBOFjVIx5F842cpA+zp5a62GENTGYPQTTRBB/2/ZwnW5aIkrlg54AtmbqBZ
|
||||||
|
Oh+2kJdJQD/tfoVmc5soUE2ScTHadK5RKwJhAN4w9kjkXS+MSZjX0kIMsBIBVkhh
|
||||||
|
C+aREjJqa9ir7/Ey7RvmLXdYuCxtGLRXp7/R8+rjcK49Tx6O+IRJZe042mfhbq3C
|
||||||
|
EhS1Tr86f4xXix9EXlDhs9bSxrOgcAN9Dv/opQJhAK7eBcPaav0rVfYh/8emqQHS
|
||||||
|
3fJ9Pu6WnzbEksWTFS2ff9KDGCx9YspIFJ5TF/oXDAaumGZdZrlgirm6O1kr8tGY
|
||||||
|
F97i04PZl1+bWAaWQH+1TUNI43m2WFUPE7coG2tb8QJgcddDg9VlXliZqgcETZfJ
|
||||||
|
kJmYETxrcSn3ao6v116N8yxhEgUgjkmsCTiFgx36iDVnXwK6PIt+sIu8MC7eYNa3
|
||||||
|
berrv/M21K0LRn20IWRxvUobG070weHCAgkko7fTWgr2
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICFzCCAUACCQDO660L5y5LGDANBgkqhkiG9w0BAQUFADAQMQ4wDAYDVQQDEwVw
|
||||||
|
ZXRhbDAeFw0xMDA5MzAxMzQzMDFaFw0zMDA2MTcxMzQzMDFaMBAxDjAMBgNVBAMT
|
||||||
|
BXBldGFsMIHfMA0GCSqGSIb3DQEBAQUAA4HNADCByQKBwQC1xQ/Kca6zszZbcCtd
|
||||||
|
OTIH2Uy2gOy/DfabMUU7TmNPm0dVE0NJRuN+Rm304SonpwghfP2/ULZNnuDgpG03
|
||||||
|
/32yI7k/VzG6iA4hiF7tT/KAAWC/+2l1QCsawCV2bSrFK0VhcZr7ALqXd8vkDaQ8
|
||||||
|
67K029ypjOQtAJ85qdO3mERy7TGtdUcuO6hLeVet419YeQ2F8cfNxn63d7bOzNGL
|
||||||
|
PW5xwaCd3UcgD+Ib0k4xfFvbinvPQUeUJ/i4YDWexFYSL+ECAwEAATANBgkqhkiG
|
||||||
|
9w0BAQUFAAOBwQBBkX9KDP2RXbg+xPmdJ4P6CwvA5x1LZwC++ydVx4NlvT0pWicD
|
||||||
|
ZUnXjcWAJlkeOuUBAqFG7WHTrXpUUAjmdqFVq2yFjteUYBdrFz0RDB2jM9feeKYO
|
||||||
|
mTgxdZyT9a6humxCxt5VfgT02axLjm/2AqCyFPMbf4PASoJDln01AEuZLZ8Xl2gV
|
||||||
|
bYHMnHTGoD1Hu6FNEzRgkMC6XT8X3YjHvzQhpc/qL5wEfEsinQGdX4twsuWbf8xd
|
||||||
|
q7miNnkO8vd0maw=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
server:
|
||||||
|
verbosity: 8
|
||||||
|
num-threads: 1
|
||||||
|
interface: 127.0.0.1
|
||||||
|
port: @PORT@
|
||||||
|
use-syslog: no
|
||||||
|
directory: ""
|
||||||
|
pidfile: "unbound.pid"
|
||||||
|
chroot: ""
|
||||||
|
username: ""
|
||||||
|
do-not-query-localhost: no
|
||||||
|
auth-task-threads: 2
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example1.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example2.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example3.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example4.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example5.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example6.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example7.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example8.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example9.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example10.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example11.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example12.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example13.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example14.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
auth-zone:
|
||||||
|
name: "example15.com"
|
||||||
|
for-upstream: yes
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
BaseName: auth_load_list
|
||||||
|
Version: 1.0
|
||||||
|
Description: Perform more transfers than the auth load thread count
|
||||||
|
CreationDate: Fri 9 Jul 15:00:00 CEST 2026
|
||||||
|
Maintainer: dr. W.C.A. Wijngaards
|
||||||
|
Category:
|
||||||
|
Component:
|
||||||
|
CmdDepends:
|
||||||
|
Depends:
|
||||||
|
Help:
|
||||||
|
Pre: auth_load_list.pre
|
||||||
|
Post: auth_load_list.post
|
||||||
|
Test: auth_load_list.test
|
||||||
|
AuxFiles:
|
||||||
|
Passed:
|
||||||
|
Failure:
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# #-- auth_load_list.post --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# source the test var file when it's there
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
#
|
||||||
|
# do your teardown here
|
||||||
|
. ../common.sh
|
||||||
|
kill_pid $FWD_PID
|
||||||
|
kill_pid $UNBOUND_PID
|
||||||
|
cat fwd.log
|
||||||
|
cat unbound.log
|
||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
# #-- auth_load_list.pre--#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
. ../common.sh
|
||||||
|
# if no threads; exit
|
||||||
|
if grep -e "define HAVE_PTHREAD 1" -e "define HAVE_SOLARIS_THREADS 1" -e "define HAVE_WINDOWS_THREADS 1" $PRE/config.h; then
|
||||||
|
echo "have threads"
|
||||||
|
else
|
||||||
|
skip_test "no threads"
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_random_port 2
|
||||||
|
UNBOUND_PORT=$RND_PORT
|
||||||
|
FWD_PORT=$(($RND_PORT + 1))
|
||||||
|
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
|
||||||
|
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
|
||||||
|
|
||||||
|
# start forwarder
|
||||||
|
|
||||||
|
# create auth_load_list.testns
|
||||||
|
for((i=1; i<16; i++)); do
|
||||||
|
cat >>auth_load_list.testns <<EOF
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
example$i.com. IN SOA
|
||||||
|
SECTION ANSWER
|
||||||
|
example$i.com. IN SOA ns.example$i.com. hostmaster.example$i.com. 1 3600 900 86400 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
example$i.com. IN AXFR
|
||||||
|
SECTION ANSWER
|
||||||
|
example$i.com. IN SOA ns.example$i.com. hostmaster.example$i.com. 1 3600 900 86400 3600
|
||||||
|
example$i.com. IN NS ns.example.net.
|
||||||
|
EXTRA_PACKET
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
example$i.com. IN AXFR
|
||||||
|
SECTION ANSWER
|
||||||
|
www.example$i.com. IN A 1.2.3.4
|
||||||
|
example$i.com. IN SOA ns.example$i.com. hostmaster.example$i.com. 1 3600 900 86400 3600
|
||||||
|
ENTRY_END
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
get_ldns_testns
|
||||||
|
$LDNS_TESTNS -p $FWD_PORT auth_load_list.testns >fwd.log 2>&1 &
|
||||||
|
FWD_PID=$!
|
||||||
|
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
# make config file
|
||||||
|
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < auth_load_list.conf > ub.conf
|
||||||
|
# start unbound in the background
|
||||||
|
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
#valgrind --leak-check=full --show-reachable=yes $PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
UNBOUND_PID=$!
|
||||||
|
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
cat .tpkg.var.test
|
||||||
|
wait_ldns_testns_up fwd.log
|
||||||
|
wait_unbound_up unbound.log
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# #-- auth_load_list.test --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
|
||||||
|
# do the test
|
||||||
|
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
|
||||||
|
name="www.example$i.com"
|
||||||
|
echo ""
|
||||||
|
echo "> dig $name"
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT $name | tee outfile
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT $name | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT $name | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT $name | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT $name | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT $name | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT $name | tee outfile
|
||||||
|
fi
|
||||||
|
echo "> check answer"
|
||||||
|
if grep "1.2.3.4" outfile; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if grep "auth zone example$i.com. details" unbound.log; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "loop done"
|
||||||
|
|
||||||
|
exit 0
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
server:
|
||||||
|
verbosity: 8
|
||||||
|
# num-threads: 1
|
||||||
|
interface: 127.0.0.1
|
||||||
|
port: @PORT@
|
||||||
|
use-syslog: no
|
||||||
|
directory: ""
|
||||||
|
pidfile: "unbound.pid"
|
||||||
|
module-config: "respip validator iterator"
|
||||||
|
chroot: ""
|
||||||
|
username: ""
|
||||||
|
do-not-query-localhost: no
|
||||||
|
auth-task-threads: 1
|
||||||
|
log-queries: yes
|
||||||
|
log-replies: yes
|
||||||
|
|
||||||
|
forward-zone:
|
||||||
|
name: "."
|
||||||
|
forward-addr: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
rpz:
|
||||||
|
name: "rpz.example.com"
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
rpz-log: yes
|
||||||
|
rpz-log-name: "rpz.example.com"
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
BaseName: auth_load_rpz
|
||||||
|
Version: 1.0
|
||||||
|
Description: Load RPZ zone with auth load thread
|
||||||
|
CreationDate: Tue 6 Oct 10:00:00 CEST 2026
|
||||||
|
Maintainer: dr. W.C.A. Wijngaards
|
||||||
|
Category:
|
||||||
|
Component:
|
||||||
|
CmdDepends:
|
||||||
|
Depends:
|
||||||
|
Help:
|
||||||
|
Pre: auth_load_rpz.pre
|
||||||
|
Post: auth_load_rpz.post
|
||||||
|
Test: auth_load_rpz.test
|
||||||
|
AuxFiles:
|
||||||
|
Passed:
|
||||||
|
Failure:
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
# #-- auth_load_rpz.post --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# source the test var file when it's there
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
#
|
||||||
|
# do your teardown here
|
||||||
|
. ../common.sh
|
||||||
|
kill_pid $FWD_PID
|
||||||
|
kill_pid $UNBOUND_PID
|
||||||
|
cat fwd.log
|
||||||
|
cat unbound.log
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
# #-- auth_load_rpz.pre--#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
. ../common.sh
|
||||||
|
# if no threads; exit
|
||||||
|
if grep -e "define HAVE_PTHREAD 1" -e "define HAVE_SOLARIS_THREADS 1" -e "define HAVE_WINDOWS_THREADS 1" $PRE/config.h; then
|
||||||
|
echo "have threads"
|
||||||
|
else
|
||||||
|
skip_test "no threads"
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_random_port 2
|
||||||
|
UNBOUND_PORT=$RND_PORT
|
||||||
|
FWD_PORT=$(($RND_PORT + 1))
|
||||||
|
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
|
||||||
|
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
|
||||||
|
|
||||||
|
# start forwarder
|
||||||
|
get_ldns_testns
|
||||||
|
$LDNS_TESTNS -p $FWD_PORT auth_load_rpz.testns >fwd.log 2>&1 &
|
||||||
|
FWD_PID=$!
|
||||||
|
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
# make config file
|
||||||
|
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < auth_load_rpz.conf > ub.conf
|
||||||
|
# start unbound in the background
|
||||||
|
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
#valgrind --leak-check=full --show-reachable=yes $PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
UNBOUND_PID=$!
|
||||||
|
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
cat .tpkg.var.test
|
||||||
|
wait_ldns_testns_up fwd.log
|
||||||
|
wait_unbound_up unbound.log
|
||||||
|
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
# #-- auth_load_rpz.test --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
# do the test
|
||||||
|
# The answer is rewritten by RPZ, that is loaded in the auth load thread.
|
||||||
|
echo "> dig www.example.com."
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
echo "> check answer"
|
||||||
|
if grep "1.2.3.4" outfile; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep "auth zone rpz.example.com. details" unbound.log; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
rpz.example.com. IN SOA
|
||||||
|
SECTION ANSWER
|
||||||
|
rpz.example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
rpz.example.com. IN AXFR
|
||||||
|
SECTION ANSWER
|
||||||
|
rpz.example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
rpz.example.com. IN NS ns.example.net.
|
||||||
|
www.example.com.rpz.example.com. IN A 1.2.3.4
|
||||||
|
rpz.example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
ENTRY_END
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
server:
|
||||||
|
verbosity: 8
|
||||||
|
# num-threads: 1
|
||||||
|
interface: 127.0.0.1
|
||||||
|
port: @PORT@
|
||||||
|
use-syslog: no
|
||||||
|
directory: ""
|
||||||
|
pidfile: "unbound.pid"
|
||||||
|
module-config: "respip validator iterator"
|
||||||
|
chroot: ""
|
||||||
|
username: ""
|
||||||
|
do-not-query-localhost: no
|
||||||
|
auth-task-threads: 1
|
||||||
|
log-queries: yes
|
||||||
|
log-replies: yes
|
||||||
|
|
||||||
|
forward-zone:
|
||||||
|
name: "."
|
||||||
|
forward-addr: "127.0.0.1@@TOPORT@"
|
||||||
|
|
||||||
|
rpz:
|
||||||
|
name: "rpz.example.com"
|
||||||
|
zonefile: "auth_load_write.zone"
|
||||||
|
for-downstream: yes
|
||||||
|
master: "127.0.0.1@@TOPORT@"
|
||||||
|
rpz-log: yes
|
||||||
|
rpz-log-name: "rpz.example.com"
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
BaseName: auth_load_write
|
||||||
|
Version: 1.0
|
||||||
|
Description: Write zonefile with auth load thread
|
||||||
|
CreationDate: Wed 7 Oct 10:00:00 CEST 2026
|
||||||
|
Maintainer: dr. W.C.A. Wijngaards
|
||||||
|
Category:
|
||||||
|
Component:
|
||||||
|
CmdDepends:
|
||||||
|
Depends:
|
||||||
|
Help:
|
||||||
|
Pre: auth_load_write.pre
|
||||||
|
Post: auth_load_write.post
|
||||||
|
Test: auth_load_write.test
|
||||||
|
AuxFiles:
|
||||||
|
Passed:
|
||||||
|
Failure:
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# #-- auth_load_write.post --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# source the test var file when it's there
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
#
|
||||||
|
# do your teardown here
|
||||||
|
. ../common.sh
|
||||||
|
kill_pid $FWD_PID
|
||||||
|
kill_pid $UNBOUND_PID
|
||||||
|
cat fwd.log
|
||||||
|
cat unbound.log
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# #-- auth_load_write.pre--#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
. ../common.sh
|
||||||
|
# if no threads; exit
|
||||||
|
if grep -e "define HAVE_PTHREAD 1" -e "define HAVE_SOLARIS_THREADS 1" -e "define HAVE_WINDOWS_THREADS 1" $PRE/config.h; then
|
||||||
|
echo "have threads"
|
||||||
|
else
|
||||||
|
skip_test "no threads"
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_random_port 2
|
||||||
|
UNBOUND_PORT=$RND_PORT
|
||||||
|
FWD_PORT=$(($RND_PORT + 1))
|
||||||
|
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
|
||||||
|
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
|
||||||
|
|
||||||
|
# start forwarder
|
||||||
|
get_ldns_testns
|
||||||
|
$LDNS_TESTNS -p $FWD_PORT auth_load_write.testns >fwd.log 2>&1 &
|
||||||
|
FWD_PID=$!
|
||||||
|
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
# make config file
|
||||||
|
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < auth_load_write.conf > ub.conf
|
||||||
|
# start unbound in the background
|
||||||
|
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
#valgrind --leak-check=full --show-reachable=yes $PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||||
|
UNBOUND_PID=$!
|
||||||
|
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
|
||||||
|
|
||||||
|
cat .tpkg.var.test
|
||||||
|
wait_ldns_testns_up fwd.log
|
||||||
|
wait_unbound_up unbound.log
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# #-- auth_load_write.test --#
|
||||||
|
# source the master var file when it's there
|
||||||
|
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||||
|
# use .tpkg.var.test for in test variable passing
|
||||||
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
|
PRE="../.."
|
||||||
|
. ../common.sh
|
||||||
|
# do the test
|
||||||
|
# The answer is rewritten by RPZ, that is loaded in the auth load thread.
|
||||||
|
echo "> dig www.example.com."
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 1
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
if grep SERVFAIL outfile; then
|
||||||
|
echo "> try again"
|
||||||
|
sleep 3
|
||||||
|
dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile
|
||||||
|
fi
|
||||||
|
echo "> check answer"
|
||||||
|
if grep "1.2.3.4" outfile; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep "auth zone rpz.example.com. details" unbound.log; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
wait_logfile unbound.log "write zonefile auth_load_write.zone for rpz.example.com." 10
|
||||||
|
grep "write zonefile" unbound.log
|
||||||
|
echo "> auth_load_write.zone"
|
||||||
|
cat auth_load_write.zone
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if grep "text a b c d" auth_load_write.zone; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "not OK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
rpz.example.com. IN SOA
|
||||||
|
SECTION ANSWER
|
||||||
|
rpz.example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
rpz.example.com. IN AXFR
|
||||||
|
SECTION ANSWER
|
||||||
|
rpz.example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
rpz.example.com. IN NS ns.example.net.
|
||||||
|
www.example.com.rpz.example.com. IN A 1.2.3.4
|
||||||
|
txt.example.com.rpz.example.com. IN TXT "text a b c d"
|
||||||
|
rpz.example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||||
|
ENTRY_END
|
||||||
@@ -243,6 +243,7 @@ config_create(void)
|
|||||||
cfg->views = NULL;
|
cfg->views = NULL;
|
||||||
cfg->acls = NULL;
|
cfg->acls = NULL;
|
||||||
cfg->tcp_connection_limits = NULL;
|
cfg->tcp_connection_limits = NULL;
|
||||||
|
cfg->auth_task_threads = 0;
|
||||||
cfg->harden_short_bufsize = 1;
|
cfg->harden_short_bufsize = 1;
|
||||||
cfg->harden_large_queries = 0;
|
cfg->harden_large_queries = 0;
|
||||||
cfg->harden_glue = 1;
|
cfg->harden_glue = 1;
|
||||||
@@ -460,6 +461,7 @@ struct config_file* config_create_forlib(void)
|
|||||||
cfg->neg_cache_size = 100 * 1024;
|
cfg->neg_cache_size = 100 * 1024;
|
||||||
cfg->donotquery_localhost = 0; /* allow, so that you can ask a
|
cfg->donotquery_localhost = 0; /* allow, so that you can ask a
|
||||||
forward nameserver running on localhost */
|
forward nameserver running on localhost */
|
||||||
|
cfg->auth_task_threads = 0; /* no extra threads to spawn in library */
|
||||||
cfg->val_log_level = 2; /* to fill why_bogus with */
|
cfg->val_log_level = 2; /* to fill why_bogus with */
|
||||||
cfg->val_log_squelch = 1;
|
cfg->val_log_squelch = 1;
|
||||||
cfg->minimal_responses = 0;
|
cfg->minimal_responses = 0;
|
||||||
@@ -746,6 +748,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
|||||||
else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold)
|
else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold)
|
||||||
else S_STRLIST("private-address:", private_address)
|
else S_STRLIST("private-address:", private_address)
|
||||||
else S_STRLIST("private-domain:", private_domain)
|
else S_STRLIST("private-domain:", private_domain)
|
||||||
|
else S_NUMBER_OR_ZERO("auth-task-threads:", auth_task_threads)
|
||||||
else S_YNO("do-not-query-localhost:", donotquery_localhost)
|
else S_YNO("do-not-query-localhost:", donotquery_localhost)
|
||||||
else S_STRLIST("do-not-query-address:", donotqueryaddrs)
|
else S_STRLIST("do-not-query-address:", donotqueryaddrs)
|
||||||
else S_STRLIST("auto-trust-anchor-file:", auto_trust_anchor_file_list)
|
else S_STRLIST("auto-trust-anchor-file:", auto_trust_anchor_file_list)
|
||||||
@@ -1293,6 +1296,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
|||||||
else O_LST(opt, "root-hints", root_hints)
|
else O_LST(opt, "root-hints", root_hints)
|
||||||
else O_LS2(opt, "access-control", acls)
|
else O_LS2(opt, "access-control", acls)
|
||||||
else O_LS2(opt, "tcp-connection-limit", tcp_connection_limits)
|
else O_LS2(opt, "tcp-connection-limit", tcp_connection_limits)
|
||||||
|
else O_DEC(opt, "auth-task-threads", auth_task_threads)
|
||||||
else O_LST(opt, "do-not-query-address", donotqueryaddrs)
|
else O_LST(opt, "do-not-query-address", donotqueryaddrs)
|
||||||
else O_LST(opt, "private-address", private_address)
|
else O_LST(opt, "private-address", private_address)
|
||||||
else O_LST(opt, "private-domain", private_domain)
|
else O_LST(opt, "private-domain", private_domain)
|
||||||
|
|||||||
@@ -291,6 +291,8 @@ struct config_file {
|
|||||||
|
|
||||||
/** list of tcp connection limitss, linked list */
|
/** list of tcp connection limitss, linked list */
|
||||||
struct config_str2list* tcp_connection_limits;
|
struct config_str2list* tcp_connection_limits;
|
||||||
|
/** auth task threads, or 0 disabled. */
|
||||||
|
int auth_task_threads;
|
||||||
|
|
||||||
/** harden against very small edns buffer sizes */
|
/** harden against very small edns buffer sizes */
|
||||||
int harden_short_bufsize;
|
int harden_short_bufsize;
|
||||||
|
|||||||
@@ -596,6 +596,7 @@ name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) }
|
|||||||
name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) }
|
name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) }
|
||||||
udp-upstream-without-downstream{COLON} { YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM) }
|
udp-upstream-without-downstream{COLON} { YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM) }
|
||||||
tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
|
tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
|
||||||
|
auth-task-threads{COLON} { YDVAR(1, VAR_AUTH_TASK_THREADS) }
|
||||||
answer-cookie{COLON} { YDVAR(1, VAR_ANSWER_COOKIE ) }
|
answer-cookie{COLON} { YDVAR(1, VAR_ANSWER_COOKIE ) }
|
||||||
cookie-secret{COLON} { YDVAR(1, VAR_COOKIE_SECRET) }
|
cookie-secret{COLON} { YDVAR(1, VAR_COOKIE_SECRET) }
|
||||||
cookie-secret-file{COLON} { YDVAR(1, VAR_COOKIE_SECRET_FILE) }
|
cookie-secret-file{COLON} { YDVAR(1, VAR_COOKIE_SECRET_FILE) }
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ extern struct config_parser_state* cfg_parser;
|
|||||||
%token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL
|
%token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL
|
||||||
%token VAR_FAST_SERVER_PERMIL VAR_FAST_SERVER_NUM
|
%token VAR_FAST_SERVER_PERMIL VAR_FAST_SERVER_NUM
|
||||||
%token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT VAR_TCP_CONNECTION_LIMIT
|
%token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT VAR_TCP_CONNECTION_LIMIT
|
||||||
|
%token VAR_AUTH_TASK_THREADS
|
||||||
%token VAR_ANSWER_COOKIE VAR_COOKIE_SECRET VAR_IP_RATELIMIT_COOKIE
|
%token VAR_ANSWER_COOKIE VAR_COOKIE_SECRET VAR_IP_RATELIMIT_COOKIE
|
||||||
%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
|
%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
|
||||||
%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
|
%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
|
||||||
@@ -345,6 +346,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
|||||||
server_tls_cert_bundle | server_tls_additional_port | server_low_rtt |
|
server_tls_cert_bundle | server_tls_additional_port | server_low_rtt |
|
||||||
server_fast_server_permil | server_fast_server_num | server_tls_win_cert |
|
server_fast_server_permil | server_fast_server_num | server_tls_win_cert |
|
||||||
server_tcp_connection_limit | server_log_servfail | server_deny_any |
|
server_tcp_connection_limit | server_log_servfail | server_deny_any |
|
||||||
|
server_auth_task_threads |
|
||||||
server_unknown_server_time_limit | server_log_tag_queryreply |
|
server_unknown_server_time_limit | server_log_tag_queryreply |
|
||||||
server_discard_timeout | server_wait_limit | server_wait_limit_cookie |
|
server_discard_timeout | server_wait_limit | server_wait_limit_cookie |
|
||||||
server_wait_limit_netblock | server_wait_limit_cookie_netblock |
|
server_wait_limit_netblock | server_wait_limit_cookie_netblock |
|
||||||
@@ -4211,6 +4213,15 @@ server_tcp_connection_limit: VAR_TCP_CONNECTION_LIMIT STRING_ARG STRING_ARG
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
server_auth_task_threads: VAR_AUTH_TASK_THREADS STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(server_auth_task_threads:%s)\n", $2));
|
||||||
|
if(atoi($2) == 0 && strcmp($2, "0") != 0)
|
||||||
|
yyerror("number expected");
|
||||||
|
else cfg_parser->cfg->auth_task_threads = atoi($2);
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
server_answer_cookie: VAR_ANSWER_COOKIE STRING_ARG
|
server_answer_cookie: VAR_ANSWER_COOKIE STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(server_answer_cookie:%s)\n", $2));
|
OUTYY(("P(server_answer_cookie:%s)\n", $2));
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
#include "services/mesh.h"
|
#include "services/mesh.h"
|
||||||
#include "services/localzone.h"
|
#include "services/localzone.h"
|
||||||
#include "services/authzone.h"
|
#include "services/authzone.h"
|
||||||
|
#include "services/authload.h"
|
||||||
#include "services/cache/infra.h"
|
#include "services/cache/infra.h"
|
||||||
#include "services/cache/rrset.h"
|
#include "services/cache/rrset.h"
|
||||||
#include "services/view.h"
|
#include "services/view.h"
|
||||||
@@ -72,6 +73,7 @@
|
|||||||
#include "libunbound/libworker.h"
|
#include "libunbound/libworker.h"
|
||||||
#include "libunbound/context.h"
|
#include "libunbound/context.h"
|
||||||
#include "libunbound/worker.h"
|
#include "libunbound/worker.h"
|
||||||
|
#include "libunbound/authload.h"
|
||||||
#include "util/tube.h"
|
#include "util/tube.h"
|
||||||
#include "util/config_file.h"
|
#include "util/config_file.h"
|
||||||
#include "daemon/remote.h"
|
#include "daemon/remote.h"
|
||||||
@@ -146,6 +148,7 @@ fptr_whitelist_comm_timer(void (*fptr)(void*))
|
|||||||
else if(fptr == &auth_xfer_timer) return 1;
|
else if(fptr == &auth_xfer_timer) return 1;
|
||||||
else if(fptr == &auth_xfer_probe_timer_callback) return 1;
|
else if(fptr == &auth_xfer_probe_timer_callback) return 1;
|
||||||
else if(fptr == &auth_xfer_transfer_timer_callback) return 1;
|
else if(fptr == &auth_xfer_transfer_timer_callback) return 1;
|
||||||
|
else if(fptr == &auth_load_resume_timer_cb) return 1;
|
||||||
else if(fptr == &mesh_serve_expired_callback) return 1;
|
else if(fptr == &mesh_serve_expired_callback) return 1;
|
||||||
else if(fptr == &serviced_timer_cb) return 1;
|
else if(fptr == &serviced_timer_cb) return 1;
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
@@ -193,6 +196,7 @@ fptr_whitelist_event(void (*fptr)(int, short, void *))
|
|||||||
else if(fptr == &comm_point_doq_callback) return 1;
|
else if(fptr == &comm_point_doq_callback) return 1;
|
||||||
#endif
|
#endif
|
||||||
else if(fptr == &fast_reload_service_cb) return 1;
|
else if(fptr == &fast_reload_service_cb) return 1;
|
||||||
|
else if(fptr == &worker_auth_load_service_cb) return 1;
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
else if(fptr == &dtio_output_cb) return 1;
|
else if(fptr == &dtio_output_cb) return 1;
|
||||||
else if(fptr == &dtio_cmd_cb) return 1;
|
else if(fptr == &dtio_cmd_cb) return 1;
|
||||||
@@ -264,6 +268,7 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
|
|||||||
else if(fptr == &auth_zone_cmp) return 1;
|
else if(fptr == &auth_zone_cmp) return 1;
|
||||||
else if(fptr == &auth_data_cmp) return 1;
|
else if(fptr == &auth_data_cmp) return 1;
|
||||||
else if(fptr == &auth_xfer_cmp) return 1;
|
else if(fptr == &auth_xfer_cmp) return 1;
|
||||||
|
else if(fptr == &auth_load_tree_cmp) return 1;
|
||||||
#ifdef HAVE_NGTCP2
|
#ifdef HAVE_NGTCP2
|
||||||
else if(fptr == &doq_conn_cmp) return 1;
|
else if(fptr == &doq_conn_cmp) return 1;
|
||||||
else if(fptr == &doq_conid_cmp) return 1;
|
else if(fptr == &doq_conid_cmp) return 1;
|
||||||
|
|||||||
+360
@@ -58,6 +58,9 @@
|
|||||||
#include "sldns/wire2str.h"
|
#include "sldns/wire2str.h"
|
||||||
#include "sldns/str2wire.h"
|
#include "sldns/str2wire.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#ifdef HAVE_POLL_H
|
||||||
|
#include <poll.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_OPENSSL_SSL_H
|
#ifdef HAVE_OPENSSL_SSL_H
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
@@ -92,6 +95,9 @@ int RRSET_ROUNDROBIN = 1;
|
|||||||
/** log tag queries with name instead of 'info' for filtering */
|
/** log tag queries with name instead of 'info' for filtering */
|
||||||
int LOG_TAG_QUERYREPLY = 0;
|
int LOG_TAG_QUERYREPLY = 0;
|
||||||
|
|
||||||
|
/** What number of loop iterations is too much for sock poll retries */
|
||||||
|
#define SOCK_POLL_LOOP_MAX 200
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
static struct tls_session_ticket_key {
|
static struct tls_session_ticket_key {
|
||||||
unsigned char *key_name;
|
unsigned char *key_name;
|
||||||
@@ -2083,3 +2089,357 @@ hex_pton(const char* src, uint8_t* target, size_t targsize)
|
|||||||
}
|
}
|
||||||
return t-target;
|
return t-target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
|
||||||
|
{
|
||||||
|
int loopcount = 0;
|
||||||
|
/* Loop if the system call returns an errno to do so, like EINTR. */
|
||||||
|
log_assert(pollin || pollout);
|
||||||
|
while(1) {
|
||||||
|
struct pollfd p, *fds;
|
||||||
|
int nfds, ret;
|
||||||
|
if(++loopcount > SOCK_POLL_LOOP_MAX) {
|
||||||
|
log_err("sock_poll_timeout: loop");
|
||||||
|
if(event)
|
||||||
|
*event = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(fd == -1) {
|
||||||
|
fds = NULL;
|
||||||
|
nfds = 0;
|
||||||
|
} else {
|
||||||
|
fds = &p;
|
||||||
|
nfds = 1;
|
||||||
|
memset(&p, 0, sizeof(p));
|
||||||
|
p.fd = fd;
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
p.events = POLLERR
|
||||||
|
| POLLHUP
|
||||||
|
;
|
||||||
|
#endif
|
||||||
|
if(pollin)
|
||||||
|
p.events |= POLLIN;
|
||||||
|
if(pollout)
|
||||||
|
p.events |= POLLOUT;
|
||||||
|
}
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
ret = poll(fds, nfds, timeout);
|
||||||
|
#else
|
||||||
|
if(fds == NULL) {
|
||||||
|
Sleep(timeout);
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
ret = WSAPoll(fds, nfds, timeout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(ret == -1) {
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
if(
|
||||||
|
errno == EINTR || errno == EAGAIN
|
||||||
|
# ifdef EWOULDBLOCK
|
||||||
|
|| errno == EWOULDBLOCK
|
||||||
|
# endif
|
||||||
|
) continue; /* Try again. */
|
||||||
|
#endif
|
||||||
|
/* For WSAPoll we only get errors here:
|
||||||
|
* o WSAENETDOWN
|
||||||
|
* o WSAEFAULT
|
||||||
|
* o WSAEINVAL
|
||||||
|
* o WSAENOBUFS
|
||||||
|
*/
|
||||||
|
log_err("poll: %s", sock_strerror(errno));
|
||||||
|
if(event)
|
||||||
|
*event = 0;
|
||||||
|
return 0;
|
||||||
|
} else if(ret == 0) {
|
||||||
|
/* Timeout */
|
||||||
|
if(event)
|
||||||
|
*event = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(event)
|
||||||
|
*event = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
create_socketpair(int* pair, struct ub_randstate* rand)
|
||||||
|
{
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
if(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
|
||||||
|
log_err("socketpair: %s", strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
(void)rand;
|
||||||
|
#else
|
||||||
|
struct sockaddr_in addr, baddr, accaddr, connaddr;
|
||||||
|
socklen_t baddrlen, accaddrlen, connaddrlen;
|
||||||
|
uint8_t localhost[] = {127, 0, 0, 1};
|
||||||
|
uint8_t nonce[16], recvnonce[16];
|
||||||
|
size_t i;
|
||||||
|
int lst, pollin_event, bcount, loopcount;
|
||||||
|
int connect_poll_timeout = 200; /* msec to wait for connection */
|
||||||
|
ssize_t ret;
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
for(i=0; i<sizeof(nonce); i++) {
|
||||||
|
nonce[i] = ub_random_max(rand, 256);
|
||||||
|
}
|
||||||
|
lst = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(lst == -1) {
|
||||||
|
log_err("create_socketpair: socket: %s", sock_strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = 0;
|
||||||
|
memcpy(&addr.sin_addr, localhost, 4);
|
||||||
|
if(bind(lst, (struct sockaddr*)&addr, (socklen_t)sizeof(addr))
|
||||||
|
== -1) {
|
||||||
|
log_err("create socketpair: bind: %s", sock_strerror(errno));
|
||||||
|
sock_close(lst);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(listen(lst, 12) == -1) {
|
||||||
|
log_err("create socketpair: listen: %s", sock_strerror(errno));
|
||||||
|
sock_close(lst);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pair[1] = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(pair[1] == -1) {
|
||||||
|
log_err("create socketpair: socket: %s", sock_strerror(errno));
|
||||||
|
sock_close(lst);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
baddrlen = (socklen_t)sizeof(baddr);
|
||||||
|
if(getsockname(lst, (struct sockaddr*)&baddr, &baddrlen) == -1) {
|
||||||
|
log_err("create socketpair: getsockname: %s",
|
||||||
|
sock_strerror(errno));
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(baddrlen > (socklen_t)sizeof(baddr)) {
|
||||||
|
log_err("create socketpair: getsockname returned addr too big");
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* the socket is blocking */
|
||||||
|
if(connect(pair[1], (struct sockaddr*)&baddr, baddrlen) == -1) {
|
||||||
|
log_err("create socketpair: connect: %s",
|
||||||
|
sock_strerror(errno));
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!sock_poll_timeout(lst, connect_poll_timeout, 1, 0, &pollin_event)) {
|
||||||
|
log_err("create socketpair: poll for accept failed: %s",
|
||||||
|
sock_strerror(errno));
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!pollin_event) {
|
||||||
|
log_err("create socketpair: poll timeout for accept");
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
accaddrlen = (socklen_t)sizeof(accaddr);
|
||||||
|
pair[0] = accept(lst, (struct sockaddr*)&accaddr, &accaddrlen);
|
||||||
|
if(pair[0] == -1) {
|
||||||
|
log_err("create socketpair: accept: %s", sock_strerror(errno));
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(accaddrlen > (socklen_t)sizeof(accaddr)) {
|
||||||
|
log_err("create socketpair: accept returned addr too big");
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(accaddr.sin_family != AF_INET ||
|
||||||
|
memcmp(localhost, &accaddr.sin_addr, 4) != 0) {
|
||||||
|
log_err("create socketpair: accept from wrong address");
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
connaddrlen = (socklen_t)sizeof(connaddr);
|
||||||
|
if(getsockname(pair[1], (struct sockaddr*)&connaddr, &connaddrlen)
|
||||||
|
== -1) {
|
||||||
|
log_err("create socketpair: getsockname connectedaddr: %s",
|
||||||
|
sock_strerror(errno));
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(connaddrlen > (socklen_t)sizeof(connaddr)) {
|
||||||
|
log_err("create socketpair: getsockname connectedaddr returned addr too big");
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(connaddr.sin_family != AF_INET ||
|
||||||
|
memcmp(localhost, &connaddr.sin_addr, 4) != 0) {
|
||||||
|
log_err("create socketpair: getsockname connectedaddr returned wrong address");
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(accaddr.sin_port != connaddr.sin_port) {
|
||||||
|
log_err("create socketpair: accept from wrong port");
|
||||||
|
sock_close(lst);
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sock_close(lst);
|
||||||
|
|
||||||
|
loopcount = 0;
|
||||||
|
bcount = 0;
|
||||||
|
while(1) {
|
||||||
|
if(++loopcount > SOCK_POLL_LOOP_MAX) {
|
||||||
|
log_err("create socketpair: send failed due to loop");
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret = send(pair[1], (void*)(nonce+bcount),
|
||||||
|
sizeof(nonce)-bcount, 0);
|
||||||
|
if(ret == -1) {
|
||||||
|
if(
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
errno == EINTR || errno == EAGAIN
|
||||||
|
# ifdef EWOULDBLOCK
|
||||||
|
|| errno == EWOULDBLOCK
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
WSAGetLastError() == WSAEINTR ||
|
||||||
|
WSAGetLastError() == WSAEINPROGRESS ||
|
||||||
|
WSAGetLastError() == WSAEWOULDBLOCK
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
continue; /* Try again. */
|
||||||
|
log_err("create socketpair: send: %s", sock_strerror(errno));
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
} else if(ret+(ssize_t)bcount != sizeof(nonce)) {
|
||||||
|
bcount += ret;
|
||||||
|
if((size_t)bcount < sizeof(nonce))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!sock_poll_timeout(pair[0], connect_poll_timeout, 1, 0, &pollin_event)) {
|
||||||
|
log_err("create socketpair: poll failed: %s",
|
||||||
|
sock_strerror(errno));
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!pollin_event) {
|
||||||
|
log_err("create socketpair: poll timeout for recv");
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
loopcount = 0;
|
||||||
|
bcount = 0;
|
||||||
|
while(1) {
|
||||||
|
if(++loopcount > SOCK_POLL_LOOP_MAX) {
|
||||||
|
log_err("create socketpair: recv failed due to loop");
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret = recv(pair[0], (void*)(recvnonce+bcount),
|
||||||
|
sizeof(nonce)-bcount, 0);
|
||||||
|
if(ret == -1) {
|
||||||
|
if(
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
errno == EINTR || errno == EAGAIN
|
||||||
|
# ifdef EWOULDBLOCK
|
||||||
|
|| errno == EWOULDBLOCK
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
WSAGetLastError() == WSAEINTR ||
|
||||||
|
WSAGetLastError() == WSAEINPROGRESS ||
|
||||||
|
WSAGetLastError() == WSAEWOULDBLOCK
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
continue; /* Try again. */
|
||||||
|
log_err("create socketpair: recv: %s", sock_strerror(errno));
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
} else if(ret == 0) {
|
||||||
|
log_err("create socketpair: stream closed");
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
} else if(ret+(ssize_t)bcount != sizeof(nonce)) {
|
||||||
|
bcount += ret;
|
||||||
|
if((size_t)bcount < sizeof(nonce))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(memcmp(nonce, recvnonce, sizeof(nonce)) != 0) {
|
||||||
|
log_err("create socketpair: recv wrong nonce");
|
||||||
|
sock_close(pair[0]);
|
||||||
|
sock_close(pair[1]);
|
||||||
|
pair[0] = -1;
|
||||||
|
pair[1] = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -604,4 +604,20 @@ ssize_t hex_ntop(uint8_t const *src, size_t srclength, char *target,
|
|||||||
/** Convert hexadecimal data to binary. */
|
/** Convert hexadecimal data to binary. */
|
||||||
ssize_t hex_pton(const char* src, uint8_t* target, size_t targsize);
|
ssize_t hex_pton(const char* src, uint8_t* target, size_t targsize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This routine polls a socket for readiness.
|
||||||
|
* @param fd: file descriptor, -1 uses no fd for a timer only.
|
||||||
|
* @param timeout: time in msec to wait. 0 means nonblocking test,
|
||||||
|
* -1 waits blocking for events.
|
||||||
|
* @param pollin: check for input event.
|
||||||
|
* @param pollout: check for output event.
|
||||||
|
* @param event: output variable, set to true if the event happens.
|
||||||
|
* It is false if there was an error or timeout.
|
||||||
|
* @return false is system call failure, also logged.
|
||||||
|
*/
|
||||||
|
int sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event);
|
||||||
|
|
||||||
|
/** create a socketpair for bidirectional communication, false on failure */
|
||||||
|
int create_socketpair(int* pair, struct ub_randstate* rand);
|
||||||
|
|
||||||
#endif /* NET_HELP_H */
|
#endif /* NET_HELP_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user