resolved-dns-query.c revision b9d394ea565fd742bcdd34e8dd61ae07c58a9565
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "resolved-dns-query.h"
#include "resolved-dns-domain.h"
#define ATTEMPTS_MAX 8
if (!t)
return NULL;
dns_packet_unref(t->packet);
if (t->query) {
}
if (t->scope)
free(t);
return NULL;
}
int r;
assert(q);
assert(s);
if (r < 0)
return r;
if (!t)
return -ENOMEM;
do
while (t->id == 0 ||
if (r < 0) {
t->id = 0;
return r;
}
t->query = q;
t->scope = s;
if (ret)
*ret = t;
t = NULL;
return 0;
}
assert(t);
return;
if (state != DNS_QUERY_SENT)
dns_query_finish(t->query);
}
assert(t);
assert(p);
t->packet = dns_packet_ref(p);
if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
else
return 0;
}
DnsQueryTransaction *t = userdata;
int r;
assert(s);
assert(t);
/* Timeout reached? Try again, with a new server */
r = dns_query_transaction_start(t);
if (r < 0)
return 0;
}
unsigned n;
int r;
assert(t);
if (t->n_attempts >= ATTEMPTS_MAX) {
return 0;
}
t->n_attempts++;
r = dns_packet_new_query(&p, 0);
if (r < 0)
return r;
if (r < 0)
return r;
}
r = dns_scope_send(t->scope, p);
if (r < 0) {
/* Couldn't send? Try immediately again, with a new server */
return dns_query_transaction_start(t);
}
if (r > 0) {
int q;
q = sd_event_add_time(t->query->manager->event, &t->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + TRANSACTION_TIMEOUT_USEC, 0, on_transaction_timeout, t);
if (q < 0)
return q;
} else
return r;
}
unsigned n;
if (!q)
return NULL;
dns_packet_unref(q->packet);
while (q->transactions)
if (q->manager)
for (n = 0; n < q->n_keys; n++)
free(q);
return NULL;
}
int n, r;
assert(m);
return -EINVAL;
if (!q)
return -ENOMEM;
if (!q->keys)
return -ENOMEM;
return -ENOMEM;
if (!name)
return -EINVAL;
}
q->manager = m;
if (match < 0)
return match;
if (match == DNS_SCOPE_NO)
continue;
if (match == DNS_SCOPE_YES) {
first = s;
break;
} else {
if (!first)
first = s;
}
}
if (found == DNS_SCOPE_NO)
return -ENETDOWN;
if (r < 0)
return r;
n = 1;
if (match < 0)
return match;
continue;
r = dns_query_transaction_new(q, NULL, s);
if (r < 0)
return r;
n++;
}
if (ret)
*ret = q;
q = NULL;
return n;
}
assert(q);
return;
if (state == DNS_QUERY_SENT)
return;
while (q->transactions)
if (q->complete)
q->complete(q);
}
assert(s);
assert(q);
return 0;
}
int dns_query_start(DnsQuery *q) {
int r;
assert(q);
if (!q->transactions)
return -ENETDOWN;
r = sd_event_add_time(q->manager->event, &q->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + QUERY_TIMEOUT_USEC, 0, on_query_timeout, q);
if (r < 0)
goto fail;
r = dns_query_transaction_start(t);
if (r < 0)
goto fail;
if (q->state != DNS_QUERY_SENT)
break;
}
return 0;
fail:
while (q->transactions)
return r;
}
void dns_query_finish(DnsQuery *q) {
assert(q);
if (q->state != DNS_QUERY_SENT)
return;
/* One of the transactions is still going on, let's wait for it */
return;
/* One of the transactions is sucecssful, let's use it */
if (t->state == DNS_QUERY_SUCCESS) {
return;
}
if (t->state == DNS_QUERY_FAILURE) {
}
if (state == DNS_QUERY_FAILURE)
dns_query_set_state(q, state);
}