forked from enlightenment/efl
Big update.
Understand CNAME, get the right hostname and aliases and get all IP's. SVN revision: 16303
This commit is contained in:
parent
6ad4e5e98e
commit
e90fd32b80
|
@ -71,6 +71,8 @@ static void _ecore_con_dns_ghbn(Ecore_Con_Dns_Query *query);
|
||||||
static int _ecore_con_dns_timeout(void *data);
|
static int _ecore_con_dns_timeout(void *data);
|
||||||
static int _ecore_con_cb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
|
static int _ecore_con_cb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
|
||||||
static void _ecore_con_dns_query_free(Ecore_Con_Dns_Query *query);
|
static void _ecore_con_dns_query_free(Ecore_Con_Dns_Query *query);
|
||||||
|
static int _ecore_con_hostname_get(unsigned char *buf, char *hostname,
|
||||||
|
int pos, int length);
|
||||||
|
|
||||||
static int _init = 0;
|
static int _init = 0;
|
||||||
|
|
||||||
|
@ -134,6 +136,10 @@ ecore_con_dns_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Skip leading dot */
|
||||||
|
if (*p == '.')
|
||||||
|
p++;
|
||||||
|
/* Get the domain */
|
||||||
_domain = strdup(p);
|
_domain = strdup(p);
|
||||||
/* clear search */
|
/* clear search */
|
||||||
for (i = 0; i < _search_count; i++)
|
for (i = 0; i < _search_count; i++)
|
||||||
|
@ -150,6 +156,9 @@ ecore_con_dns_init(void)
|
||||||
/* Remove whitespace */
|
/* Remove whitespace */
|
||||||
while ((*p) && (isspace(*p)))
|
while ((*p) && (isspace(*p)))
|
||||||
p++;
|
p++;
|
||||||
|
/* Skip leading dot */
|
||||||
|
if (*p == '.')
|
||||||
|
p++;
|
||||||
/* Find next element */
|
/* Find next element */
|
||||||
p2 = strchr(p, ' ');
|
p2 = strchr(p, ' ');
|
||||||
if (!p2)
|
if (!p2)
|
||||||
|
@ -374,6 +383,7 @@ _ecore_con_dns_timeout(void *data)
|
||||||
|
|
||||||
query = data;
|
query = data;
|
||||||
|
|
||||||
|
query->timeout = NULL;
|
||||||
if (query->done.cb)
|
if (query->done.cb)
|
||||||
query->done.cb(NULL, query->done.data);
|
query->done.cb(NULL, query->done.data);
|
||||||
_ecore_con_dns_query_free(query);
|
_ecore_con_dns_query_free(query);
|
||||||
|
@ -384,11 +394,15 @@ static int
|
||||||
_ecore_con_cb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
_ecore_con_cb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
||||||
{
|
{
|
||||||
Ecore_Con_Dns_Query *query;
|
Ecore_Con_Dns_Query *query;
|
||||||
int i, n, fd, found = 0;
|
int i, n, fd, found, len;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
unsigned char buf[1024];
|
unsigned char buf[1024];
|
||||||
|
char hostname[1024];
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
int size;
|
char **aliases;
|
||||||
|
struct in_addr *addrs;
|
||||||
|
int naliases, naddrs;
|
||||||
|
int ancount;
|
||||||
struct hostent he;
|
struct hostent he;
|
||||||
|
|
||||||
query = data;
|
query = data;
|
||||||
|
@ -396,9 +410,10 @@ _ecore_con_cb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
n = recv(fd, buf, sizeof(buf), 0);
|
n = recv(fd, buf, sizeof(buf), 0);
|
||||||
if (n == -1) goto error;
|
if ((n == -1) || (n < HFIXEDSZ) || (n > sizeof(buf))) goto error;
|
||||||
/* Check if this message is for us */
|
/* Check if this message is for us */
|
||||||
id = GET_16BIT(buf);
|
id = GET_16BIT(buf);
|
||||||
|
found = 0;
|
||||||
for (i = 0; i < _server_count; i++)
|
for (i = 0; i < _server_count; i++)
|
||||||
{
|
{
|
||||||
if (query->id[i] == id)
|
if (query->id[i] == id)
|
||||||
|
@ -414,40 +429,115 @@ _ecore_con_cb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
||||||
p = buf;
|
p = buf;
|
||||||
|
|
||||||
/* Skip the query */
|
/* Skip the query */
|
||||||
p += HFIXEDSZ;
|
/* Skip id and flags */
|
||||||
while (*p)
|
p += 4;
|
||||||
p += (*p + 1);
|
/* Check question count (QDCOUNT)*/
|
||||||
p++;
|
i = GET_16BIT(p);
|
||||||
p += QFIXEDSZ;
|
p += 2;
|
||||||
|
if (i != 1) goto error;
|
||||||
/* Skip the header */
|
/* Get the number of answers (ANCOUNT) */
|
||||||
p += RRFIXEDSZ;
|
ancount = GET_16BIT(p);
|
||||||
size = GET_16BIT(p);
|
p += 2;
|
||||||
/* We should get 4 bytes, 1 for each octet in the IP addres */
|
if (ancount < 1) goto error;
|
||||||
if (size != 4) goto error;
|
/* Skip NSCOUNT */
|
||||||
|
p += 2;
|
||||||
|
/* Skip ARCOUNT */
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
/* Get the IP address */
|
/* Skip the hostname */
|
||||||
he.h_addr_list = malloc(2 * sizeof(char *));
|
if ((len = _ecore_con_hostname_get(buf, hostname, p - buf, n)) == -1) goto error;
|
||||||
if (!he.h_addr_list) goto error;
|
if (strcmp(hostname, query->hostname))
|
||||||
|
printf("WARNING: Not the same hostname: %s %s?\n", hostname, query->hostname);
|
||||||
|
p += len;
|
||||||
|
/* Skip the question */
|
||||||
|
if (((p + QFIXEDSZ) - buf) >= n) goto error;
|
||||||
|
p += QFIXEDSZ;
|
||||||
|
|
||||||
|
aliases = malloc((ancount + 1) * sizeof(char *));
|
||||||
|
naliases = 0;
|
||||||
|
addrs = malloc((ancount + 1) * sizeof(struct in_addr));
|
||||||
|
naddrs = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ancount; i++)
|
||||||
|
{
|
||||||
|
int rr_type, rr_class, rr_len;
|
||||||
|
char rr_name[1024], rr_data[1024];
|
||||||
|
|
||||||
|
/* Get the name */
|
||||||
|
if ((len = _ecore_con_hostname_get(buf, rr_name, p - buf, n)) == -1) goto error;
|
||||||
|
p += len;
|
||||||
|
if (((p + RRFIXEDSZ) - buf) >= n) goto error;
|
||||||
|
/* Get the resource record type */
|
||||||
|
rr_type = GET_16BIT(p);
|
||||||
|
p += 2;
|
||||||
|
/* Get the resource record class */
|
||||||
|
rr_class = GET_16BIT(p);
|
||||||
|
p += 2;
|
||||||
|
/* Skip resource record ttl */
|
||||||
|
p += 4;
|
||||||
|
/* Get the resource record length */
|
||||||
|
rr_len = GET_16BIT(p);
|
||||||
|
p += 2;
|
||||||
|
/* > n is correct here. On the last message p will point after the last
|
||||||
|
* data bit, but for all other messages p will point to the next data
|
||||||
|
*/
|
||||||
|
if (((p + rr_len) - buf) > n) goto error;
|
||||||
|
|
||||||
|
if ((rr_class == C_IN) && (rr_type == T_CNAME))
|
||||||
|
{
|
||||||
|
/* Store name as alias */
|
||||||
|
aliases[naliases++] = strdup(rr_name);
|
||||||
|
|
||||||
|
/* Get hostname */
|
||||||
|
if ((len = _ecore_con_hostname_get(buf, rr_data, p - buf, n)) == -1) goto error;
|
||||||
|
strcpy(hostname, rr_data);
|
||||||
|
p += rr_len;
|
||||||
|
}
|
||||||
|
else if ((rr_class == C_IN) && (rr_type == T_A) && (!strcmp(hostname, rr_name)))
|
||||||
|
{
|
||||||
|
/* We should get 4 bytes, 1 for each octet in the IP addres */
|
||||||
|
if (rr_len != 4) goto error;
|
||||||
|
memcpy(&addrs[naddrs++], p, sizeof(struct in_addr));
|
||||||
|
p += rr_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p += rr_len;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill in the hostent and return successfully. */
|
/* Fill in the hostent and return successfully. */
|
||||||
/* TODO: Maybe get the hostname from the reply */
|
he.h_addr_list = malloc((naddrs + 1) * sizeof(char *));
|
||||||
he.h_name = strdup(query->hostname);
|
if (!he.h_addr_list) goto error;
|
||||||
/* he.h_aliases = aliases; */
|
he.h_name = strdup(hostname);
|
||||||
|
aliases[naliases] = NULL;
|
||||||
|
he.h_aliases = aliases;
|
||||||
he.h_addrtype = AF_INET;
|
he.h_addrtype = AF_INET;
|
||||||
he.h_length = sizeof(struct in_addr);
|
he.h_length = sizeof(struct in_addr);
|
||||||
he.h_addr_list[0] = malloc(4 * sizeof(char));
|
for (i = 0; i < naddrs; i++)
|
||||||
memcpy(he.h_addr_list[0], p, he.h_length);
|
he.h_addr_list[i] = (char *) &addrs[i];
|
||||||
he.h_addr_list[1] = NULL;
|
he.h_addr_list[naddrs] = NULL;
|
||||||
|
|
||||||
if (query->done.cb)
|
if (query->done.cb)
|
||||||
query->done.cb(&he, query->done.data);
|
query->done.cb(&he, query->done.data);
|
||||||
|
|
||||||
free(he.h_addr_list);
|
free(he.h_addr_list);
|
||||||
|
free(he.h_name);
|
||||||
|
free(addrs);
|
||||||
|
for (i = 0; i < naliases; i++)
|
||||||
|
free(aliases[i]);
|
||||||
|
free(aliases);
|
||||||
|
|
||||||
_ecore_con_dns_query_free(query);
|
_ecore_con_dns_query_free(query);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
if (addrs) free(addrs);
|
||||||
|
if (aliases)
|
||||||
|
{
|
||||||
|
for (i = 0; i < naliases; i++)
|
||||||
|
free(aliases[i]);
|
||||||
|
free(aliases);
|
||||||
|
}
|
||||||
|
|
||||||
found = 0;
|
found = 0;
|
||||||
for (i = 0; i < _server_count; i++)
|
for (i = 0; i < _server_count; i++)
|
||||||
{
|
{
|
||||||
|
@ -472,7 +562,7 @@ error:
|
||||||
/* Should we look more? */
|
/* Should we look more? */
|
||||||
if ((_domain) && (query->search++))
|
if ((_domain) && (query->search++))
|
||||||
{
|
{
|
||||||
if (snprintf(buf, sizeof(buf), "%s%s", query->searchname, _domain) < sizeof(buf))
|
if (snprintf(buf, sizeof(buf), "%s.%s", query->searchname, _domain) < sizeof(buf))
|
||||||
{
|
{
|
||||||
free(query->hostname);
|
free(query->hostname);
|
||||||
query->hostname = strdup(buf);
|
query->hostname = strdup(buf);
|
||||||
|
@ -487,7 +577,7 @@ error:
|
||||||
}
|
}
|
||||||
else if ((++query->search) < _search_count)
|
else if ((++query->search) < _search_count)
|
||||||
{
|
{
|
||||||
if (snprintf(buf, sizeof(buf), "%s%s", query->searchname, _search[query->search]) < sizeof(buf))
|
if (snprintf(buf, sizeof(buf), "%s.%s", query->searchname, _search[query->search]) < sizeof(buf))
|
||||||
{
|
{
|
||||||
free(query->hostname);
|
free(query->hostname);
|
||||||
query->hostname = strdup(buf);
|
query->hostname = strdup(buf);
|
||||||
|
@ -528,3 +618,63 @@ _ecore_con_dns_query_free(Ecore_Con_Dns_Query *query)
|
||||||
free(query->hostname);
|
free(query->hostname);
|
||||||
free(query);
|
free(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_ecore_con_hostname_get(unsigned char *buf, char *hostname,
|
||||||
|
int pos, int length)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
char *q;
|
||||||
|
int offset, indir, len, data;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
p += pos;
|
||||||
|
|
||||||
|
q = hostname;
|
||||||
|
|
||||||
|
offset = pos;
|
||||||
|
data = 0;
|
||||||
|
indir = 0;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
if ((*p & INDIR_MASK) == INDIR_MASK)
|
||||||
|
{
|
||||||
|
/* Check offset */
|
||||||
|
if (((p + 1) - buf) >= length) return -1;
|
||||||
|
offset = (*p & ~INDIR_MASK) << 8 | *(p + 1);
|
||||||
|
if (offset >= length) return -1;
|
||||||
|
p = buf + offset;
|
||||||
|
|
||||||
|
if (!indir)
|
||||||
|
{
|
||||||
|
data = 2;
|
||||||
|
indir = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset += (*p + 1);
|
||||||
|
if (offset >= length) return -1;
|
||||||
|
|
||||||
|
len = *p;
|
||||||
|
if (!indir)
|
||||||
|
data += len + 1;
|
||||||
|
|
||||||
|
/* Get the name */
|
||||||
|
*p++;
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
if (*p == '.')
|
||||||
|
*q++ = '\\';
|
||||||
|
*q++ = *p++;
|
||||||
|
}
|
||||||
|
if (*(p + 1))
|
||||||
|
*q++ = '.';
|
||||||
|
else
|
||||||
|
*q++ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!indir)
|
||||||
|
data++;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue