--- /dev/null
+/* This code is in the public domain. */
+
+#include <mowgli.h>
+
+typedef struct
+{
+ char *domain;
+ mowgli_dns_query_t query;
+} dns_query;
+
+static void resolve_cb(mowgli_dns_reply_t *reply, int reason, void *vptr)
+{
+ char buf[2048];
+ dns_query *dnsquery = vptr;
+ const void *sockptr;
+
+ if (reply == NULL)
+ {
+ printf("Got null reply for %s\n", dnsquery->domain);
+ switch (reason)
+ {
+ case MOWGLI_DNS_RES_NXDOMAIN:
+ printf("Nonexistent domain\n");
+ break;
+ case MOWGLI_DNS_RES_INVALID:
+ printf("Invalid domain\n");
+ break;
+ case MOWGLI_DNS_RES_TIMEOUT:
+ printf("Timed out\n");
+ break;
+ }
+ goto end;
+ }
+
+ printf("Finished %s\n", dnsquery->domain);
+ printf("Hostname: %s\n", reply->h_name);
+
+ if (reply->addr.addr.ss_family == AF_INET)
+ {
+ const struct sockaddr_in *saddr = (const struct sockaddr_in *)&reply->addr.addr;
+ sockptr = &saddr->sin_addr;
+ }
+ else if (reply->addr.addr.ss_family == AF_INET6)
+ {
+ const struct sockaddr_in6 *saddr = (const struct sockaddr_in6 *)&reply->addr.addr;
+ sockptr = &saddr->sin6_addr;
+ }
+ else
+ {
+ printf("Invalid Address family %d\n", reply->addr.addr.ss_family);
+ return;
+ }
+
+ inet_ntop(reply->addr.addr.ss_family, sockptr, buf, sizeof(buf));
+ printf("Resolved: %s\n", buf);
+
+end:
+ mowgli_free(dnsquery->domain);
+ mowgli_free(vptr);
+}
+
+static void read_data(mowgli_eventloop_t *eventloop, mowgli_eventloop_io_t *io, mowgli_eventloop_io_dir_t dir, void *userdata)
+{
+ mowgli_eventloop_pollable_t *pollable = mowgli_eventloop_io_pollable(io);
+ mowgli_dns_t *dns = userdata;
+ char buf[2048];
+ char *ch;
+ size_t ret;
+
+ return_if_fail(pollable->fd == STDIN_FILENO);
+
+ if ((ret = read(pollable->fd, buf, sizeof(buf))) < 0)
+ {
+ perror("read");
+ mowgli_pollable_destroy(eventloop, io);
+ return;
+ }
+ else if (ret == 0)
+ return;
+
+ buf[--ret] = '\0';
+
+ ch = strtok(buf, " ");
+ while (ch != NULL)
+ {
+ dns_query *dnsquery = mowgli_alloc(sizeof(dns_query));
+ mowgli_dns_query_t *query = &dnsquery->query;
+
+ printf("Domain input: %s\n", ch);
+ printf("End domain input\n");
+
+ query->callback = resolve_cb;
+ query->ptr = dnsquery;
+ dnsquery->domain = mowgli_strdup(ch);
+
+ if (*ch == '+')
+ {
+ int type;
+ void *addrptr;
+ struct sockaddr_storage addr;
+
+ if(strchr(++ch, ':') != NULL)
+ {
+ struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&addr;
+ type = AF_INET6;
+ addrptr = &saddr->sin6_addr;
+ }
+ else
+ {
+ struct sockaddr_in *saddr = (struct sockaddr_in *)&addr;
+ type = AF_INET;
+ addrptr = &saddr->sin_addr;
+ }
+
+ addr.ss_family = type;
+
+ if ((ret = inet_pton(type, ch, addrptr)) != 1)
+ {
+ if (ret == -1)
+ perror("inet_pton");
+ else
+ printf("Invalid address %s\n", ch);
+
+ return;
+ }
+
+ mowgli_dns_gethost_byaddr(dns, &addr, query);
+ }
+ else
+ mowgli_dns_gethost_byname(dns, ch, query, MOWGLI_DNS_T_A);
+
+ dnsquery->domain = mowgli_strdup(ch);
+ ch = strtok(NULL, " ");
+ }
+}
+
+int main (void)
+{
+ mowgli_eventloop_t *evloop = mowgli_eventloop_create();
+ mowgli_dns_t *dns = mowgli_dns_create(evloop, MOWGLI_DNS_TYPE_ASYNC);
+ mowgli_eventloop_pollable_t *stdin_pollable = mowgli_pollable_create(evloop, STDIN_FILENO, dns);
+ mowgli_pollable_set_nonblocking(stdin_pollable, true);
+
+ mowgli_pollable_setselect(evloop, stdin_pollable, MOWGLI_EVENTLOOP_IO_READ, read_data);
+
+ mowgli_eventloop_run(evloop);
+
+ mowgli_eventloop_destroy(evloop);
+
+ return 0;
+}
state->nscount = 0;
parse_resvconf(dns);
if (state->nscount == 0)
+ {
+ mowgli_log("couldn't get resolv.conf entries, falling back to localhost resolver");
add_nameserver(dns, "127.0.0.1");
-
+ }
+
for (i = 0; i < state->nscount; i++)
state->timeout_count[i] = 0;
if (state->vio == NULL)
{
state->vio = mowgli_vio_create(dns);
- if (!mowgli_vio_socket(state->vio, state->nsaddr_list[0].addr.ss_family, SOCK_DGRAM, 0))
+ if (mowgli_vio_socket(state->vio, state->nsaddr_list[0].addr.ss_family, SOCK_DGRAM, 0) != 0)
{
mowgli_log("start_resolver(): unable to open UDP resolver socket: %s",
state->vio->error.string);
state->eventloop = eventloop;
mowgli_vio_eventloop_attach(state->vio, state->eventloop);
mowgli_pollable_setselect(state->eventloop, state->vio->io, MOWGLI_EVENTLOOP_IO_READ, res_readreply);
- state->timeout_resolver_timer = mowgli_timer_add(state->eventloop, "timeout_resolver", timeout_resolver, (void *)dns, 1);
+ state->timeout_resolver_timer = mowgli_timer_add(state->eventloop, "timeout_resolver", timeout_resolver, dns, 1);
}
return 0;
mowgli_vio_destroy(state->vio);
mowgli_timer_destroy(state->eventloop, state->timeout_resolver_timer);
-
+
mowgli_free(state);
dns->dns_state = NULL;
}
for(server = strtok_s(buf, " ", &p); server != NULL; server = strtok_s(NULL, " ", &p))
add_nameserver(dns, server);
-
+
mowgli_free(buf);
}
{
if (--request->retries <= 0)
{
- (*request->query->callback) (request->query->ptr, NULL);
+ (*request->query->callback) (NULL, MOWGLI_DNS_RES_TIMEOUT, request->query->ptr);
rem_request(dns, request);
continue;
}
void mowgli_dns_evloop_add_local_domain(mowgli_dns_t *dns, char *hname, size_t size)
{
mowgli_dns_evloop_t *state = dns->dns_state;
-
+
/* try to fix up unqualified names */
if (strchr(hname, '.') == NULL)
{
{
int i;
int counter = 1;
- const int max_retries = 7;
+ const int max_retries = 5;
for (i = 0; i < (timeouts < max_retries ? timeouts : max_retries); i++)
counter *= 3;
for (i = 0; i < state->nscount; i++)
{
ns = (i + rcount - 1) % state->nscount;
+
if (state->timeout_count[ns] && state->retrycnt % retryfreq(state->timeout_count[ns]))
continue;
void mowgli_dns_evloop_gethost_byname(mowgli_dns_t *dns, const char *name, mowgli_dns_query_t * query, int type)
{
return_if_fail(name != NULL);
-
+
do_query_name(dns, query, name, NULL, type);
}
if (request == NULL)
{
request = make_request(dns, query);
- request->name = (char *)mowgli_alloc(strlen(host_name) + 1);
- strcpy(request->name, host_name);
+ request->name = mowgli_strdup(host_name);
}
mowgli_strlcpy(request->queryname, host_name, sizeof(request->queryname));
mowgli_dns_reslist_t *request)
{
const unsigned char *cp;
+ const size_t size = addr->ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
if (request == NULL)
{
request = make_request(dns, query);
- memcpy(&request->addr, addr, sizeof(struct sockaddr_storage));
+ memcpy(&request->addr, addr, size);
request->name = (char *)mowgli_alloc(MOWGLI_DNS_RES_HOSTLEN + 1);
}
char *rqptr = request->queryname;
const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
-
- for(i = 15; i >= 0; i++, rqptr += 4)
+
+ for(i = 15; i >= 0; i--, rqptr += 4)
{
sprintf(rqptr, "%1x.%1x.",
(unsigned int)(cp[i] & 0xf),
strcpy(rqptr, ".ip6.arpa");
}
+ else
+ {
+ mowgli_log("do_query_number() called with invalid sockaddr_storage %d", addr->ss_family);
+ return;
+ }
+
request->type = MOWGLI_DNS_T_PTR;
+
+ mowgli_log("name: %s\n", request->queryname);
query_name(dns, request);
}
if (header->qdcount != 1)
return 0;
-
+
+ mowgli_log("qdcount checks out...");
+
n = mowgli_dns_dn_expand((unsigned char *)buf, (unsigned char *)eob, current, hostbuf, sizeof(hostbuf));
if (n <= 0)
return 0;
-
+
+ mowgli_log("length checks out...");
+ mowgli_log("hostbuf %s | queryname %s", hostbuf, request->queryname);
+
if (strcasecmp(hostbuf, request->queryname))
return 0;
-
+
+ mowgli_log("it matches what we sent");
+
return 1;
}
v4 = (struct sockaddr_in *)&request->addr;
v4->sin_family = AF_INET;
memcpy(&v4->sin_addr, current, sizeof(struct in_addr));
-
+
return 1;
}
case MOWGLI_DNS_T_AAAA:
header->nscount = ntohs(header->nscount);
header->arcount = ntohs(header->arcount);
+ mowgli_log("Recieved packet!");
+
/* response for an id which we have already received an answer for
* just ignore this response. */
if ((request = find_id(dns, header->id)) == 0)
return 1;
+ mowgli_log("ID found! id = %d", header->id);
+
/* check against possibly fake replies */
if (!res_ourserver(dns, &lsin.addr))
return 1;
+ mowgli_log("It's our server alright");
+
if (!check_question(dns, request, header, buf, buf + rc))
return 1;
+ mowgli_log("We sent it and its not timed out");
+
if ((header->rcode != MOWGLI_DNS_NO_ERRORS) || (header->ancount == 0))
{
if (header->rcode == MOWGLI_DNS_NXDOMAIN)
{
- (*request->query->callback) (request->query->ptr, NULL);
+ mowgli_log("Ack, nxdomain!");
+ (*request->query->callback) (NULL, MOWGLI_DNS_RES_NXDOMAIN, request->query->ptr);
rem_request(dns, request);
}
else
* If a bad error was returned, we stop here and dont send
* send any more (no retries granted).
*/
- (*request->query->callback) (request->query->ptr, NULL);
+ mowgli_log("Ack, no records or a bad error!");
+ (*request->query->callback) (NULL, MOWGLI_DNS_RES_INVALID, request->query->ptr);
rem_request(dns, request);
}
return 1;
}
+
/* If this fails there was an error decoding the received packet,
* give up. -- jilles
*/
/* got a PTR response with no name, something bogus is happening
* don't bother trying again, the client address doesn't resolve
*/
- (*request->query->callback) (request->query->ptr, reply);
+ mowgli_log("WTF, ptr with no name?!");
+ (*request->query->callback) (reply, MOWGLI_DNS_RES_INVALID, request->query->ptr);
rem_request(dns, request);
return 1;
}
+ mowgli_log("ptr found, searching other record...");
+
/* Lookup the 'authoritative' name that we were given for the
* ip#. */
if (request->addr.ss_family == AF_INET6)
else
{
/* got a name and address response, client resolved */
+ mowgli_log("woop woop we resolved");
reply = make_dnsreply(request);
- (*request->query->callback) (request->query->ptr, reply);
+ (*request->query->callback) (reply, MOWGLI_DNS_RES_SUCCESS, request->query->ptr);
mowgli_free(reply);
rem_request(dns, request);
}
else
{
/* couldn't decode, give up -- jilles */
- (*request->query->callback) (request->query->ptr, NULL);
+ mowgli_log("Ack, couldn't decode packet! ;_;");
+ (*request->query->callback) (NULL, MOWGLI_DNS_RES_INVALID, request->query->ptr);
rem_request(dns, request);
}
+
return 1;
}