2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

Merge branch '2140-dig-netmgr' into 'main'

Resolve "convert dig and friends to use the netmgr"

Closes #2140

See merge request isc-projects/bind9!4115
This commit is contained in:
Evan Hunt
2020-11-08 22:06:04 +00:00
18 changed files with 1070 additions and 1057 deletions

View File

@@ -1,3 +1,8 @@
5528. [func] Convert "dig", "host" and "nslookup" to use the
network manager. As a side effect of this change,
"dig +unexpected" no longer works, and has been
disabled. [GL #2140]
5527. [bug] There was a NULL pointer dereference if the creation
of the fetch to determine if a negative trust anchor
was still valid failed. [GL #2244]

View File

@@ -296,9 +296,6 @@ help(void) {
"in records)\n"
" +[no]ttlunits (Display TTLs in "
"human-readable units)\n"
" +[no]unexpected (Print replies from "
"unexpected sources\n"
" default=off)\n"
" +[no]unknownformat (Print RDATA in RFC 3597 "
"\"unknown\" "
"format)\n"
@@ -555,6 +552,8 @@ printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg,
UNUSED(msgbuf);
dig_idnsetup(query->lookup, true);
styleflags |= DNS_STYLEFLAG_REL_OWNER;
if (yaml) {
msg->indent.string = " ";
@@ -642,7 +641,6 @@ printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg,
if (yaml) {
enum { Q = 0x1, R = 0x2 }; /* Q:query; R:ecursive */
unsigned int tflag = 0;
isc_sockaddr_t saddr;
char sockstr[ISC_SOCKADDR_FORMATSIZE];
uint16_t sport;
char *hash;
@@ -723,10 +721,9 @@ printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg,
printf(" response_port: %u\n", sport);
}
if (query->sock != NULL &&
isc_socket_getsockname(query->sock, &saddr) ==
ISC_R_SUCCESS)
{
if (query->handle != NULL) {
isc_sockaddr_t saddr =
isc_nmhandle_localaddr(query->handle);
sport = isc_sockaddr_getport(&saddr);
isc_sockaddr_format(&saddr, sockstr, sizeof(sockstr));
hash = strchr(sockstr, '#');
@@ -917,6 +914,9 @@ repopulate_buffer:
if (style != NULL) {
dns_master_styledestroy(&style, mctx);
}
dig_idnsetup(query->lookup, false);
return (result);
}
@@ -1809,7 +1809,8 @@ plus_option(char *option, bool is_batchfile, dig_lookup_t *lookup) {
switch (cmd[2]) {
case 'e':
FULLCHECK("unexpected");
lookup->accept_reply_unexpected_src = state;
fprintf(stderr, ";; +unexpected option "
"is deprecated");
break;
case 'k':
FULLCHECK("unknownformat");
@@ -1979,10 +1980,10 @@ dash_option(char *option, char *next, dig_lookup_t **lookup,
srcport = 0;
}
if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) {
isc_sockaddr_fromin6(&bind_address, &in6, srcport);
isc_sockaddr_fromin6(&localaddr, &in6, srcport);
isc_net_disableipv4();
} else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) {
isc_sockaddr_fromin(&bind_address, &in4, srcport);
isc_sockaddr_fromin(&localaddr, &in4, srcport);
isc_net_disableipv6();
} else {
if (hash != NULL) {

View File

@@ -549,11 +549,6 @@ abbreviation is unambiguous; for example, ``+cd`` is equivalent to
units of ``s``, ``m``, ``h``, ``d``, and ``w``, representing seconds, minutes,
hours, days, and weeks. This implies ``+ttlid``.
``+[no]unexpected``
This option accepts [or does not accept] answers from unexpected sources. By default, ``dig``
will not accept a reply from a source other than the one to which it sent the
query.
``+[no]unknownformat``
This option prints all RDATA in unknown RR type presentation format (:rfc:`3597`).
The default is to print RDATA for known types in the type's

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,7 @@
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/sockaddr.h>
#include <isc/socket.h>
@@ -88,12 +89,18 @@ typedef struct dig_server dig_server_t;
typedef ISC_LIST(dig_server_t) dig_serverlist_t;
typedef struct dig_searchlist dig_searchlist_t;
#define DIG_LOOKUP_MAGIC ISC_MAGIC('D', 'i', 'g', 'l')
#define DIG_VALID_LOOKUP(x) ISC_MAGIC_VALID((x), DIG_LOOKUP_MAGIC)
#define DIG_QUERY_MAGIC ISC_MAGIC('D', 'i', 'g', 'q')
#define DIG_VALID_QUERY(x) ISC_MAGIC_VALID((x), DIG_QUERY_MAGIC)
/*% The dig_lookup structure */
struct dig_lookup {
unsigned int magic;
isc_refcount_t references;
bool pending, /*%< Pending a successful answer */
waiting_connect, doing_xfr, ns_search_only, /*%< dig
* +nssearch,
@@ -113,12 +120,9 @@ struct dig_lookup {
tcp_keepalive, header_only, ednsneg, mapped,
print_unknown_format, multiline, nottl, noclass, onesoa,
use_usec, nocrypto, ttlunits, idnin, idnout, expandaaaa, qr,
accept_reply_unexpected_src, /*% print replies from
* unexpected
* sources. */
setqid; /*% use a speciied query ID */
char textname[MXNAME]; /*% Name we're going to be
* looking up */
setqid; /*% use a specified query ID */
char textname[MXNAME]; /*% Name we're going to be
* looking up */
char cmdline[MXNAME];
dns_rdatatype_t rdtype;
dns_rdatatype_t qrdtype;
@@ -170,9 +174,11 @@ struct dig_lookup {
struct dig_query {
unsigned int magic;
dig_lookup_t *lookup;
bool waiting_connect, pending_free, waiting_senddone, first_pass,
first_soa_rcvd, second_rr_rcvd, first_repeat_rcvd, recv_made,
warn_id, timedout;
bool first_pass;
bool first_soa_rcvd;
bool second_rr_rcvd;
bool first_repeat_rcvd;
bool warn_id;
uint32_t first_rr_serial;
uint32_t second_rr_serial;
uint32_t msg_count;
@@ -180,9 +186,12 @@ struct dig_query {
bool ixfr_axfr;
char *servname;
char *userarg;
isc_buffer_t recvbuf, lengthbuf, tmpsendbuf, sendbuf;
isc_buffer_t sendbuf;
char *recvspace, *tmpsendspace, lengthspace[4];
isc_socket_t *sock;
isc_refcount_t references;
isc_nmhandle_t *handle;
isc_nmhandle_t *readhandle;
isc_nmhandle_t *sendhandle;
ISC_LINK(dig_query_t) link;
ISC_LINK(dig_query_t) clink;
isc_sockaddr_t sockaddr;
@@ -190,6 +199,7 @@ struct dig_query {
isc_time_t time_recv;
uint64_t byte_count;
isc_timer_t *timer;
uint8_t tries;
};
struct dig_server {
@@ -220,11 +230,11 @@ extern bool check_ra, have_ipv4, have_ipv6, specified_source, usesearch,
extern in_port_t port;
extern unsigned int timeout;
extern isc_mem_t *mctx;
extern int sendcount;
extern isc_refcount_t sendcount;
extern int ndots;
extern int lookup_counter;
extern int exitcode;
extern isc_sockaddr_t bind_address;
extern isc_sockaddr_t localaddr;
extern char keynametext[MXNAME];
extern char keyfile[MXNAME];
extern char keysecret[MXNAME];
@@ -389,32 +399,38 @@ setup_text_key(void);
* Routines exported from dig.c for use by dig for iOS
*/
/*%<
/*%
* Call once only to set up libraries, parse global
* parameters and initial command line query parameters
*/
void
dig_setup(int argc, char **argv);
/*%<
/*%
* Call to supply new parameters for the next lookup
*/
void
dig_query_setup(bool, bool, int argc, char **argv);
/*%<
/*%
* set the main application event cycle running
*/
void
dig_startup(void);
/*%<
/*%
* Initiates the next lookup cycle
*/
void
dig_query_start(void);
/*%<
/*%
* Activate/deactivate IDN filtering of output.
*/
void
dig_idnsetup(dig_lookup_t *lookup, bool active);
/*%
* Cleans up the application
*/
void

View File

@@ -110,8 +110,6 @@ static const char *rtypetext[] = {
#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
static void
flush_lookup_list(void);
static void
getinput(isc_task_t *task, isc_event_t *event);
@@ -136,7 +134,6 @@ static void
query_finished(void) {
isc_event_t *event = global_event;
flush_lookup_list();
debug("dighost_shutdown()");
if (!in_use) {
@@ -622,6 +619,8 @@ static void
setoption(char *opt) {
size_t l = strlen(opt);
debugging = true;
#define CHECKOPT(A, N) \
((l >= N) && (l < sizeof(A)) && (strncasecmp(opt, A, l) == 0))
@@ -904,46 +903,6 @@ parse_args(int argc, char **argv) {
}
}
static void
flush_lookup_list(void) {
dig_lookup_t *l, *lp;
dig_query_t *q, *qp;
dig_server_t *s, *sp;
lookup_counter = 0;
l = ISC_LIST_HEAD(lookup_list);
while (l != NULL) {
q = ISC_LIST_HEAD(l->q);
while (q != NULL) {
if (q->sock != NULL) {
isc_socket_cancel(q->sock, NULL,
ISC_SOCKCANCEL_ALL);
isc_socket_detach(&q->sock);
}
isc_buffer_invalidate(&q->recvbuf);
isc_buffer_invalidate(&q->lengthbuf);
qp = q;
q = ISC_LIST_NEXT(q, link);
ISC_LIST_DEQUEUE(l->q, qp, link);
isc_mem_free(mctx, qp);
}
s = ISC_LIST_HEAD(l->my_server_list);
while (s != NULL) {
sp = s;
s = ISC_LIST_NEXT(s, link);
ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
isc_mem_free(mctx, sp);
}
if (l->sendmsg != NULL) {
dns_message_detach(&l->sendmsg);
}
lp = l;
l = ISC_LIST_NEXT(l, link);
ISC_LIST_DEQUEUE(lookup_list, lp, link);
isc_mem_free(mctx, lp);
}
}
static void
getinput(isc_task_t *task, isc_event_t *event) {
UNUSED(task);

View File

@@ -82,7 +82,7 @@ if [ -x "$NSLOOKUP" -a $checkupdate -eq 1 ] ; then
n=$((n+1))
echo_i "check nslookup handles UPDATE response ($n)"
ret=0
"$NSLOOKUP" -q=CNAME "-port=$PORT" foo.bar 10.53.0.7 > nslookup.out.test$n 2>&1 && ret=1
"$NSLOOKUP" -q=CNAME -timeout=1 "-port=$PORT" foo.bar 10.53.0.7 > nslookup.out.test$n 2>&1 && ret=1
grep "Opcode mismatch" nslookup.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
@@ -94,7 +94,7 @@ if [ -x "$HOST" -a $checkupdate -eq 1 ] ; then
n=$((n+1))
echo_i "check host handles UPDATE response ($n)"
ret=0
"$HOST" -t CNAME -p $PORT foo.bar 10.53.0.7 > host.out.test$n 2>&1 && ret=1
"$HOST" -W 1 -t CNAME -p $PORT foo.bar 10.53.0.7 > host.out.test$n 2>&1 && ret=1
grep "Opcode mismatch" host.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
@@ -108,7 +108,7 @@ if [ -x "$DIG" ] ; then
n=$((n+1))
echo_i "check dig handles UPDATE response ($n)"
ret=0
dig_with_opts @10.53.0.7 cname foo.bar > dig.out.test$n 2>&1 && ret=1
dig_with_opts @10.53.0.7 +tries=1 +timeout=1 cname foo.bar > dig.out.test$n 2>&1 && ret=1
grep "Opcode mismatch" dig.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
@@ -919,33 +919,6 @@ if [ -x "$DIG" ] ; then
status=$((status+ret))
fi
n=$((n+1))
echo_i "check that dig +unexpected works ($n)"
ret=0
dig_with_opts @10.53.0.6 +unexpected a a.example > dig.out.test$n || ret=1
grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "check that dig +nounexpected works ($n)"
ret=0
dig_with_opts @10.53.0.6 +nounexpected +tries=1 +time=2 a a.example > dig.out.test$n && ret=1
grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
grep "status: NOERROR" < dig.out.test$n > /dev/null && ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "check that dig default for +[no]unexpected (+nounexpected) works ($n)"
ret=0
dig_with_opts @10.53.0.6 +tries=1 +time=2 a a.example > dig.out.test$n && ret=1
grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
grep "status: NOERROR" < dig.out.test$n > /dev/null && ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "check that dig +bufsize=0 just sets the buffer size to 0 ($n)"
ret=0

View File

@@ -805,7 +805,7 @@ status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that the resolver accepts a reply with empty question section with TC=1 and retries over TCP ($n)"
ret=0
$DIG $DIGOPTS @10.53.0.5 truncated.no-questions. a +tries=3 +time=5 > dig.ns5.out.${n} || ret=1
$DIG $DIGOPTS @10.53.0.5 truncated.no-questions. a +tries=3 +time=4 > dig.ns5.out.${n} || ret=1
grep "status: NOERROR" dig.ns5.out.${n} > /dev/null || ret=1
grep "ANSWER: 1," dig.ns5.out.${n} > /dev/null || ret=1
grep "1\.2\.3\.4" dig.ns5.out.${n} > /dev/null || ret=1
@@ -815,7 +815,7 @@ status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that the resolver rejects a reply with empty question section with TC=0 ($n)"
ret=0
$DIG $DIGOPTS @10.53.0.5 not-truncated.no-questions. a +tries=3 +time=5 > dig.ns5.out.${n} || ret=1
$DIG $DIGOPTS @10.53.0.5 not-truncated.no-questions. a +tries=3 +time=4 > dig.ns5.out.${n} || ret=1
grep "status: NOERROR" dig.ns5.out.${n} > /dev/null && ret=1
grep "ANSWER: 1," dig.ns5.out.${n} > /dev/null && ret=1
grep "1\.2\.3\.4" dig.ns5.out.${n} > /dev/null && ret=1

View File

@@ -13,14 +13,16 @@
RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
# wait up to ten seconds to ensure that a file has been written
# wait up to 11 seconds to ensure that a file has been written
waitfile () {
for try in 0 1 2 3 4 5 6 7 8 9; do
for try in 0 1 2 3 4 5 6 7 8 9 10; do
[ -s "$1" ] && break
sleep 1
done
}
DIG="$DIG +time=11"
max_stale_ttl=$(sed -ne 's,^[[:space:]]*max-stale-ttl \([[:digit:]]*\).*,\1,p' $TOP_SRCDIR/bin/named/config.c)
status=0

View File

@@ -561,11 +561,6 @@ This option displays [or does not display] the TTL in friendly human\-readable t
units of \fBs\fP, \fBm\fP, \fBh\fP, \fBd\fP, and \fBw\fP, representing seconds, minutes,
hours, days, and weeks. This implies \fB+ttlid\fP\&.
.TP
.B \fB+[no]unexpected\fP
This option accepts [or does not accept] answers from unexpected sources. By default, \fBdig\fP
will not accept a reply from a source other than the one to which it sent the
query.
.TP
.B \fB+[no]unknownformat\fP
This option prints all RDATA in unknown RR type presentation format (\fI\%RFC 3597\fP).
The default is to print RDATA for known types in the type\(aqs

View File

@@ -36,6 +36,16 @@ Feature Changes
- None.
- The ``dig``, ``host``, and ``nslookup`` tools have been converted to
use the new network manager API rather than the older ISC socket API.
As a side effect of this change, the ``dig +unexpected`` option no longer
works. This could previously be used for diagnosing broken servers or
network configurations by listening for replies from servers other than
the one that was queried. With the new API such answers are filtered
before they ever reach ``dig``. Consequently, the option has been
removed. [GL #2140]
Bug Fixes
~~~~~~~~~

View File

@@ -135,16 +135,27 @@ isc_nmhandle_getextra(isc_nmhandle_t *handle);
bool
isc_nmhandle_is_stream(isc_nmhandle_t *handle);
/*
* isc_nmhandle_t has a void * opaque field (usually - ns_client_t).
void
isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg,
isc_nm_opaquecb_t doreset, isc_nm_opaquecb_t dofree);
/*%<
* isc_nmhandle_t has a void* opaque field (for example, ns_client_t).
* We reuse handle and `opaque` can also be reused between calls.
* This function sets this field and two callbacks:
* - doreset resets the `opaque` to initial state
* - dofree frees everything associated with `opaque`
*/
void
isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg,
isc_nm_opaquecb_t doreset, isc_nm_opaquecb_t dofree);
isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
/*%<
* Set the read/recv timeout for the socket connected to 'handle'
* to 'timeout', and reset the timer.
*
* When this is called on a 'wrapper' socket handle (for example,
* a TCPDNS socket wrapping a TCP connection), the timer is set for
* both socket layers.
*/
isc_sockaddr_t
isc_nmhandle_peeraddr(isc_nmhandle_t *handle);
@@ -359,9 +370,9 @@ isc_nm_tcpdns_sequential(isc_nmhandle_t *handle);
*/
void
isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle);
isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle, bool value);
/*%<
* Enable keepalive on this connection.
* Enable/disable keepalive on this connection by setting it to 'value'.
*
* When keepalive is active, we switch to using the keepalive timeout
* to determine when to close a connection, rather than the idle timeout.

View File

@@ -748,6 +748,15 @@ isc__nm_udp_shutdown(isc_nmsocket_t *sock);
void
isc__nm_udp_stoplistening(isc_nmsocket_t *sock);
/*%<
* Stop listening on 'sock'.
*/
void
isc__nm_udp_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
/*%<
* Set the recv timeout for the UDP socket associated with 'handle'.
*/
void
isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0);
@@ -813,6 +822,15 @@ isc__nm_tcp_cancelread(isc_nmhandle_t *handle);
void
isc__nm_tcp_stoplistening(isc_nmsocket_t *sock);
/*%<
* Stop listening on 'sock'.
*/
void
isc__nm_tcp_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
/*%<
* Set the read timeout for the TCP socket associated with 'handle'.
*/
void
isc__nm_async_tcpconnect(isc__networker_t *worker, isc__netievent_t *ev0);
@@ -858,6 +876,16 @@ isc__nm_tcpdns_close(isc_nmsocket_t *sock);
void
isc__nm_tcpdns_stoplistening(isc_nmsocket_t *sock);
/*%<
* Stop listening on 'sock'.
*/
void
isc__nm_tcpdns_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
/*%<
* Set the read timeout and reset the timer for the TCPDNS socket
* associated with 'handle', and the TCP socket it wraps around.
*/
void
isc__nm_async_tcpdnscancel(isc__networker_t *worker, isc__netievent_t *ev0);
@@ -922,6 +950,12 @@ isc__nm_decstats(isc_nm_t *mgr, isc_statscounter_t counterid);
* Decrement socket-related statistics counters.
*/
isc_result_t
isc__nm_socket(int domain, int type, int protocol, uv_os_sock_t *sockp);
/*%<
* Platform independent socket() version
*/
isc_result_t
isc__nm_socket_freebind(uv_os_sock_t fd, sa_family_t sa_family);
/*%<

View File

@@ -16,6 +16,7 @@
#include <isc/atomic.h>
#include <isc/buffer.h>
#include <isc/condition.h>
#include <isc/errno.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/netmgr.h>
@@ -27,6 +28,7 @@
#include <isc/result.h>
#include <isc/sockaddr.h>
#include <isc/stats.h>
#include <isc/strerr.h>
#include <isc/thread.h>
#include <isc/util.h>
@@ -1206,7 +1208,8 @@ isc__nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
UNLOCK(&sock->lock);
if (sock->type == isc_nm_tcpsocket ||
(sock->type == isc_nm_udpsocket && atomic_load(&sock->client)))
(sock->type == isc_nm_udpsocket && atomic_load(&sock->client)) ||
(sock->type == isc_nm_tcpdnssocket && atomic_load(&sock->client)))
{
INSIST(sock->statichandle == NULL);
@@ -1384,6 +1387,26 @@ isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg,
handle->dofree = dofree;
}
void
isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
REQUIRE(VALID_NMHANDLE(handle));
switch (handle->sock->type) {
case isc_nm_udpsocket:
isc__nm_udp_settimeout(handle, timeout);
break;
case isc_nm_tcpsocket:
isc__nm_tcp_settimeout(handle, timeout);
break;
case isc_nm_tcpdnssocket:
isc__nm_tcpdns_settimeout(handle, timeout);
break;
default:
INSIST(0);
ISC_UNREACHABLE();
}
}
void *
isc_nmhandle_getextra(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
@@ -1701,6 +1724,40 @@ isc__nm_decstats(isc_nm_t *mgr, isc_statscounter_t counterid) {
}
}
isc_result_t
isc__nm_socket(int domain, int type, int protocol, uv_os_sock_t *sockp) {
#ifdef WIN32
SOCKET sock;
sock = socket(domain, type, protocol);
if (sock == INVALID_SOCKET) {
char strbuf[ISC_STRERRORSIZE];
DWORD socket_errno = WSAGetLastError();
switch (socket_errno) {
case WSAEMFILE:
case WSAENOBUFS:
return (ISC_R_NORESOURCES);
case WSAEPROTONOSUPPORT:
case WSAEPFNOSUPPORT:
case WSAEAFNOSUPPORT:
return (ISC_R_FAMILYNOSUPPORT);
default:
strerror_r(socket_errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"socket() failed: %s", strbuf);
return (ISC_R_UNEXPECTED);
}
}
#else
int sock = socket(domain, type, protocol);
if (sock < 0) {
return (isc_errno_toresult(errno));
}
#endif
*sockp = (uv_os_sock_t)sock;
return (ISC_R_SUCCESS);
}
#define setsockopt_on(socket, level, name) \
setsockopt(socket, level, name, &(int){ 1 }, sizeof(int))

View File

@@ -813,6 +813,10 @@ isc__nm_tcp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
sock->recv_cb = cb;
sock->recv_cbarg = cbarg;
sock->read_timeout = (atomic_load(&sock->keepalive)
? sock->mgr->keepalive
: sock->mgr->idle);
ievent = isc__nm_get_ievent(sock->mgr, netievent_tcpstartread);
ievent->sock = sock;
@@ -885,9 +889,9 @@ isc__nm_async_tcp_startread(isc__networker_t *worker, isc__netievent_t *ev0) {
if (sock->read_timeout != 0) {
if (!sock->timer_initialized) {
uv_timer_init(&worker->loop, &sock->timer);
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
sock->timer_initialized = true;
}
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
uv_timer_start(&sock->timer, readtimeout_cb, sock->read_timeout,
0);
sock->timer_running = true;
@@ -987,10 +991,6 @@ read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
cb(sock->statichandle, ISC_R_SUCCESS, &region, cbarg);
}
sock->read_timeout = (atomic_load(&sock->keepalive)
? sock->mgr->keepalive
: sock->mgr->idle);
if (sock->timer_initialized && sock->read_timeout != 0) {
/* The timer will be updated */
uv_timer_start(&sock->timer, readtimeout_cb,
@@ -1471,3 +1471,18 @@ isc__nm_async_tcpcancel(isc__networker_t *worker, isc__netievent_t *ev0) {
isc_nmhandle_detach(&handle);
}
void
isc__nm_tcp_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
isc_nmsocket_t *sock = NULL;
REQUIRE(VALID_NMHANDLE(handle));
sock = handle->sock;
sock->read_timeout = timeout;
if (sock->timer_running) {
uv_timer_start(&sock->timer, readtimeout_cb, sock->read_timeout,
0);
}
}

View File

@@ -470,7 +470,7 @@ isc_nm_tcpdns_sequential(isc_nmhandle_t *handle) {
}
void
isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle) {
isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle, bool value) {
REQUIRE(VALID_NMHANDLE(handle));
if (handle->sock->type != isc_nm_tcpdnssocket ||
@@ -479,8 +479,8 @@ isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle) {
return;
}
atomic_store(&handle->sock->keepalive, true);
atomic_store(&handle->sock->outerhandle->sock->keepalive, true);
atomic_store(&handle->sock->keepalive, value);
atomic_store(&handle->sock->outerhandle->sock->keepalive, value);
}
static void
@@ -736,6 +736,7 @@ tcpdnsconnect_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
void *cbarg = conn->cbarg;
size_t extrahandlesize = conn->extrahandlesize;
isc_nmsocket_t *dnssock = NULL;
isc_nmhandle_t *readhandle = NULL;
REQUIRE(result != ISC_R_SUCCESS || VALID_NMHANDLE(handle));
@@ -758,7 +759,13 @@ tcpdnsconnect_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
dnssock->tid = isc_nm_tid();
atomic_init(&dnssock->client, true);
dnssock->statichandle = isc__nmhandle_get(dnssock, NULL, NULL);
readhandle = isc__nmhandle_get(dnssock, NULL, NULL);
INSIST(dnssock->statichandle != NULL);
INSIST(dnssock->statichandle == readhandle);
INSIST(readhandle->sock == dnssock);
INSIST(dnssock->recv_cb == NULL);
uv_timer_init(&dnssock->mgr->workers[isc_nm_tid()].loop,
&dnssock->timer);
@@ -774,7 +781,11 @@ tcpdnsconnect_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
* packet.
*/
isc_nm_read(handle, dnslisten_readcb, dnssock);
cb(dnssock->statichandle, ISC_R_SUCCESS, cbarg);
cb(readhandle, ISC_R_SUCCESS, cbarg);
/*
* The sock is now attached to the handle.
*/
isc__nmsocket_detach(&dnssock);
}
@@ -820,6 +831,10 @@ isc__nm_tcpdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
sock->recv_cb = cb;
sock->recv_cbarg = cbarg;
sock->read_timeout = (atomic_load(&sock->keepalive)
? sock->mgr->keepalive
: sock->mgr->idle);
/*
* Add a reference to the handle to keep it from being freed by
* the caller; it will be detached in in isc__nm_async_tcpdnsread().
@@ -932,3 +947,22 @@ isc__nm_async_tcpdnscancel(isc__networker_t *worker, isc__netievent_t *ev0) {
isc_nmhandle_detach(&handle);
}
void
isc__nm_tcpdns_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
isc_nmsocket_t *sock = NULL;
REQUIRE(VALID_NMHANDLE(handle));
sock = handle->sock;
if (sock->outerhandle != NULL) {
isc__nm_tcp_settimeout(sock->outerhandle, timeout);
}
sock->read_timeout = timeout;
if (sock->timer_running) {
uv_timer_start(&sock->timer, dnstcp_readtimeout,
sock->read_timeout, 0);
}
}

View File

@@ -93,8 +93,8 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
INSIST(csock->recv_cb == NULL && csock->recv_cbarg == NULL);
csock->recv_cb = cb;
csock->recv_cbarg = cbarg;
csock->fd = socket(sa_family, SOCK_DGRAM, 0);
RUNTIME_CHECK(csock->fd >= 0);
result = isc__nm_socket(sa_family, SOCK_DGRAM, 0, &csock->fd);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = isc__nm_socket_reuse(csock->fd);
RUNTIME_CHECK(result == ISC_R_SUCCESS ||
@@ -368,6 +368,7 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
if (addr == NULL) {
goto done;
}
/*
* - If we're simulating a firewall blocking UDP packets
* bigger than 'maxudp' bytes for testing purposes.
@@ -376,6 +377,7 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
if ((maxudp != 0 && (uint32_t)nrecv > maxudp)) {
goto done;
}
/*
* - If the socket is no longer active.
*/
@@ -389,6 +391,11 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
cb = sock->recv_cb;
cbarg = sock->recv_cbarg;
if (sock->timer_running) {
uv_timer_stop(&sock->timer);
sock->timer_running = false;
}
if (atomic_load(&sock->client)) {
if (nrecv < 0) {
failed_read_cb(sock, isc__nm_uverr2result(nrecv));
@@ -765,6 +772,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
isc__netievent_udpconnect_t *event = NULL;
isc__nm_uvreq_t *req = NULL;
sa_family_t sa_family;
uv_os_sock_t fd;
REQUIRE(VALID_NM(mgr));
REQUIRE(local != NULL);
@@ -772,6 +780,15 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
sa_family = peer->addr.type.sa.sa_family;
/*
* The socket() call can fail spuriously on FreeBSD 12, so we need to
* handle the failure early and gracefully.
*/
result = isc__nm_socket(sa_family, SOCK_DGRAM, 0, &fd);
if (result != ISC_R_SUCCESS) {
return (result);
}
sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t));
isc__nmsocket_init(sock, mgr, isc_nm_udpsocket, local);
@@ -781,11 +798,9 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
sock->read_timeout = timeout;
sock->extrahandlesize = extrahandlesize;
sock->peer = peer->addr;
sock->fd = fd;
atomic_init(&sock->client, true);
sock->fd = socket(sa_family, SOCK_DGRAM, 0);
RUNTIME_CHECK(sock->fd >= 0);
result = isc__nm_socket_reuse(sock->fd);
RUNTIME_CHECK(result == ISC_R_SUCCESS ||
result == ISC_R_NOTIMPLEMENTED);
@@ -834,9 +849,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
isc__nm_uvreq_put(&req, sock);
}
if (atomic_load(&sock->result) != ISC_R_SUCCESS) {
result = atomic_load(&sock->result);
}
result = atomic_load(&sock->result);
isc__nmsocket_detach(&tmp);
@@ -848,10 +861,6 @@ udp_read_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
const struct sockaddr *addr, unsigned flags) {
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)handle);
if (sock->timer_running) {
uv_timer_stop(&sock->timer);
sock->timer_running = false;
}
udp_recv_cb(handle, nrecv, buf, addr, flags);
uv_udp_recv_stop(&sock->uv_handle.udp);
}
@@ -1146,3 +1155,18 @@ isc__nm_async_udpcancel(isc__networker_t *worker, isc__netievent_t *ev0) {
isc_nmhandle_detach(&handle);
}
void
isc__nm_udp_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
isc_nmsocket_t *sock = NULL;
REQUIRE(VALID_NMHANDLE(handle));
sock = handle->sock;
sock->read_timeout = timeout;
if (sock->timer_running) {
uv_timer_start(&sock->timer, readtimeout_cb, sock->read_timeout,
0);
}
}

View File

@@ -443,6 +443,7 @@ isc_nmhandle_netmgr
isc_nmhandle_localaddr
isc_nmhandle_peeraddr
isc_nmhandle_setdata
isc_nmhandle_settimeout
isc_nm_cancelread
isc_nm_closedown
isc_nm_destroy