summaryrefslogtreecommitdiffstats
path: root/rfc1035/rfc1035resolve.c
diff options
context:
space:
mode:
authorSam Varshavchik2020-04-21 21:58:36 -0400
committerSam Varshavchik2020-04-21 22:46:40 -0400
commit33fcb84fa5dc2aecb85930d71aeeafb49d66a85a (patch)
treefab18b80d795ecb590403b05fef3352ad2f0e07b /rfc1035/rfc1035resolve.c
parent74eb9fac379104c0e326ebff60a4af7dc15359cc (diff)
downloadcourier-libs-33fcb84fa5dc2aecb85930d71aeeafb49d66a85a.tar.bz2
Use parallel queries in rfc1035_resolve_multiple.
Diffstat (limited to 'rfc1035/rfc1035resolve.c')
-rw-r--r--rfc1035/rfc1035resolve.c147
1 files changed, 95 insertions, 52 deletions
diff --git a/rfc1035/rfc1035resolve.c b/rfc1035/rfc1035resolve.c
index 6ba95fc..b875d05 100644
--- a/rfc1035/rfc1035resolve.c
+++ b/rfc1035/rfc1035resolve.c
@@ -84,8 +84,7 @@ struct rfc1035_reply
static struct rfc1035_reply
*rfc1035_resolve_multiple_attempt(struct rfc1035_res *res,
- int opcode,
- struct querybuf *qbuf,
+ struct rfc1035_udp_query_responses *resps,
int udpfd,
int af,
const RFC1035_ADDR *sin,
@@ -93,8 +92,8 @@ static struct rfc1035_reply
static struct rfc1035_reply
*rfc1035_resolve_multiple_attempt_tcp(struct rfc1035_res *res,
- int opcode,
- struct querybuf *qbuf,
+ char const*query,
+ unsigned querylen,
int af,
const RFC1035_ADDR *sin,
int isaxfr,
@@ -106,9 +105,9 @@ static struct rfc1035_reply
const struct rfc1035_query *queries,
unsigned nqueries)
{
- struct querybuf qbuf;
+ struct querybuf qbuf[nqueries];
int udpfd;
- int attempt;
+ unsigned attempt;
const RFC1035_ADDR *ns;
unsigned nscount;
unsigned current_timeout, timeout_backoff;
@@ -116,6 +115,7 @@ static struct rfc1035_reply
int af;
unsigned i;
int isaxfr=0;
+ struct rfc1035_udp_query_responses *resps=0;
struct rfc1035_reply *rfcreply=0;
static const char fakereply[]={0, 0, 0, RFC1035_RCODE_SERVFAIL,
@@ -130,20 +130,21 @@ static struct rfc1035_reply
if (res->rfc1035_good_ns >= nscount)
res->rfc1035_good_ns=0;
- qbuf.qbuflen=0;
- if ( rfc1035_mkquery(res,
- opcode, queries, nqueries, &putqbuf, &qbuf))
- {
- errno=EINVAL;
- return (0);
- }
-
for (i=0; i<nqueries; i++)
+ {
+ qbuf[i].qbuflen=0;
+ if ( rfc1035_mkquery(res,
+ opcode, &queries[i], 1, &putqbuf, &qbuf[i]))
+ {
+ errno=EINVAL;
+ return (0);
+ }
if (queries[i].qtype == RFC1035_TYPE_AXFR)
{
isaxfr=1;
break;
}
+ }
if (isaxfr && nqueries > 1)
return rfc1035_replyparse(fakereply, sizeof(fakereply));
@@ -152,6 +153,11 @@ static struct rfc1035_reply
if ((udpfd=rfc1035_open_udp(&af)) < 0) return (0);
+ /* Prepare responses array for multple queries */
+
+ if (!isaxfr)
+ resps=rfc1035_udp_query_response_alloc_bis(qbuf, nqueries);
+
/* Keep trying until we get an answer from a nameserver */
current_timeout=res->rfc1035_timeout_initial;
@@ -172,16 +178,15 @@ static struct rfc1035_reply
rfcreply=isaxfr ?
rfc1035_resolve_multiple_attempt_tcp
(res,
- opcode,
- &qbuf,
+ qbuf[0].qbuf,
+ qbuf[0].qbuflen,
af,
sin,
1,
current_timeout)
: rfc1035_resolve_multiple_attempt
(res,
- opcode,
- &qbuf,
+ resps,
udpfd,
af,
sin,
@@ -202,6 +207,9 @@ static struct rfc1035_reply
sox_close(udpfd);
+ if (resps)
+ rfc1035_udp_query_response_free(resps);
+
if (!rfcreply)
rfcreply=rfc1035_replyparse(fakereply, sizeof(fakereply));
@@ -210,21 +218,19 @@ static struct rfc1035_reply
static struct rfc1035_reply
*rfc1035_resolve_multiple_attempt(struct rfc1035_res *res,
- int opcode,
- struct querybuf *qbuf,
+ struct rfc1035_udp_query_responses *resps,
int udpfd,
int af,
const RFC1035_ADDR *sin,
unsigned current_timeout)
{
- int nbytes;
- char *reply;
- struct rfc1035_reply *rfcreply=0;
-
+ struct rfc1035_reply *rfcreply=0, **rfcpp=&rfcreply;
int sin_len=sizeof(*sin);
-
int dotcp=0;
+ unsigned n, nqueries=resps->n_queries;
+ if (!resps)
+ return NULL;
if (!dotcp)
{
@@ -238,50 +244,87 @@ static struct rfc1035_reply
&addrptr, &addrptrlen))
return NULL;
- if ((reply=rfc1035_query_udp(res, udpfd, addrptr,
- addrptrlen, qbuf->qbuf, qbuf->qbuflen, &nbytes,
- current_timeout)) == 0)
+ if (rfc1035_udp_query_multi(res, udpfd, addrptr,
+ addrptrlen, resps, current_timeout) == 0)
return NULL;
- /* Parse the reply */
+ /* Parse the replies */
- rfcreply=rfc1035_replyparse(reply, nbytes);
- if (!rfcreply)
+ for (n = 0; n < nqueries; ++n)
{
- free(reply);
- return NULL;
- /* Bad response from the server, try the next one. */
+ struct rfc1035_udp_query_response *reply=&resps->queries[n];
+ if (!reply->response)
+ break; // How come? rfc1035_udp_query_multi succeeded...
+
+ *rfcpp=rfc1035_replyparse(reply->response, reply->resplen);
+ if (!*rfcpp)
+ {
+ free(reply->response); // possibly unparseable
+ reply->response=0;
+ break;
+ }
+
+ if ((*rfcpp)->tc)
+ dotcp=1;
+ (*rfcpp)->mallocedbuf=reply->response;
+ reply->response=0;
+ rfcpp=&(*rfcpp)->next;
}
- rfcreply->mallocedbuf=reply;
- /*
- ** If the reply came back with the truncated bit set,
- ** retry the query via TCP.
- */
- if (rfcreply->tc)
+ if (n < nqueries)
{
- dotcp=1;
- rfc1035_replyfree(rfcreply);
+ if (rfcreply)
+ rfc1035_replyfree(rfcreply);
+ return NULL;
}
}
if (dotcp)
{
- rfcreply=rfc1035_resolve_multiple_attempt_tcp
- (res, opcode, qbuf, af, sin, 0,
- current_timeout);
- if (!rfcreply)
- return NULL;
+ n = 0;
+ for (rfcpp=&rfcreply; *rfcpp; rfcpp=&(*rfcpp)->next, ++n)
+ {
+ /*
+ * UDP replies are all in, some were truncated.
+ */
+ if ((*rfcpp)->tc)
+ {
+ struct rfc1035_reply *next=(*rfcpp)->next, *newrfc;
+ struct rfc1035_udp_query_response *reply=&resps->queries[n];
+
+ newrfc=rfc1035_resolve_multiple_attempt_tcp(res,
+ reply->query, reply->querylen,
+ af, sin, 0, current_timeout);
+ if (!newrfc)
+ break;
+
+ /*
+ * Replace the truncated reply in the linked list
+ */
+ (*rfcpp)->next=0; // only free this
+ rfc1035_replyfree(*rfcpp);
+ *rfcpp=newrfc;
+ (*rfcpp)->next=next;
+ }
+ }
+
+ if (n < nqueries && rfcreply)
+ {
+ rfc1035_replyfree(rfcreply);
+ rfcreply=0;
+ }
}
- memcpy(&rfcreply->server_addr, sin, sin_len);
+ if (rfcreply)
+ memcpy(&rfcreply->server_addr, sin, sin_len);
+
return (rfcreply);
}
static struct rfc1035_reply
*rfc1035_resolve_multiple_attempt_tcp(struct rfc1035_res *res,
- int opcode,
- struct querybuf *qbuf,
+ char const*query,
+ unsigned querylen,
int af,
const RFC1035_ADDR *sin,
int isaxfr,
@@ -308,8 +351,8 @@ static struct rfc1035_reply
** try the next server.
*/
- reply=rfc1035_query_tcp(res, tcpfd, qbuf->qbuf,
- qbuf->qbuflen, &nbytes, current_timeout);
+ reply=rfc1035_query_tcp(res, tcpfd, query,
+ querylen, &nbytes, current_timeout);
if (!reply)
{