Пример #1
0
/* Perform an async dns lookup. This is host -> ip. For ip -> host, use
 * egg_dns_reverse(). We return a dns id that you can use to cancel the
 * lookup. */
int egg_dns_lookup(const char *host, interval_t timeout, dns_callback_t callback, void *client_data)
{
	dns_query_t *q = NULL;
	int i, cache_id;

	sdprintf("egg_dns_lookup(%s, %d)", host, timeout);

	if (is_dotted_ip(host)) {
		/* If it's already an ip, we're done. */
		dns_answer_t answer;

		answer_init(&answer);
		answer_add(&answer, host);
		callback(-1, client_data, host, answer.list);
		answer_free(&answer);
		return(-1);
	}

	/* Ok, now see if it's in our host cache. */
	for (i = 0; i < nhosts; i++) {
		if (!egg_strcasecmp(host, hosts[i].host)) {
			dns_answer_t answer;

			answer_init(&answer);
			answer_add(&answer, hosts[i].ip);
			callback(-1, client_data, host, answer.list);
			answer_free(&answer);
			return(-1);
		}
	}

	cache_id = cache_find(host);
	if (cache_id >= 0) {
		shuffleArray(cache[cache_id].answer.list, cache[cache_id].answer.len);
		callback(-1, client_data, host, cache[cache_id].answer.list);
		return(-1);
	}

	/* check if the query was already made */
        if (find_query(host))
          return(-2);

	/* Allocate our query struct. */
        q = alloc_query(client_data, callback, host);

        dns_send_query(q);

//        /* setup a timer to detect dead ns */
//	dns_create_timeout_timer(&q, host, timeout);

	/* Send the ipv4 query. */

	return(q->id);
}
Пример #2
0
/** @brief Destroys a task and its data
  * @param task the task that'll be destroyed
  */
void task_free(msg_task_t task)
{
  xbt_assert((task != NULL), "Tried to free a NULL task");

  task_data_t data = MSG_task_get_data(task);

  if (data->answer) {
    answer_free(data->answer);
  }
  xbt_free(data);

  MSG_task_destroy(task);
}
Пример #3
0
static void cache_del(int id)
{
	answer_free(&cache[id].answer);
	free(cache[id].query);
	cache[id].expiretime = 0;

	ncache--;

	if (id < ncache) egg_memcpy(&cache[id], &cache[ncache], sizeof(dns_cache_t));
	else egg_bzero(&cache[id], sizeof(dns_cache_t));

	cache = (dns_cache_t *) my_realloc(cache, (ncache+1)*sizeof(*cache));
}
Пример #4
0
static int parse_reply(char *response, size_t nbytes)
{
	dns_header_t header;
	dns_query_t *q = NULL, *prev = NULL;
	dns_rr_t reply;
	char result[512] = "";
	short rr;
	int r = -1;
	unsigned const char *eop = (unsigned char *) response + nbytes;
	unsigned char *ptr = (unsigned char *) response;

	egg_memcpy(&header, ptr, HEAD_SIZE);
	ptr += HEAD_SIZE;

	/* header.id is already in our order, echoed by the server */
	header.flags = ntohs(header.flags);
	header.question_count = ntohs(header.question_count);
	header.answer_count = ntohs(header.answer_count);
	header.ar_count = ntohs(header.ar_count);
	header.ns_count = ntohs(header.ns_count);

//	print_header(header);

	/* Find our copy of the query before proceeding. */
	for (q = query_head; q; q = q->next) {
		if (q->id == header.id) break;
		prev = q;
	}
	if (!q) return 0;
        
//        /* destroy our async timeout */
//        timer_destroy(q->timer_id);

	/* Pass over the questions. */
	for (rr = 0; rr < header.question_count; rr++) {
		ptr += skip_name(ptr);
		ptr += 4;
	}
	/* End of questions. */

//	for (rr = 0; rr < header.answer_count + header.ar_count + header.ns_count; rr++) {


	q->answers += header.answer_count;

	for (rr = 0; rr < header.answer_count; rr++) {
		result[0] = 0;
		/* Read in the answer. */
		ptr += skip_name(ptr);

		egg_memcpy(&reply, ptr, RR_SIZE);
		ptr += RR_SIZE;

		reply.type = ntohs(reply.type);
		reply.dclass = ntohs(reply.dclass);
		reply.rdlength = ntohs(reply.rdlength);
		reply.ttl = ntohl(reply.ttl);
		/* Save the lowest ttl */
		if (reply.ttl && ((!q->answer.ttl) || (q->answer.ttl > reply.ttl))) q->answer.ttl = reply.ttl;

//		print_reply(reply);

		switch (reply.type) {
		case DNS_A:
			egg_inet_ntop(AF_INET, ptr, result, 512);
			answer_add(&q->answer, result);
			break;
		case DNS_AAAA:
#ifdef USE_IPV6
			egg_inet_ntop(AF_INET6, ptr, result, 512);
			answer_add(&q->answer, result);
#endif /* USE_IPV6 */
			break;
		case DNS_PTR:
			r = my_dn_expand((const unsigned char *) response, eop, ptr, result, sizeof(result));

			if (r != -1 && result[0])
				answer_add(&q->answer, result);
			break;
		default:
			sdprintf("Unhandled DNS reply type: %d", reply.type);
			break;
		}

		ptr += reply.rdlength;
                if ((size_t) (ptr - (unsigned char*) response) > nbytes) {
                  sdprintf("MALFORMED/TRUNCATED DNS PACKET detected (need TCP).");
                  q->remaining = 0;
                  break;
                }
	}
	/* Don't continue if we haven't gotten all expected replies. */
	if (--q->remaining > 0) return 0;

        if (q->answer.len == 0) {
          sdprintf("Failed to get any answers for query");

          if (prev) prev->next = q->next;
          else query_head = q->next;

          q->callback(q->id, q->client_data, q->query, NULL);

          free(q->query);
          if (q->ip)
            free(q->ip);
          free(q);
          return 1;		/* get a new server */
        }

	/* Ok, we have, so now issue the callback with the answers. */
	if (prev) prev->next = q->next;
	else query_head = q->next;

	cache_add(q->query, &q->answer);

	q->callback(q->id, q->client_data, q->query, q->answer.list);
	answer_free(&q->answer);
	free(q->query);
        if (q->ip)
          free(q->ip);
	free(q);

	return(0);
}
Пример #5
0
/* Perform an async dns reverse lookup. This does ip -> host. For host -> ip
 * use egg_dns_lookup(). We return a dns id that you can use to cancel the
 * lookup. */
