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:
5
CHANGES
5
CHANGES
@@ -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]
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
1705
bin/dig/dighost.c
1705
bin/dig/dighost.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
~~~~~~~~~
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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);
|
||||
/*%<
|
||||
|
@@ -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))
|
||||
|
||||
|
@@ -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, ®ion, 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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user