clean up ecore_con dns query- on shut down nuke all pending queries
SVN revision: 30292
This commit is contained in:
parent
b5c8891349
commit
2a5d49866c
|
@ -35,241 +35,13 @@
|
|||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
/* #include <arpa/nameser_compat.h> */
|
||||
#include <netdb.h>
|
||||
|
||||
#define SERVERS 3
|
||||
|
||||
typedef struct _Ecore_Con_Dns_Query Ecore_Con_Dns_Query;
|
||||
typedef struct _Ecore_Con_Dns_Cache Ecore_Con_Dns_Cache;
|
||||
|
||||
struct _Ecore_Con_Dns_Query {
|
||||
Ecore_List2 list;
|
||||
|
||||
/* Can ask three servers */
|
||||
unsigned int id[SERVERS];
|
||||
int socket[SERVERS];
|
||||
Ecore_Fd_Handler *fd_handlers[SERVERS];
|
||||
|
||||
Ecore_Timer *timeout;
|
||||
|
||||
int search;
|
||||
|
||||
/* The name the user searches for */
|
||||
char *searchname;
|
||||
|
||||
struct {
|
||||
void (*cb)(void *data, struct hostent *hostent);
|
||||
void *data;
|
||||
} done;
|
||||
|
||||
};
|
||||
|
||||
struct _Ecore_Con_Dns_Cache {
|
||||
Ecore_List2 list;
|
||||
|
||||
int ttl;
|
||||
double time;
|
||||
struct hostent *he;
|
||||
};
|
||||
|
||||
#if 0
|
||||
static void _ecore_con_dns_ghbn(Ecore_Con_Dns_Query *query, const char *hostname);
|
||||
static int _ecore_con_dns_timeout(void *data);
|
||||
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_cache_free(Ecore_Con_Dns_Cache *cache);
|
||||
static int _ecore_con_hostname_get(unsigned char *buf, char *hostname,
|
||||
int pos, int length);
|
||||
#endif
|
||||
|
||||
static int dns_init = 0;
|
||||
|
||||
#if 0
|
||||
static struct in_addr servers[SERVERS];
|
||||
static int server_count;
|
||||
|
||||
static char *search[6];
|
||||
static int search_count = 0;
|
||||
|
||||
static char *domain = NULL;
|
||||
|
||||
static uint16_t dns_id = 0;
|
||||
|
||||
static Ecore_Con_Dns_Cache *dns_cache = NULL;
|
||||
#endif
|
||||
|
||||
#define SET_16BIT(p, v) \
|
||||
(((p)[0]) = ((v) >> 8) & 0xff), \
|
||||
(((p)[1]) = v & 0xff)
|
||||
|
||||
#define GET_16BIT(p) (((p)[0]) << 8 | ((p)[1]))
|
||||
#define GET_32BIT(p) (((p)[0]) << 24 | ((p)[1]) << 16 | ((p)[2]) << 8 | ((p)[3]))
|
||||
|
||||
int
|
||||
ecore_con_dns_init(void)
|
||||
{
|
||||
#if 1
|
||||
dns_init++;
|
||||
return dns_init;
|
||||
#else
|
||||
FILE *file;
|
||||
char buf[1024];
|
||||
char *p, *p2;
|
||||
int ret;
|
||||
|
||||
if (++dns_init != 1) return dns_init;
|
||||
|
||||
memset(servers, 0, sizeof(servers));
|
||||
server_count = 0;
|
||||
|
||||
file = fopen("/etc/resolv.conf", "rb");
|
||||
if (!file) return --dns_init;
|
||||
while (fgets(buf, sizeof(buf), file))
|
||||
{
|
||||
if (strlen(buf) >= 1023)
|
||||
printf("WARNING: Very long line in resolv.conf\n");
|
||||
|
||||
/* remove whitespace */
|
||||
p = strchr(buf, ' ');
|
||||
if (!p)
|
||||
p = strchr(buf, '\t');
|
||||
if (!p) continue;
|
||||
while ((*p) && (isspace(*p)))
|
||||
p++;
|
||||
/* Remove trailing newline */
|
||||
p2 = strchr(buf, '\n');
|
||||
if (p2)
|
||||
*p2 = 0;
|
||||
|
||||
if (!strncmp(buf, "nameserver", 10))
|
||||
{
|
||||
if (server_count >= SERVERS) continue;
|
||||
|
||||
servers[server_count].s_addr = inet_addr(p);
|
||||
server_count++;
|
||||
}
|
||||
else if (!strncmp(buf, "domain", 6))
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Skip leading dot */
|
||||
if (*p == '.')
|
||||
p++;
|
||||
/* Get the domain */
|
||||
domain = strdup(p);
|
||||
/* clear search */
|
||||
for (i = 0; i < search_count; i++)
|
||||
{
|
||||
free(search[i]);
|
||||
search[i] = NULL;
|
||||
}
|
||||
search_count = 0;
|
||||
}
|
||||
else if (!strncmp(buf, "search", 6))
|
||||
{
|
||||
while ((p) && (search_count < 6))
|
||||
{
|
||||
/* Remove whitespace */
|
||||
while ((*p) && (isspace(*p)))
|
||||
p++;
|
||||
/* Skip leading dot */
|
||||
if (*p == '.')
|
||||
p++;
|
||||
/* Find next element */
|
||||
p2 = strchr(p, ' ');
|
||||
if (!p2)
|
||||
p2 = strchr(p, '\t');
|
||||
if (p2)
|
||||
*p2 = 0;
|
||||
/* Get this element */
|
||||
search[search_count] = strdup(p);
|
||||
search_count++;
|
||||
if (p2) p = p2 + 1;
|
||||
else p = NULL;
|
||||
}
|
||||
if (domain)
|
||||
{
|
||||
free(domain);
|
||||
domain = NULL;
|
||||
}
|
||||
}
|
||||
else if (!strncmp(buf, "sortlist", 8))
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
else if (!strncmp(buf, "options", 8))
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
if (!server_count)
|
||||
{
|
||||
/* We should try localhost */
|
||||
servers[server_count].s_addr = inet_addr("127.0.0.1");
|
||||
server_count++;
|
||||
}
|
||||
if ((!search_count) && (!domain))
|
||||
{
|
||||
/* Get domain from hostname */
|
||||
ret = gethostname(buf, sizeof(buf));
|
||||
if ((ret > 0) && (ret < 1024))
|
||||
{
|
||||
p = strchr(buf, '.');
|
||||
if (p)
|
||||
{
|
||||
p++;
|
||||
domain = strdup(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dns_init;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
ecore_con_dns_shutdown(void)
|
||||
{
|
||||
#if 1
|
||||
dns_init--;
|
||||
return dns_init;
|
||||
#else
|
||||
Ecore_List2 *l;
|
||||
int i;
|
||||
|
||||
if (--dns_init != 0) return dns_init;
|
||||
|
||||
for (l = (Ecore_List2 *)dns_cache; l;)
|
||||
{
|
||||
Ecore_Con_Dns_Cache *current;
|
||||
|
||||
current = (Ecore_Con_Dns_Cache *)l;
|
||||
l = l->next;
|
||||
_ecore_con_dns_cache_free(current);
|
||||
}
|
||||
dns_cache = NULL;
|
||||
|
||||
if (domain)
|
||||
{
|
||||
free(domain);
|
||||
domain = NULL;
|
||||
}
|
||||
for (i = 0; i < search_count; i++)
|
||||
free(search[i]);
|
||||
search_count = 0;
|
||||
|
||||
return dns_init;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 1
|
||||
typedef struct _CB_Data CB_Data;
|
||||
|
||||
struct _CB_Data
|
||||
{
|
||||
Ecore_List2 __list_data;
|
||||
void (*cb_done) (void *data, struct hostent *hostent);
|
||||
void *data;
|
||||
Ecore_Fd_Handler *fdh;
|
||||
|
@ -278,83 +50,40 @@ struct _CB_Data
|
|||
int fd2;
|
||||
};
|
||||
|
||||
static void
|
||||
_ecore_con_dns_readdata(CB_Data *cbdata)
|
||||
{
|
||||
struct hostent he;
|
||||
struct in_addr addr;
|
||||
char *addr2;
|
||||
ssize_t size;
|
||||
static void _ecore_con_dns_readdata(CB_Data *cbdata);
|
||||
static void _ecore_con_dns_slave_free(CB_Data *cbdata);
|
||||
static int _ecore_con_dns_data_handler(void *data, Ecore_Fd_Handler *fd_handler);
|
||||
static int _ecore_con_dns_exit_handler(void *data, int type __UNUSED__, void *event);
|
||||
|
||||
size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &(addr.s_addr),
|
||||
sizeof(in_addr_t));
|
||||
if (size == sizeof(in_addr_t))
|
||||
static int dns_init = 0;
|
||||
static Ecore_List2 *dns_slaves = NULL;
|
||||
|
||||
int
|
||||
ecore_con_dns_init(void)
|
||||
{
|
||||
dns_init++;
|
||||
return dns_init;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_con_dns_shutdown(void)
|
||||
{
|
||||
dns_init--;
|
||||
if (dns_init == 0)
|
||||
{
|
||||
addr2 = (char *)&addr;
|
||||
he.h_addrtype = AF_INET;
|
||||
he.h_length = sizeof(in_addr_t);
|
||||
he.h_addr_list = &addr2;
|
||||
cbdata->cb_done(cbdata->data, &he);
|
||||
while (dns_slaves) _ecore_con_dns_slave_free((CB_Data *)dns_slaves);
|
||||
}
|
||||
else
|
||||
cbdata->cb_done(cbdata->data, NULL);
|
||||
cbdata->cb_done = NULL;
|
||||
return dns_init;
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_con_dns_data_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
||||
{
|
||||
CB_Data *cbdata;
|
||||
|
||||
cbdata = data;
|
||||
if (cbdata->cb_done)
|
||||
{
|
||||
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
|
||||
_ecore_con_dns_readdata(cbdata);
|
||||
else
|
||||
{
|
||||
cbdata->cb_done(cbdata->data, NULL);
|
||||
cbdata->cb_done = NULL;
|
||||
}
|
||||
}
|
||||
close(ecore_main_fd_handler_fd_get(cbdata->fdh));
|
||||
close(cbdata->fd2);
|
||||
ecore_main_fd_handler_del(cbdata->fdh);
|
||||
ecore_event_handler_del(cbdata->handler);
|
||||
free(cbdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_con_dns_exit_handler(void *data, int type __UNUSED__, void *event)
|
||||
{
|
||||
CB_Data *cbdata;
|
||||
Ecore_Exe_Event_Del *ev;
|
||||
|
||||
ev = event;
|
||||
cbdata = data;
|
||||
if (cbdata->pid != ev->pid) return 1;
|
||||
return 0;
|
||||
close(ecore_main_fd_handler_fd_get(cbdata->fdh));
|
||||
close(cbdata->fd2);
|
||||
ecore_main_fd_handler_del(cbdata->fdh);
|
||||
ecore_event_handler_del(cbdata->handler);
|
||||
free(cbdata);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
int
|
||||
ecore_con_dns_lookup(const char *name,
|
||||
void (*done_cb) (void *data, struct hostent *hostent),
|
||||
void *data)
|
||||
{
|
||||
#if 1
|
||||
CB_Data *cbdata;
|
||||
int fd[2];
|
||||
|
||||
/* FIXME: set up one-way pipe back to parent and fdhandler */
|
||||
if (pipe(fd) < 0) return 0;
|
||||
cbdata = calloc(1, sizeof(CB_Data));
|
||||
if (!cbdata)
|
||||
|
@ -408,533 +137,74 @@ ecore_con_dns_lookup(const char *name,
|
|||
close(fd[1]);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
Ecore_Con_Dns_Query *query;
|
||||
Ecore_Con_Dns_Cache *current;
|
||||
Ecore_List2 *l;
|
||||
|
||||
if (!server_count) return 0;
|
||||
if ((!name) || (!*name)) return 0;
|
||||
|
||||
for (l = (Ecore_List2 *)dns_cache; l;)
|
||||
{
|
||||
double time;
|
||||
int i;
|
||||
|
||||
current = (Ecore_Con_Dns_Cache *)l;
|
||||
l = l->next;
|
||||
|
||||
time = ecore_time_get();
|
||||
if ((time - current->time) > current->ttl)
|
||||
{
|
||||
dns_cache = _ecore_list2_remove(dns_cache, current);
|
||||
_ecore_con_dns_cache_free(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if we have a match */
|
||||
if (!strcmp(name, current->he->h_name))
|
||||
{
|
||||
if (done_cb)
|
||||
done_cb(data, current->he);
|
||||
dns_cache = _ecore_list2_remove(dns_cache, current);
|
||||
dns_cache = _ecore_list2_prepend(dns_cache, current);
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; current->he->h_aliases[i]; i++)
|
||||
{
|
||||
if (!strcmp(name, current->he->h_aliases[i]))
|
||||
{
|
||||
if (done_cb)
|
||||
done_cb(data, current->he);
|
||||
dns_cache = _ecore_list2_remove(dns_cache, current);
|
||||
dns_cache = _ecore_list2_prepend(dns_cache, current);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query = calloc(1, sizeof(Ecore_Con_Dns_Query));
|
||||
if (!query) return 0;
|
||||
|
||||
query->done.cb = done_cb;
|
||||
query->done.data = data;
|
||||
query->timeout = ecore_timer_add(20.0, _ecore_con_dns_timeout, query);
|
||||
query->searchname = strdup(name);
|
||||
query->search = -1;
|
||||
|
||||
_ecore_con_dns_ghbn(query, name);
|
||||
#endif
|
||||
dns_slaves = _ecore_list2_append(dns_slaves, cbdata);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 1
|
||||
#else
|
||||
static void
|
||||
_ecore_con_dns_ghbn(Ecore_Con_Dns_Query *query, const char *hostname)
|
||||
_ecore_con_dns_readdata(CB_Data *cbdata)
|
||||
{
|
||||
char buf[256];
|
||||
char *p, *pl;
|
||||
const char *q;
|
||||
int i, len, total_len;
|
||||
struct hostent he;
|
||||
struct in_addr addr;
|
||||
char *addr2;
|
||||
ssize_t size;
|
||||
|
||||
/* Create buf */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
p = buf;
|
||||
total_len = 0;
|
||||
|
||||
p += 2;
|
||||
/* opcode */
|
||||
*p |= (QUERY & 0xf) << 3;
|
||||
/* TODO: rd, do we always want recursive? */
|
||||
*p |= 1 & 0x1;
|
||||
/* qdcount, only asking for one name */
|
||||
p += 2;
|
||||
SET_16BIT(p, 1);
|
||||
|
||||
total_len += HFIXEDSZ;
|
||||
p = &buf[HFIXEDSZ];
|
||||
|
||||
/* remember where the length shall be placed */
|
||||
pl = p;
|
||||
p++;
|
||||
total_len++;
|
||||
/* name */
|
||||
q = hostname;
|
||||
len = 0;
|
||||
while ((*q) && (total_len < 1024))
|
||||
size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &(addr.s_addr),
|
||||
sizeof(in_addr_t));
|
||||
if (size == sizeof(in_addr_t))
|
||||
{
|
||||
if (*q == '.')
|
||||
{
|
||||
if (len)
|
||||
{
|
||||
*pl = len;
|
||||
pl = p;
|
||||
p++;
|
||||
len = 0;
|
||||
total_len++;
|
||||
}
|
||||
q++;
|
||||
}
|
||||
else if ((*q == '\\') && (*(q + 1) == 0))
|
||||
{
|
||||
q++;
|
||||
|
||||
*p++ = *q++;
|
||||
len++;
|
||||
total_len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p++ = *q++;
|
||||
len++;
|
||||
total_len++;
|
||||
}
|
||||
}
|
||||
/* Null at the end of the query */
|
||||
if (len)
|
||||
{
|
||||
*pl = len;
|
||||
*p = 0;
|
||||
p++;
|
||||
total_len++;
|
||||
}
|
||||
|
||||
/* type */
|
||||
SET_16BIT(p, T_A);
|
||||
p += 2;
|
||||
/* class */
|
||||
SET_16BIT(p, C_IN);
|
||||
p += 2;
|
||||
total_len += QFIXEDSZ;
|
||||
|
||||
/* We're crazy, just ask all servers! */
|
||||
for (i = 0; i < server_count; i++)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
||||
query->socket[i] = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (query->socket[i] == -1)
|
||||
{
|
||||
printf("ERROR: Couldn't create socket\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr = servers[i];
|
||||
sin.sin_port = htons(NAMESERVER_PORT);
|
||||
if (connect(query->socket[i], (struct sockaddr *) &sin, sizeof(sin)) == -1)
|
||||
{
|
||||
/* TODO: EINPROGRESS isn't a fatal error */
|
||||
printf("ERROR: Couldn't connect to nameserver\n");
|
||||
close(query->socket[i]);
|
||||
query->socket[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* qid */
|
||||
query->id[i] = ++dns_id;
|
||||
SET_16BIT(buf, query->id[i]);
|
||||
|
||||
if (send(query->socket[i], buf, total_len, 0) == -1)
|
||||
{
|
||||
printf("ERROR: Send failed\n");
|
||||
close(query->socket[i]);
|
||||
query->socket[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
query->fd_handlers[i] = ecore_main_fd_handler_add(query->socket[i],
|
||||
ECORE_FD_READ,
|
||||
_ecore_con_cb_fd_handler, query,
|
||||
NULL, NULL);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_con_dns_timeout(void *data)
|
||||
{
|
||||
Ecore_Con_Dns_Query *query;
|
||||
|
||||
query = data;
|
||||
|
||||
query->timeout = NULL;
|
||||
if (query->done.cb)
|
||||
query->done.cb(query->done.data, NULL);
|
||||
_ecore_con_dns_query_free(query);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_con_cb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
||||
{
|
||||
Ecore_Con_Dns_Query *query;
|
||||
Ecore_Con_Dns_Cache *cache;
|
||||
int i, n, fd, found, len;
|
||||
unsigned int id;
|
||||
unsigned char buf[1024];
|
||||
char hostname[1024];
|
||||
unsigned char *p;
|
||||
char **aliases = NULL;
|
||||
struct in_addr *addrs = NULL;
|
||||
int naliases = 0, naddrs = 0;
|
||||
int ancount, ttl = INT_MAX;
|
||||
struct hostent *he;
|
||||
|
||||
query = data;
|
||||
fd = ecore_main_fd_handler_fd_get(fd_handler);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
n = recv(fd, buf, sizeof(buf), 0);
|
||||
if ((n == -1) || (n < HFIXEDSZ) || (n > sizeof(buf))) goto error;
|
||||
/* Check if this message is for us */
|
||||
id = GET_16BIT(buf);
|
||||
found = 0;
|
||||
for (i = 0; i < server_count; i++)
|
||||
{
|
||||
if (query->id[i] == id)
|
||||
{
|
||||
found = 1;
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) goto error;
|
||||
|
||||
/* This should be it! */
|
||||
p = buf;
|
||||
|
||||
/* Skip the query */
|
||||
/* Skip id and flags */
|
||||
p += 4;
|
||||
/* Check question count (QDCOUNT)*/
|
||||
i = GET_16BIT(p);
|
||||
p += 2;
|
||||
if (i != 1) goto error;
|
||||
/* Get the number of answers (ANCOUNT) */
|
||||
ancount = GET_16BIT(p);
|
||||
p += 2;
|
||||
if (ancount < 1) goto error;
|
||||
/* Skip NSCOUNT */
|
||||
p += 2;
|
||||
/* Skip ARCOUNT */
|
||||
p += 2;
|
||||
|
||||
/* Skip the hostname */
|
||||
if ((len = _ecore_con_hostname_get(buf, hostname, p - buf, n)) == -1) goto error;
|
||||
p += len;
|
||||
/* Skip the question */
|
||||
if (((p + QFIXEDSZ) - buf) >= n) goto error;
|
||||
p += QFIXEDSZ;
|
||||
|
||||
aliases = malloc((ancount + 1) * sizeof(char *));
|
||||
addrs = malloc((ancount + 1) * sizeof(struct in_addr));
|
||||
|
||||
for (i = 0; i < ancount; i++)
|
||||
{
|
||||
int rr_type, rr_class, rr_len, rr_ttl;
|
||||
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;
|
||||
/* Get the resource record ttl */
|
||||
rr_ttl = GET_32BIT(p);
|
||||
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;
|
||||
ttl = MIN(rr_ttl, ttl);
|
||||
}
|
||||
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;
|
||||
ttl = MIN(rr_ttl, ttl);
|
||||
}
|
||||
else
|
||||
p += rr_len;
|
||||
}
|
||||
|
||||
/* Fill in the hostent and return successfully. */
|
||||
he = malloc(sizeof(struct hostent));
|
||||
if (!he) goto error;
|
||||
he->h_addr_list = malloc((naddrs + 1) * sizeof(char *));
|
||||
if (!he->h_addr_list) goto error;
|
||||
he->h_name = strdup(hostname);
|
||||
aliases[naliases] = NULL;
|
||||
he->h_aliases = aliases;
|
||||
he->h_addrtype = AF_INET;
|
||||
he->h_length = sizeof(struct in_addr);
|
||||
for (i = 0; i < naddrs; i++)
|
||||
he->h_addr_list[i] = (char *) &addrs[i];
|
||||
he->h_addr_list[naddrs] = NULL;
|
||||
|
||||
if (query->done.cb)
|
||||
query->done.cb(query->done.data, he);
|
||||
|
||||
cache = malloc(sizeof(Ecore_Con_Dns_Cache));
|
||||
if (cache)
|
||||
{
|
||||
Ecore_List2 *l;
|
||||
|
||||
cache->ttl = ttl;
|
||||
cache->time = ecore_time_get();
|
||||
cache->he = he;
|
||||
dns_cache = _ecore_list2_prepend(dns_cache, cache);
|
||||
|
||||
/* Check cache size */
|
||||
i = 1;
|
||||
l = (Ecore_List2 *)dns_cache;
|
||||
while ((l = l->next))
|
||||
i++;
|
||||
|
||||
/* Remove old stuff if cache to big */
|
||||
if (i > 16)
|
||||
{
|
||||
cache = (Ecore_Con_Dns_Cache *)((Ecore_List2 *)dns_cache)->last;
|
||||
dns_cache = _ecore_list2_remove(dns_cache, cache);
|
||||
_ecore_con_dns_cache_free(cache);
|
||||
}
|
||||
addr2 = (char *)&addr;
|
||||
he.h_addrtype = AF_INET;
|
||||
he.h_length = sizeof(in_addr_t);
|
||||
he.h_addr_list = &addr2;
|
||||
cbdata->cb_done(cbdata->data, &he);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(he->h_addr_list);
|
||||
free(he->h_name);
|
||||
free(addrs);
|
||||
for (i = 0; i < naliases; i++)
|
||||
free(aliases[i]);
|
||||
free(aliases);
|
||||
free(he);
|
||||
}
|
||||
|
||||
_ecore_con_dns_query_free(query);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (addrs) free(addrs);
|
||||
if (aliases)
|
||||
{
|
||||
for (i = 0; i < naliases; i++)
|
||||
free(aliases[i]);
|
||||
free(aliases);
|
||||
}
|
||||
|
||||
found = 0;
|
||||
for (i = 0; i < server_count; i++)
|
||||
{
|
||||
if (query->fd_handlers[i] == fd_handler)
|
||||
{
|
||||
/* This server didn't do it */
|
||||
if (query->socket[i]) close(query->socket[i]);
|
||||
query->socket[i] = 0;
|
||||
query->fd_handlers[i] = NULL;
|
||||
}
|
||||
else if (query->socket[i])
|
||||
{
|
||||
/* We're still looking */
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
/* Should we look more? */
|
||||
if ((domain) && (query->search++))
|
||||
{
|
||||
if (snprintf(buf, sizeof(buf), "%s.%s", query->searchname, domain) < sizeof(buf))
|
||||
{
|
||||
_ecore_con_dns_ghbn(query, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (query->done.cb)
|
||||
query->done.cb(query->done.data, NULL);
|
||||
_ecore_con_dns_query_free(query);
|
||||
}
|
||||
}
|
||||
else if ((++query->search) < search_count)
|
||||
{
|
||||
if (snprintf(buf, sizeof(buf), "%s.%s", query->searchname, search[query->search]) < sizeof(buf))
|
||||
{
|
||||
_ecore_con_dns_ghbn(query, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (query->done.cb)
|
||||
query->done.cb(query->done.data, NULL);
|
||||
_ecore_con_dns_query_free(query);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Shutdown */
|
||||
if (query->done.cb)
|
||||
query->done.cb(query->done.data, NULL);
|
||||
_ecore_con_dns_query_free(query);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
cbdata->cb_done(cbdata->data, NULL);
|
||||
cbdata->cb_done = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_con_dns_query_free(Ecore_Con_Dns_Query *query)
|
||||
_ecore_con_dns_slave_free(CB_Data *cbdata)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < server_count; i++)
|
||||
{
|
||||
if (query->socket[i]) close(query->socket[i]);
|
||||
query->socket[i] = 0;
|
||||
if (query->fd_handlers[i]) ecore_main_fd_handler_del(query->fd_handlers[i]);
|
||||
query->fd_handlers[i] = NULL;
|
||||
}
|
||||
if (query->timeout) ecore_timer_del(query->timeout);
|
||||
query->timeout = NULL;
|
||||
free(query->searchname);
|
||||
free(query);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_con_dns_cache_free(Ecore_Con_Dns_Cache *cache)
|
||||
{
|
||||
int i;
|
||||
|
||||
free(cache->he->h_name);
|
||||
free(cache->he->h_addr_list[0]);
|
||||
free(cache->he->h_addr_list);
|
||||
for (i = 0; cache->he->h_aliases[i]; i++)
|
||||
free(cache->he->h_aliases[i]);
|
||||
free(cache->he->h_aliases);
|
||||
free(cache->he);
|
||||
free(cache);
|
||||
dns_slaves = _ecore_list2_remove(dns_slaves, cbdata);
|
||||
close(ecore_main_fd_handler_fd_get(cbdata->fdh));
|
||||
close(cbdata->fd2);
|
||||
ecore_main_fd_handler_del(cbdata->fdh);
|
||||
ecore_event_handler_del(cbdata->handler);
|
||||
free(cbdata);
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_con_hostname_get(unsigned char *buf, char *hostname,
|
||||
int pos, int length)
|
||||
_ecore_con_dns_data_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
||||
{
|
||||
unsigned char *p;
|
||||
char *q;
|
||||
int offset, indir, len, data;
|
||||
CB_Data *cbdata;
|
||||
|
||||
p = buf;
|
||||
p += pos;
|
||||
|
||||
q = hostname;
|
||||
|
||||
offset = pos;
|
||||
data = 0;
|
||||
indir = 0;
|
||||
while (*p)
|
||||
cbdata = data;
|
||||
if (cbdata->cb_done)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
|
||||
_ecore_con_dns_readdata(cbdata);
|
||||
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;
|
||||
cbdata->cb_done(cbdata->data, NULL);
|
||||
cbdata->cb_done = NULL;
|
||||
}
|
||||
}
|
||||
if (!indir)
|
||||
data++;
|
||||
return data;
|
||||
_ecore_con_dns_slave_free(cbdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_con_dns_exit_handler(void *data, int type __UNUSED__, void *event)
|
||||
{
|
||||
CB_Data *cbdata;
|
||||
Ecore_Exe_Event_Del *ev;
|
||||
|
||||
ev = event;
|
||||
cbdata = data;
|
||||
if (cbdata->pid != ev->pid) return 1;
|
||||
return 0;
|
||||
_ecore_con_dns_slave_free(cbdata);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue