Merging upstream version 2.7.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 08:59:05 +01:00
parent 01b97c50cd
commit 424dd7d6cc
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
27 changed files with 1877 additions and 102 deletions

View file

@ -30,19 +30,19 @@ bin_PROGRAMS = dnsperf resperf
dist_bin_SCRIPTS = resperf-report
_libperf_sources = datafile.c dns.c log.c net.c opt.c os.c strerror.c qtype.c \
edns.c tsig.c net_udp.c net_tcp.c net_dot.c
edns.c tsig.c net_udp.c net_tcp.c net_dot.c net_doh.c parse_uri.c
_libperf_headers = datafile.h dns.h log.h net.h opt.h os.h util.h strerror.h \
list.h result.h buffer.h qtype.h edns.h tsig.h
list.h result.h buffer.h qtype.h edns.h tsig.h parse_uri.h
dnsperf_SOURCES = $(_libperf_sources) dnsperf.c
dist_dnsperf_SOURCES = $(_libperf_headers)
dnsperf_LDADD = $(PTHREAD_LIBS) $(libssl_LIBS) $(libcrypto_LIBS) \
$(libldns_LIBS)
$(libldns_LIBS) $(libnghttp2_LIBS)
resperf_SOURCES = $(_libperf_sources) resperf.c
dist_resperf_SOURCES = $(_libperf_headers)
resperf_LDADD = $(PTHREAD_LIBS) $(libssl_LIBS) $(libcrypto_LIBS) \
$(libldns_LIBS)
$(libldns_LIBS) $(libnghttp2_LIBS)
man1_MANS = dnsperf.1 resperf.1

View file

@ -130,14 +130,16 @@ PROGRAMS = $(bin_PROGRAMS)
am__objects_1 = datafile.$(OBJEXT) dns.$(OBJEXT) log.$(OBJEXT) \
net.$(OBJEXT) opt.$(OBJEXT) os.$(OBJEXT) strerror.$(OBJEXT) \
qtype.$(OBJEXT) edns.$(OBJEXT) tsig.$(OBJEXT) \
net_udp.$(OBJEXT) net_tcp.$(OBJEXT) net_dot.$(OBJEXT)
net_udp.$(OBJEXT) net_tcp.$(OBJEXT) net_dot.$(OBJEXT) \
net_doh.$(OBJEXT) parse_uri.$(OBJEXT)
am_dnsperf_OBJECTS = $(am__objects_1) dnsperf.$(OBJEXT)
am__objects_2 =
dist_dnsperf_OBJECTS = $(am__objects_2)
dnsperf_OBJECTS = $(am_dnsperf_OBJECTS) $(dist_dnsperf_OBJECTS)
am__DEPENDENCIES_1 =
dnsperf_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
@ -146,7 +148,8 @@ am_resperf_OBJECTS = $(am__objects_1) resperf.$(OBJEXT)
dist_resperf_OBJECTS = $(am__objects_2)
resperf_OBJECTS = $(am_resperf_OBJECTS) $(dist_resperf_OBJECTS)
resperf_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@ -192,9 +195,10 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/datafile.Po ./$(DEPDIR)/dns.Po \
./$(DEPDIR)/dnsperf.Po ./$(DEPDIR)/edns.Po ./$(DEPDIR)/log.Po \
./$(DEPDIR)/net.Po ./$(DEPDIR)/net_dot.Po \
./$(DEPDIR)/net_tcp.Po ./$(DEPDIR)/net_udp.Po \
./$(DEPDIR)/opt.Po ./$(DEPDIR)/os.Po ./$(DEPDIR)/qtype.Po \
./$(DEPDIR)/net.Po ./$(DEPDIR)/net_doh.Po \
./$(DEPDIR)/net_dot.Po ./$(DEPDIR)/net_tcp.Po \
./$(DEPDIR)/net_udp.Po ./$(DEPDIR)/opt.Po ./$(DEPDIR)/os.Po \
./$(DEPDIR)/parse_uri.Po ./$(DEPDIR)/qtype.Po \
./$(DEPDIR)/resperf.Po ./$(DEPDIR)/strerror.Po \
./$(DEPDIR)/tsig.Po
am__mv = mv -f
@ -405,6 +409,8 @@ libdir = @libdir@
libexecdir = @libexecdir@
libldns_CFLAGS = @libldns_CFLAGS@
libldns_LIBS = @libldns_LIBS@
libnghttp2_CFLAGS = @libnghttp2_CFLAGS@
libnghttp2_LIBS = @libnghttp2_LIBS@
libssl_CFLAGS = @libssl_CFLAGS@
libssl_LIBS = @libssl_LIBS@
localedir = @localedir@
@ -435,20 +441,20 @@ AM_CFLAGS = -I$(srcdir) \
EXTRA_DIST = dnsperf.1.in resperf-report resperf.1.in
dist_bin_SCRIPTS = resperf-report
_libperf_sources = datafile.c dns.c log.c net.c opt.c os.c strerror.c qtype.c \
edns.c tsig.c net_udp.c net_tcp.c net_dot.c
edns.c tsig.c net_udp.c net_tcp.c net_dot.c net_doh.c parse_uri.c
_libperf_headers = datafile.h dns.h log.h net.h opt.h os.h util.h strerror.h \
list.h result.h buffer.h qtype.h edns.h tsig.h
list.h result.h buffer.h qtype.h edns.h tsig.h parse_uri.h
dnsperf_SOURCES = $(_libperf_sources) dnsperf.c
dist_dnsperf_SOURCES = $(_libperf_headers)
dnsperf_LDADD = $(PTHREAD_LIBS) $(libssl_LIBS) $(libcrypto_LIBS) \
$(libldns_LIBS)
$(libldns_LIBS) $(libnghttp2_LIBS)
resperf_SOURCES = $(_libperf_sources) resperf.c
dist_resperf_SOURCES = $(_libperf_headers)
resperf_LDADD = $(PTHREAD_LIBS) $(libssl_LIBS) $(libcrypto_LIBS) \
$(libldns_LIBS)
$(libldns_LIBS) $(libnghttp2_LIBS)
man1_MANS = dnsperf.1 resperf.1
all: config.h
@ -605,11 +611,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edns.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_doh.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_dot.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_tcp.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_udp.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_uri.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qtype.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resperf.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strerror.Po@am__quote@ # am--include-marker
@ -902,11 +910,13 @@ distclean: distclean-recursive
-rm -f ./$(DEPDIR)/edns.Po
-rm -f ./$(DEPDIR)/log.Po
-rm -f ./$(DEPDIR)/net.Po
-rm -f ./$(DEPDIR)/net_doh.Po
-rm -f ./$(DEPDIR)/net_dot.Po
-rm -f ./$(DEPDIR)/net_tcp.Po
-rm -f ./$(DEPDIR)/net_udp.Po
-rm -f ./$(DEPDIR)/opt.Po
-rm -f ./$(DEPDIR)/os.Po
-rm -f ./$(DEPDIR)/parse_uri.Po
-rm -f ./$(DEPDIR)/qtype.Po
-rm -f ./$(DEPDIR)/resperf.Po
-rm -f ./$(DEPDIR)/strerror.Po
@ -966,11 +976,13 @@ maintainer-clean: maintainer-clean-recursive
-rm -f ./$(DEPDIR)/edns.Po
-rm -f ./$(DEPDIR)/log.Po
-rm -f ./$(DEPDIR)/net.Po
-rm -f ./$(DEPDIR)/net_doh.Po
-rm -f ./$(DEPDIR)/net_dot.Po
-rm -f ./$(DEPDIR)/net_tcp.Po
-rm -f ./$(DEPDIR)/net_udp.Po
-rm -f ./$(DEPDIR)/opt.Po
-rm -f ./$(DEPDIR)/os.Po
-rm -f ./$(DEPDIR)/parse_uri.Po
-rm -f ./$(DEPDIR)/qtype.Po
-rm -f ./$(DEPDIR)/resperf.Po
-rm -f ./$(DEPDIR)/strerror.Po

View file

@ -21,9 +21,15 @@
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the `nghttp2' library (-lnghttp2). */
#undef HAVE_LIBNGHTTP2
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <nghttp2.h> header file. */
#undef HAVE_NGHTTP2_H
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD

View file

@ -53,6 +53,7 @@ const char* perf_dns_rcode_strings[] = {
perf_result_t perf_dname_fromstring(const char* str, size_t len, perf_buffer_t* target)
{
size_t label_len, at;
ssize_t max = 255;
const char* orig_str = str;
bool is_quoted;
@ -101,6 +102,10 @@ perf_result_t perf_dname_fromstring(const char* str, size_t len, perf_buffer_t*
if (label_len > 63) {
return PERF_R_FAILURE;
}
max -= label_len + 1;
if (max < 0) {
return PERF_R_FAILURE;
}
perf_buffer_putuint8(target, label_len);
if (is_quoted) {
for (at = 0; at < len; at++) {

View file

@ -44,6 +44,7 @@ dnsperf \- test the performance of a DNS server
[\fB\-W\fR]
[\fB\-x\ \fIlocal_port\fR]
[\fB\-y\ \fI[alg:]name:secret\fR]
[\fB\-O\ \fIoption=value\fR]
.ad
.hy
.SH DESCRIPTION
@ -170,6 +171,11 @@ test over a local Ethernet connection, it should be zero.
If one or more packets has been dropped, there may be a problem with the
network connection.
In that case, the results should be considered suspect and the test repeated.
.SS "Using DNS-over-HTTPS"
When using DNS-over-HTTPS you must set the \fB-O doh\-uri=...\fR to something
that works with the server you're sending to.
Also note that the value for maximum outstanding queries will be used to
control the maximum concurrent streams within the HTTP/2 connection.
.SH OPTIONS
\fB-a \fIlocal_addr\fR
@ -259,7 +265,7 @@ times; if a time limit is set, the file may be read fewer times.
.br
.RS
Sets the port on which the DNS packets are sent.
If not specified, the standard DNS port (udp/tcp 53, DoT 853) is used.
If not specified, the standard DNS port (udp/tcp 53, DoT 853, DoH 443) is used.
.RE
\fB-q \fInum_queries\fR
@ -281,7 +287,7 @@ There is no default limit.
\fB-m \fImode\fR
.br
.RS
Specifies the transport mode to use, "udp", "tcp" or "dot".
Specifies the transport mode to use, "udp", "tcp", "dot" or "doh".
Default is "udp".
.RE
@ -368,6 +374,29 @@ the secret is expressed as a base-64 encoded string.
Available algorithms are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256,
hmac-sha384 and hmac-sha512.
.RE
\fB-O \fIoption=value\fR
.br
.RS
Set an extended long option for various things to control different aspects
of testing or protocol modules, see EXTENDED OPTIONS for list of available
options.
.RE
.SH "EXTENDED OPTIONS"
\fBdoh-uri=\fIURI\fR
.br
.RS
The URI to use for DNS-over-HTTPS, default value is
"https://localhost/dns-query".
.RE
\fBdoh-method=\fIHTTP_METHOD\fR
.br
.RS
The HTTP method to use when querying with DNS-over-HTTPS, default is GET.
Available methods are: GET, POST.
.RE
.SH "SEE ALSO"
\fBresperf\fR(1)
.SH AUTHOR

View file

@ -52,7 +52,8 @@
#define DEFAULT_SERVER_NAME "127.0.0.1"
#define DEFAULT_SERVER_PORT 53
#define DEFAULT_SERVER_DOT_PORT 853
#define DEFAULT_SERVER_PORTS "udp/tcp 53 or DoT 853"
#define DEFAULT_SERVER_DOH_PORT 443
#define DEFAULT_SERVER_PORTS "udp/tcp 53, DoT 853 or DoH 443"
#define DEFAULT_LOCAL_PORT 0
#define DEFAULT_MAX_OUTSTANDING 100
#define DEFAULT_TIMEOUT 5
@ -407,6 +408,8 @@ setup(int argc, char** argv, config_t* config)
const char* edns_option = NULL;
const char* tsigkey = NULL;
const char* mode = 0;
const char* doh_uri = DEFAULT_DOH_URI;
const char* doh_method = DEFAULT_DOH_METHOD;
memset(config, 0, sizeof(*config));
config->argc = argc;
@ -422,7 +425,7 @@ setup(int argc, char** argv, config_t* config)
perf_opt_add('f', perf_opt_string, "family",
"address family of DNS transport, inet or inet6", "any",
&family);
perf_opt_add('m', perf_opt_string, "mode", "set transport mode: udp, tcp or dot", "udp", &mode);
perf_opt_add('m', perf_opt_string, "mode", "set transport mode: udp, tcp, dot or doh", "udp", &mode);
perf_opt_add('s', perf_opt_string, "server_addr",
"the server to query", DEFAULT_SERVER_NAME, &server_name);
perf_opt_add('p', perf_opt_port, "port",
@ -480,6 +483,11 @@ setup(int argc, char** argv, config_t* config)
perf_opt_add('v', perf_opt_boolean, NULL,
"verbose: report each query and additional information to stdout",
NULL, &config->verbose);
perf_long_opt_add("doh-uri", perf_opt_string, "doh_uri",
"the URI to use for DNS-over-HTTPS", DEFAULT_DOH_URI, &doh_uri);
perf_long_opt_add("doh-method", perf_opt_string, "doh_method",
"the HTTP method to use for DNS-over-HTTPS: GET or POST", DEFAULT_DOH_METHOD, &doh_method);
bool log_stdout = false;
perf_opt_add('W', perf_opt_boolean, NULL, "log warnings and errors to stdout instead of stderr", NULL, &log_stdout);
@ -493,9 +501,27 @@ setup(int argc, char** argv, config_t* config)
config->mode = perf_net_parsemode(mode);
if (!server_port) {
server_port = config->mode == sock_dot ? DEFAULT_SERVER_DOT_PORT : DEFAULT_SERVER_PORT;
switch (config->mode) {
case sock_doh:
server_port = DEFAULT_SERVER_DOH_PORT;
break;
case sock_dot:
server_port = DEFAULT_SERVER_DOT_PORT;
break;
default:
server_port = DEFAULT_SERVER_PORT;
break;
}
}
if (doh_uri) {
perf_net_doh_parse_uri(doh_uri);
}
if (doh_method) {
perf_net_doh_parse_method(doh_method);
}
perf_net_doh_set_max_concurrent_streams(config->max_outstanding);
if (family != NULL)
config->family = perf_net_parsefamily(family);
perf_net_parseserver(config->family, server_name, server_port,
@ -1181,13 +1207,11 @@ threadinfo_init(threadinfo_t* tinfo, const config_t* config,
tinfo->socks[i] = perf_net_opensocket(config->mode, &config->server_addr,
&config->local_addr,
socket_offset++,
config->bufsize);
config->bufsize,
tinfo, perf__net_sent, perf__net_event);
if (!tinfo->socks[i]) {
perf_log_fatal("perf_net_opensocket(): no socket returned, out of memory?");
}
tinfo->socks[i]->data = tinfo;
tinfo->socks[i]->sent = perf__net_sent;
tinfo->socks[i]->event = perf__net_event;
}
tinfo->current_sock = 0;
@ -1204,14 +1228,16 @@ threadinfo_stop(threadinfo_t* tinfo)
}
static void
threadinfo_cleanup(threadinfo_t* tinfo, times_t* times)
threadinfo_cleanup(config_t* config, threadinfo_t* tinfo, times_t* times)
{
unsigned int i;
if (interrupted)
cancel_queries(tinfo);
for (i = 0; i < tinfo->nsocks; i++)
for (i = 0; i < tinfo->nsocks; i++) {
perf_net_stats_compile(config->mode, tinfo->socks[i]);
perf_net_close(tinfo->socks[i]);
}
if (tinfo->last_recv > times->end_time)
times->end_time = tinfo->last_recv;
}
@ -1246,6 +1272,7 @@ int main(int argc, char** argv)
switch (config.mode) {
case sock_tcp:
case sock_dot:
case sock_doh:
// block SIGPIPE for TCP/DOT mode, if connection is closed it will generate a signal
perf_os_blocksignal(SIGPIPE, true);
break;
@ -1296,13 +1323,16 @@ int main(int argc, char** argv)
if (config.stats_interval > 0)
PERF_JOIN(stats_thread.sender, NULL);
perf_net_stats_init(config.mode);
for (i = 0; i < config.threads; i++)
threadinfo_cleanup(&threads[i], &times);
threadinfo_cleanup(&config, &threads[i], &times);
print_final_status(&config);
sum_stats(&config, &total_stats);
print_statistics(&config, &times, &total_stats);
perf_net_stats_print(config.mode);
cleanup(&config);
#if OPENSSL_VERSION_NUMBER < 0x10100000L

View file

@ -39,6 +39,8 @@ enum perf_net_mode perf_net_parsemode(const char* mode)
return sock_tcp;
} else if (!strcmp(mode, "tls") || !strcmp(mode, "dot")) {
return sock_dot;
} else if (!strcmp(mode, "doh")) {
return sock_doh;
}
perf_log_warning("invalid socket mode");
@ -189,7 +191,7 @@ void perf_net_parselocal(int family, const char* name, unsigned int port,
exit(1);
}
struct perf_net_socket* perf_net_opensocket(enum perf_net_mode mode, const perf_sockaddr_t* server, const perf_sockaddr_t* local, unsigned int offset, size_t bufsize)
struct perf_net_socket* perf_net_opensocket(enum perf_net_mode mode, const perf_sockaddr_t* server, const perf_sockaddr_t* local, unsigned int offset, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event)
{
int port;
perf_sockaddr_t tmp;
@ -209,14 +211,46 @@ struct perf_net_socket* perf_net_opensocket(enum perf_net_mode mode, const perf_
switch (mode) {
case sock_udp:
return perf_net_udp_opensocket(server, &tmp, bufsize);
return perf_net_udp_opensocket(server, &tmp, bufsize, data, sent, event);
case sock_tcp:
return perf_net_tcp_opensocket(server, &tmp, bufsize);
return perf_net_tcp_opensocket(server, &tmp, bufsize, data, sent, event);
case sock_dot:
return perf_net_dot_opensocket(server, &tmp, bufsize);
return perf_net_dot_opensocket(server, &tmp, bufsize, data, sent, event);
case sock_doh:
return perf_net_doh_opensocket(server, &tmp, bufsize, data, sent, event);
default:
perf_log_fatal("perf_net_opensocket(): invalid mode");
}
return 0;
}
void perf_net_stats_init(enum perf_net_mode mode)
{
switch (mode) {
case sock_doh:
perf_net_doh_stats_init();
default:
break;
}
}
void perf_net_stats_compile(enum perf_net_mode mode, struct perf_net_socket* sock)
{
switch (mode) {
case sock_doh:
perf_net_doh_stats_compile(sock);
default:
break;
}
}
void perf_net_stats_print(enum perf_net_mode mode)
{
switch (mode) {
case sock_doh:
perf_net_doh_stats_print();
default:
break;
}
}

View file

@ -47,7 +47,8 @@ enum perf_net_mode {
sock_pipe,
sock_udp,
sock_tcp,
sock_dot
sock_dot,
sock_doh
};
struct perf_net_socket;
@ -158,10 +159,25 @@ static inline int perf_sockaddr_isinet6(const perf_sockaddr_t* sockaddr)
return sockaddr->sa.sa.sa_family == AF_INET6;
}
struct perf_net_socket* perf_net_opensocket(enum perf_net_mode mode, const perf_sockaddr_t* server, const perf_sockaddr_t* local, unsigned int offset, size_t bufsize);
struct perf_net_socket* perf_net_opensocket(enum perf_net_mode mode, const perf_sockaddr_t* server, const perf_sockaddr_t* local, unsigned int offset, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
struct perf_net_socket* perf_net_udp_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t);
struct perf_net_socket* perf_net_tcp_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t);
struct perf_net_socket* perf_net_dot_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t);
struct perf_net_socket* perf_net_udp_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
struct perf_net_socket* perf_net_tcp_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
struct perf_net_socket* perf_net_dot_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
struct perf_net_socket* perf_net_doh_opensocket(const perf_sockaddr_t*, const perf_sockaddr_t*, size_t, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event);
#define DEFAULT_DOH_URI "https://localhost/dns-query"
#define DEFAULT_DOH_METHOD "GET"
void perf_net_doh_parse_uri(const char*);
void perf_net_doh_parse_method(const char*);
void perf_net_doh_set_max_concurrent_streams(size_t);
void perf_net_stats_init(enum perf_net_mode);
void perf_net_stats_compile(enum perf_net_mode, struct perf_net_socket*);
void perf_net_stats_print(enum perf_net_mode);
void perf_net_doh_stats_init();
void perf_net_doh_stats_compile(struct perf_net_socket*);
void perf_net_doh_stats_print();
#endif

1017
src/net_doh.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -61,8 +61,6 @@ static void perf__dot_connect(struct perf_net_socket* sock)
{
int ret;
self->is_ready = true;
int fd = socket(self->server.sa.sa.sa_family, SOCK_STREAM, 0);
if (fd == -1) {
char __s[256];
@ -119,12 +117,14 @@ static void perf__dot_connect(struct perf_net_socket* sock)
}
if (connect(sock->fd, &self->server.sa.sa, self->server.length)) {
if (errno == EINPROGRESS) {
self->is_ready = false;
return;
} else {
char __s[256];
perf_log_fatal("connect() failed: %s", perf_strerror_r(errno, __s, sizeof(__s)));
}
}
self->is_conn_ready = true;
}
static void perf__dot_reconnect(struct perf_net_socket* sock)
@ -136,6 +136,7 @@ static void perf__dot_reconnect(struct perf_net_socket* sock)
self->sending = 0;
self->is_sending = false;
}
self->is_ready = false;
self->is_conn_ready = false;
perf__dot_connect(sock);
}
@ -416,7 +417,7 @@ static bool perf__dot_have_more(struct perf_net_socket* sock)
return self->have_more;
}
struct perf_net_socket* perf_net_dot_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize)
struct perf_net_socket* perf_net_dot_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event)
{
struct perf__dot_socket* tmp = calloc(1, sizeof(struct perf__dot_socket)); // clang scan-build
struct perf_net_socket* sock = (struct perf_net_socket*)tmp;
@ -433,6 +434,10 @@ struct perf_net_socket* perf_net_dot_opensocket(const perf_sockaddr_t* server, c
sock->sockready = perf__dot_sockready;
sock->have_more = perf__dot_have_more;
sock->data = data;
sock->sent = sent;
sock->event = event;
self->server = *server;
self->local = *local;
self->bufsize = bufsize;

View file

@ -367,7 +367,7 @@ static bool perf__tcp_have_more(struct perf_net_socket* sock)
return self->have_more;
}
struct perf_net_socket* perf_net_tcp_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize)
struct perf_net_socket* perf_net_tcp_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event)
{
struct perf__tcp_socket* tmp = calloc(1, sizeof(struct perf__tcp_socket)); // clang scan-build
struct perf_net_socket* sock = (struct perf_net_socket*)tmp;
@ -384,6 +384,10 @@ struct perf_net_socket* perf_net_tcp_opensocket(const perf_sockaddr_t* server, c
sock->sockready = perf__tcp_sockready;
sock->have_more = perf__tcp_have_more;
sock->data = data;
sock->sent = sent;
sock->event = event;
self->server = *server;
self->local = *local;
self->bufsize = bufsize;

View file

@ -61,7 +61,7 @@ static int perf__udp_sockready(struct perf_net_socket* sock, int pipe_fd, int64_
return 1;
}
struct perf_net_socket* perf_net_udp_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize)
struct perf_net_socket* perf_net_udp_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event)
{
struct perf__udp_socket* tmp = calloc(1, sizeof(struct perf__udp_socket)); // clang scan-build
struct perf_net_socket* sock = (struct perf_net_socket*)tmp;
@ -79,6 +79,10 @@ struct perf_net_socket* perf_net_udp_opensocket(const perf_sockaddr_t* server, c
sock->sockeq = perf__udp_sockeq;
sock->sockready = perf__udp_sockready;
sock->data = data;
sock->sent = sent;
sock->event = event;
sock->fd = socket(server->sa.sa.sa_family, SOCK_DGRAM, 0);
if (sock->fd == -1) {
char __s[256];

140
src/opt.c
View file

@ -44,7 +44,7 @@ typedef struct {
const char* desc;
const char* help;
const char* defval;
char defvalbuf[32];
char defvalbuf[512];
union {
void* valp;
char** stringp;
@ -56,7 +56,28 @@ typedef struct {
} u;
} opt_t;
typedef struct long_opt long_opt_t;
struct long_opt {
long_opt_t* next;
const char* name;
perf_opttype_t type;
const char* desc;
const char* help;
const char* defval;
char defvalbuf[512];
union {
void* valp;
char** stringp;
bool* boolp;
unsigned int* uintp;
uint64_t* uint64p;
double* doublep;
in_port_t* portp;
} u;
};
static opt_t opts[MAX_OPTS];
static long_opt_t* longopts = 0;
static unsigned int nopts;
static char optstr[MAX_OPTS * 2 + 2 + 1] = { 0 };
extern const char* progname;
@ -76,13 +97,13 @@ void perf_opt_add(char c, perf_opttype_t type, const char* desc, const char* hel
opt->desc = desc;
opt->help = help;
if (defval != NULL) {
opt->defvalbuf[sizeof(opt->defvalbuf) - 1] = 0;
strncpy(opt->defvalbuf, defval, sizeof(opt->defvalbuf));
if (opt->defvalbuf[sizeof(opt->defvalbuf) - 1]) {
if (strlen(defval) > sizeof(opt->defvalbuf) - 1) {
perf_log_fatal("perf_opt_add(): defval too large");
return;
}
opt->defval = opt->defvalbuf;
strncpy(opt->defvalbuf, defval, sizeof(opt->defvalbuf));
opt->defvalbuf[sizeof(opt->defvalbuf) - 1] = 0;
opt->defval = opt->defvalbuf;
} else {
opt->defval = NULL;
}
@ -94,6 +115,37 @@ void perf_opt_add(char c, perf_opttype_t type, const char* desc, const char* hel
optstr[sizeof(optstr) - 1] = 0;
}
void perf_long_opt_add(const char* name, perf_opttype_t type, const char* desc, const char* help, const char* defval, void* valp)
{
long_opt_t* opt = calloc(1, sizeof(long_opt_t));
if (!opt) {
perf_log_fatal("perf_long_opt_add(): out of memory");
return;
}
opt->name = name;
opt->type = type;
opt->desc = desc;
opt->help = help;
if (defval != NULL) {
if (strlen(defval) > sizeof(opt->defvalbuf) - 1) {
perf_log_fatal("perf_opt_add(): defval too large");
free(opt); // fix clang scan-build
return;
}
strncpy(opt->defvalbuf, defval, sizeof(opt->defvalbuf));
opt->defvalbuf[sizeof(opt->defvalbuf) - 1] = 0;
opt->defval = opt->defvalbuf;
} else {
opt->defval = NULL;
}
opt->u.valp = valp;
opt->next = longopts;
longopts = opt;
}
void perf_opt_usage(void)
{
unsigned int prefix_len, position, arg_len, i, j;
@ -181,6 +233,70 @@ parse_timeval(const char* desc, const char* str)
return MILLION * parse_double(desc, str);
}
static int perf_opt_long_parse(char* optarg)
{
ssize_t optlen;
char* arg;
// TODO: Allow boolean not to have =/value
if (!(arg = strchr(optarg, '='))) {
return -1;
}
optlen = arg - optarg;
if (optlen < 1) {
return -1;
}
arg++;
long_opt_t* opt = longopts;
while (opt) {
if (!strncmp(optarg, opt->name, optlen)) {
switch (opt->type) {
case perf_opt_string:
*opt->u.stringp = arg;
break;
case perf_opt_boolean:
*opt->u.boolp = true;
break;
case perf_opt_uint:
*opt->u.uintp = parse_uint(opt->desc, arg, 1, 0xFFFFFFFF);
break;
case perf_opt_zpint:
*opt->u.uintp = parse_uint(opt->desc, arg, 0, 0xFFFFFFFF);
break;
case perf_opt_timeval:
*opt->u.uint64p = parse_timeval(opt->desc, arg);
break;
case perf_opt_double:
*opt->u.doublep = parse_double(opt->desc, arg);
break;
case perf_opt_port:
*opt->u.portp = parse_uint(opt->desc, arg, 0, 0xFFFF);
break;
}
return 0;
}
opt = opt->next;
}
return -1;
}
void perf_long_opt_usage(void)
{
fprintf(stderr, "Usage: %s ... -O <name>=<value> ...\n\nAvailable long options:\n", progname);
long_opt_t* opt = longopts;
while (opt) {
fprintf(stderr, " %s: %s", opt->name, opt->help);
if (opt->defval) {
fprintf(stderr, " (default: %s)", opt->defval);
}
fprintf(stderr, "\n");
opt = opt->next;
}
}
void perf_opt_parse(int argc, char** argv)
{
int c;
@ -188,6 +304,8 @@ void perf_opt_parse(int argc, char** argv)
unsigned int i;
perf_opt_add('h', perf_opt_boolean, NULL, "print this help", NULL, NULL);
perf_opt_add('H', perf_opt_boolean, NULL, "print long options help", NULL, NULL);
perf_opt_add('O', perf_opt_string, NULL, "set long options: <name>=<value>", NULL, NULL);
while ((c = getopt(argc, argv, optstr)) != -1) {
for (i = 0; i < nopts; i++) {
@ -202,6 +320,18 @@ void perf_opt_parse(int argc, char** argv)
perf_opt_usage();
exit(0);
}
if (c == 'H') {
perf_long_opt_usage();
exit(0);
}
if (c == 'O') {
if (perf_opt_long_parse(optarg)) {
fprintf(stderr, "invalid long option: %s\n", optarg);
perf_opt_usage();
exit(1);
}
continue;
}
opt = &opts[i];
switch (opt->type) {
case perf_opt_string:

View file

@ -30,10 +30,11 @@ typedef enum {
perf_opt_port,
} perf_opttype_t;
void perf_opt_add(char c, perf_opttype_t type, const char* desc, const char* help,
const char* defval, void* valp);
void perf_opt_add(char c, perf_opttype_t type, const char* desc, const char* help, const char* defval, void* valp);
void perf_long_opt_add(const char* name, perf_opttype_t type, const char* desc, const char* help, const char* defval, void* valp);
void perf_opt_usage(void);
void perf_long_opt_usage(void);
void perf_opt_parse(int argc, char** argv);

112
src/parse_uri.c Normal file
View file

@ -0,0 +1,112 @@
#include "parse_uri.h"
#include <string.h>
// From: https://github.com/nghttp2/nghttp2/blob/master/examples/client.c
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
int parse_uri(struct URI* res, const char* uri)
{
/* We only interested in https */
size_t len, i, offset;
int ipv6addr = 0;
memset(res, 0, sizeof(struct URI));
len = strlen(uri);
if (len < 9 || memcmp("https://", uri, 8) != 0) {
return -1;
}
offset = 8;
res->host = res->hostport = &uri[offset];
res->hostlen = 0;
if (uri[offset] == '[') {
/* IPv6 literal address */
++offset;
++res->host;
ipv6addr = 1;
for (i = offset; i < len; ++i) {
if (uri[i] == ']') {
res->hostlen = i - offset;
offset = i + 1;
break;
}
}
} else {
const char delims[] = ":/?#";
for (i = offset; i < len; ++i) {
if (strchr(delims, uri[i]) != NULL) {
break;
}
}
res->hostlen = i - offset;
offset = i;
}
if (res->hostlen == 0) {
return -1;
}
/* Assuming https */
res->port = 443;
if (offset < len) {
if (uri[offset] == ':') {
/* port */
const char delims[] = "/?#";
int port = 0;
++offset;
for (i = offset; i < len; ++i) {
if (strchr(delims, uri[i]) != NULL) {
break;
}
if ('0' <= uri[i] && uri[i] <= '9') {
port *= 10;
port += uri[i] - '0';
if (port > 65535) {
return -1;
}
} else {
return -1;
}
}
if (port == 0) {
return -1;
}
offset = i;
res->port = (uint16_t)port;
}
}
res->hostportlen = (size_t)(uri + offset + ipv6addr - res->host);
for (i = offset; i < len; ++i) {
if (uri[i] == '#') {
break;
}
}
if (i - offset == 0) {
res->path = "/";
res->pathlen = 1;
} else {
res->path = &uri[offset];
res->pathlen = i - offset;
}
return 0;
}

41
src/parse_uri.h Normal file
View file

@ -0,0 +1,41 @@
// From: https://github.com/nghttp2/nghttp2/blob/master/examples/client.c
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <inttypes.h>
#include <stdlib.h>
struct URI {
const char* host;
/* In this program, path contains query component as well. */
const char* path;
size_t pathlen;
const char* hostport;
size_t hostlen;
size_t hostportlen;
uint16_t port;
};
int parse_uri(struct URI* res, const char* uri);

View file

@ -44,6 +44,7 @@ resperf \- test the resolution performance of a caching DNS server
[\fB\-F\ \fIfall_behind\fR]
[\fB\-v\fR]
[\fB\-W\fR]
[\fB\-O\ \fIoption=value\fR]
.ad
.hy
.hy 0
@ -74,6 +75,7 @@ resperf \- test the resolution performance of a caching DNS server
[\fB\-F\ \fIfall_behind\fR]
[\fB\-v\fR]
[\fB\-W\fR]
[\fB\-O\ \fIoption=value\fR]
.ad
.hy
.SH DESCRIPTION
@ -413,6 +415,11 @@ itself and the server under test can sustain.
Otherwise, the test is likely to be cut short as a result of either running
out of query IDs (because of large numbers of dropped queries) or of
\fBresperf\fR falling behind its transmission schedule.
.SS "Using DNS-over-HTTPS"
When using DNS-over-HTTPS you must set the \fB-O doh\-uri=...\fR to something
that works with the server you're sending to.
Also note that the value for maximum outstanding queries will be used to
control the maximum concurrent streams within the HTTP/2 connection.
.SH OPTIONS
Because the \fBresperf\-report\fR script passes its command line options
directly to the \fBresperf\fR programs, they both accept the same set of
@ -437,7 +444,7 @@ This allows for long running tests on very small and simple query datafile.
\fB-M \fImode\fR
.br
.RS
Specifies the transport mode to use, "udp", "tcp" or "dot".
Specifies the transport mode to use, "udp", "tcp", "dot" or "doh".
Default is "udp".
.RE
@ -452,7 +459,7 @@ The default is the loopback address, 127.0.0.1.
.br
.RS
Sets the port on which the DNS packets are sent.
If not specified, the standard DNS port (udp/tcp 53, DoT 853) is used.
If not specified, the standard DNS port (udp/tcp 53, DoT 853, DoH 443) is used.
.RE
\fB-a \fIlocal_addr\fR
@ -634,6 +641,14 @@ Enables verbose mode to report about network readiness and congestion.
Log warnings and errors to standard output instead of standard error making
it easier for script, test and automation to capture all output.
.RE
\fB-O \fIoption=value\fR
.br
.RS
Set an extended long option for various things to control different aspects
of testing or protocol modules, see EXTENDED OPTIONS in \fBdnsperf\fR(1) for
list of available options.
.RE
.SH "THE PLOT DATA FILE"
The plot data file is written by the \fBresperf\fR program and contains the
data to be plotted using \fBgnuplot\fR.

View file

@ -53,7 +53,8 @@
#define DEFAULT_SERVER_NAME "127.0.0.1"
#define DEFAULT_SERVER_PORT 53
#define DEFAULT_SERVER_DOT_PORT 853
#define DEFAULT_SERVER_PORTS "udp/tcp 53 or DoT 853"
#define DEFAULT_SERVER_DOH_PORT 443
#define DEFAULT_SERVER_PORTS "udp/tcp 53, DoT 853 or DoH 443"
#define DEFAULT_LOCAL_PORT 0
#define DEFAULT_SOCKET_BUFFER 32
#define DEFAULT_TIMEOUT 45
@ -218,8 +219,23 @@ stringify(double value, int precision)
static void perf__net_event(struct perf_net_socket* sock, perf_socket_event_t event, uint64_t elapsed_time);
static void perf__net_sent(struct perf_net_socket* sock, uint16_t qid);
static void
setup(int argc, char** argv)
static ramp_bucket* init_buckets(int n)
{
ramp_bucket* p;
int i;
if (!(p = calloc(n, sizeof(*p)))) {
perf_log_fatal("out of memory");
return 0; // fix clang scan-build
}
for (i = 0; i < n; i++) {
p[i].queries = p[i].responses = p[i].failures = 0;
p[i].latency_sum = 0.0;
}
return p;
}
static void setup(int argc, char** argv)
{
const char* family = NULL;
const char* server_name = DEFAULT_SERVER_NAME;
@ -233,6 +249,8 @@ setup(int argc, char** argv)
unsigned int i;
const char* _mode = 0;
const char* edns_option_str = NULL;
const char* doh_uri = DEFAULT_DOH_URI;
const char* doh_method = DEFAULT_DOH_METHOD;
sock_family = AF_UNSPEC;
server_port = 0;
@ -251,7 +269,7 @@ setup(int argc, char** argv)
perf_opt_add('f', perf_opt_string, "family",
"address family of DNS transport, inet or inet6", "any",
&family);
perf_opt_add('M', perf_opt_string, "mode", "set transport mode: udp, tcp or dot", "udp", &_mode);
perf_opt_add('M', perf_opt_string, "mode", "set transport mode: udp, tcp, dot or doh", "udp", &_mode);
perf_opt_add('s', perf_opt_string, "server_addr",
"the server to query", DEFAULT_SERVER_NAME, &server_name);
perf_opt_add('p', perf_opt_port, "port",
@ -310,6 +328,10 @@ setup(int argc, char** argv)
perf_opt_add('R', perf_opt_boolean, NULL, "reopen datafile on end, allow for infinit use of it", NULL, &reopen_datafile);
perf_opt_add('F', perf_opt_zpint, "fall_behind", "the maximum number of queries that is allowed to fall behind, zero to disable",
stringify(DEFAULT_MAX_FALL_BEHIND, 0), &max_fall_behind);
perf_long_opt_add("doh-uri", perf_opt_string, "doh_uri",
"the URI to use for DNS-over-HTTPS", DEFAULT_DOH_URI, &doh_uri);
perf_long_opt_add("doh-method", perf_opt_string, "doh_method",
"the HTTP method to use for DNS-over-HTTPS: GET or POST", DEFAULT_DOH_METHOD, &doh_method);
perf_opt_parse(argc, argv);
@ -321,9 +343,27 @@ setup(int argc, char** argv)
mode = perf_net_parsemode(_mode);
if (!server_port) {
server_port = mode == sock_dot ? DEFAULT_SERVER_DOT_PORT : DEFAULT_SERVER_PORT;
switch (mode) {
case sock_doh:
server_port = DEFAULT_SERVER_DOH_PORT;
break;
case sock_dot:
server_port = DEFAULT_SERVER_DOT_PORT;
break;
default:
server_port = DEFAULT_SERVER_PORT;
break;
}
}
if (doh_uri) {
perf_net_doh_parse_uri(doh_uri);
}
if (doh_method) {
perf_net_doh_parse_method(doh_method);
}
perf_net_doh_set_max_concurrent_streams(max_outstanding);
if (max_outstanding > nsocks * DEFAULT_MAX_OUTSTANDING)
perf_log_fatal("number of outstanding packets (%u) must not "
"be more than 64K per client",
@ -364,17 +404,23 @@ setup(int argc, char** argv)
if (edns_option_str != NULL)
edns_option = perf_edns_parseoption(edns_option_str);
traffic_time = ramp_time + sustain_time;
end_time = traffic_time + wait_time;
n_buckets = (traffic_time + bucket_interval - 1) / bucket_interval;
buckets = init_buckets(n_buckets);
time_now = perf_get_time();
time_of_program_start = time_now;
if (!(socks = calloc(nsocks, sizeof(*socks)))) {
perf_log_fatal("out of memory");
}
for (i = 0; i < nsocks; i++) {
socks[i] = perf_net_opensocket(mode, &server_addr, &local_addr, i, bufsize);
socks[i] = perf_net_opensocket(mode, &server_addr, &local_addr, i, bufsize, (void*)(intptr_t)i, perf__net_sent, perf__net_event);
if (!socks[i]) {
perf_log_fatal("perf_net_opensocket(): no socket returned, out of memory?");
}
socks[i]->data = (void*)(intptr_t)i;
socks[i]->sent = perf__net_sent;
socks[i]->event = perf__net_event;
}
}
@ -384,8 +430,10 @@ cleanup(void)
unsigned int i;
perf_datafile_close(&input);
for (i = 0; i < nsocks; i++)
for (i = 0; i < nsocks; i++) {
perf_net_stats_compile(mode, socks[i]);
(void)perf_net_close(socks[i]);
}
close(dummypipe[0]);
close(dummypipe[1]);
@ -499,23 +547,7 @@ print_statistics(void)
}
printf(" Maximum throughput: %.6lf qps\n", max_throughput);
printf(" Lost at that point: %.2f%%\n", loss_at_max_throughput);
}
static ramp_bucket*
init_buckets(int n)
{
ramp_bucket* p;
int i;
if (!(p = calloc(n, sizeof(*p)))) {
perf_log_fatal("out of memory");
return 0; // fix clang scan-build
}
for (i = 0; i < n; i++) {
p[i].queries = p[i].responses = p[i].failures = 0;
p[i].latency_sum = 0.0;
}
return p;
printf("\n");
}
/*
@ -776,6 +808,7 @@ int main(int argc, char** argv)
switch (mode) {
case sock_tcp:
case sock_dot:
case sock_doh:
// block SIGPIPE for TCP/DOT mode, if connection is closed it will generate a signal
perf_os_blocksignal(SIGPIPE, true);
break;
@ -788,15 +821,6 @@ int main(int argc, char** argv)
max_packet_size = edns ? MAX_EDNS_PACKET : MAX_UDP_PACKET;
perf_buffer_init(&msg, outpacket_buffer, max_packet_size);
traffic_time = ramp_time + sustain_time;
end_time = traffic_time + wait_time;
n_buckets = (traffic_time + bucket_interval - 1) / bucket_interval;
buckets = init_buckets(n_buckets);
time_now = perf_get_time();
time_of_program_start = time_now;
printf("[Status] Command line: %s", progname);
for (i = 1; i < argc; i++) {
printf(" %s", argv[i]);
@ -896,7 +920,9 @@ end_loop:
fclose(plotf);
print_statistics();
perf_net_stats_init(mode);
cleanup();
perf_net_stats_print(mode);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
ERR_free_strings();
#endif

View file

@ -441,6 +441,8 @@ libdir = @libdir@
libexecdir = @libexecdir@
libldns_CFLAGS = @libldns_CFLAGS@
libldns_LIBS = @libldns_LIBS@
libnghttp2_CFLAGS = @libnghttp2_CFLAGS@
libnghttp2_LIBS = @libnghttp2_LIBS@
libssl_CFLAGS = @libssl_CFLAGS@
libssl_LIBS = @libssl_LIBS@
localedir = @localedir@

View file

@ -100,6 +100,9 @@ echo " A" | ../dnsperf -W -s 1.1.1.1 \
echo "toooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooolongname" \
| ../dnsperf -W -s 1.1.1.1 -u \
| grep "Unable to parse domain name"
echo "tooooooooooooooooooooooooooooo.oooooooooooooooooooooooo.ooooooooooooooooooooooooooooo.ooooooooooooooooooooooooooooooo.oooooooooooooooooooooooooooooooooooooo.oooooooooooooooooooooooooooo.ooooooooooooooooooooooooo.ooooooooooooooooooooooooooooooooo.oooooooooooooooooooooooooooo.oooooooooooooooooooooooooooooooo.ooooooooooooooooooo.longname" \
| ../dnsperf -W -s 1.1.1.1 -u \
| grep "Unable to parse domain name"
echo -e "test\ndelete toooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooolongname" \
| ../dnsperf -W -s 1.1.1.1 -u \
| grep "invalid update command, domain name too large"

View file

@ -5,13 +5,17 @@ test "$TEST_DNSPERF_WITH_NETWORK" = "1" || exit 0
dumdumd=`which dumdumd`
if [ -n "$dumdumd" ]; then
pkill -9 dumdumd || true
$dumdumd 127.0.0.1 5353 -r -D 100 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 2 -Q 10 -m tcp
kill "$pid"
$dumdumd 127.0.0.1 5353 -r -D 10 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 10 -Q 100 -m tcp
kill "$pid"
@ -20,11 +24,13 @@ if [ -n "$dumdumd" ]; then
$dumdumd 127.0.0.1 5353 -r -T -D 100 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 2 -Q 10 -m dot
kill "$pid"
$dumdumd 127.0.0.1 5353 -r -T -D 10 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 10 -Q 100 -m dot
kill "$pid"

View file

@ -28,6 +28,7 @@
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>
#include <errno.h>
#define MILLION ((uint64_t)1000000)
@ -76,6 +77,19 @@
} \
} while (0)
static inline int PERF_TRYLOCK(pthread_mutex_t* mutex)
{
int __n = pthread_mutex_trylock(mutex);
if (__n == EBUSY) {
return 1;
}
if (__n != 0) {
char __s[256];
perf_log_fatal("pthread_mutex_lock failed: %s", perf_strerror_r(__n, __s, sizeof(__s)));
}
return 0;
}
#define PERF_UNLOCK(mutex) \
do { \
int __n = pthread_mutex_unlock((mutex)); \