int egg_dns_reverse(const char *ip, interval_t timeout, dns_callback_t callback, void *client_data)
{
	dns_query_t *q;
	int i, cache_id;

	sdprintf("egg_dns_reverse(%s, %d)", ip, timeout);

	if (!is_dotted_ip(ip)) {
		/* If it's not a valid ip, don't even make the request. */
		callback(-1, client_data, ip, NULL);
		return(-1);
	}

	/* Ok, see if we have it in our host cache. */
	for (i = 0; i < nhosts; i++) {
		if (!egg_strcasecmp(hosts[i].ip, ip)) {
			dns_answer_t answer;

			answer_init(&answer);
			answer_add(&answer, hosts[i].host);
			callback(-1, client_data, ip, answer.list);
			answer_free(&answer);
			return(-1);
		}
	}

	cache_id = cache_find(ip);
        if (cache_id >= 0) {
		shuffleArray(cache[cache_id].answer.list, cache[cache_id].answer.len);
		callback(-1, client_data, ip, cache[cache_id].answer.list);
		return(-1);
	}

	/* check if the query was already made */
        if (find_query(ip))
          return(-1);

	q = alloc_query(client_data, callback, ip);

	/* We need to transform the ip address into the proper form
	 * for reverse lookup. */
	if (strchr(ip, ':')) {
		char temp[128] = "";

		socket_ipv6_to_dots(ip, temp);
sdprintf("dots: %s", temp);
		size_t iplen = strlen(temp) + 9 + 1;
		q->ip = (char *) my_calloc(1, iplen);
//		reverse_ip(temp, q->ip);
		strlcat(q->ip, temp, iplen);
		strlcat(q->ip, "ip6.arpa", iplen);
sdprintf("reversed ipv6 ip: %s", q->ip);
	}
	else {
		size_t iplen = strlen(ip) + 13 + 1;
		q->ip = (char *) my_calloc(1, iplen);
		reverse_ip(ip, q->ip);
		strlcat(q->ip, ".in-addr.arpa", iplen);
	}

        dns_send_query(q);

//	/* setup timer to detect dead ns */
//	dns_create_timeout_timer(&q, ip, timeout);

	return(q->id);
}