/* 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); }
/** @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); }
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)); }
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); }
/* 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); }