#include #include #include "libggnet_dns.h" /* * For dns with libevent, see * http://www.wangafu.net/~nickm/libevent-2.0/doxygen/html/dns_8h.html * http://www.wangafu.net/~nickm/libevent-book/Ref9_dns.html * spike/evdns_chrooted.c * spike/evdns.c */ static void _cb_evdns_reverse(int, char, int, int, void *, void *); struct ggnet_dns * ggnet_dns_new(struct event_base *ev_base) { struct ggnet_dns *ggdns = NULL; ggdns = calloc(1, sizeof(struct ggnet_dns)); if (!ggdns) { printf("could not allocate ggnet_dns\n"); exit(1); } ggdns->ev_base = ev_base; ggdns->evdns_base = evdns_base_new(ev_base, 1); if (!ggdns->evdns_base) goto err; return ggdns; err: if (ggdns) free(ggdns); return NULL; } void ggnet_dns_free(struct ggnet_dns *ggdns) { evdns_base_free(ggdns->evdns_base, 1); free(ggdns); } struct ggnet_dns_req * ggnet_dns_reverse(struct ggnet_dns *ggdns, struct in_addr *ip, void (*cb_usr)(struct in_addr *, char *, void *), void *data) { struct evutil_addrinfo hints; struct ggnet_dns_req *req; struct evdns_request *ereq; struct in_addr nip; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_flags = EVUTIL_AI_CANONNAME; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; req = malloc(sizeof(struct ggnet_dns_req)); if (!req) { printf("could not allocate ggnet_dns_req\n"); exit(1); } req->ggdns = ggdns; memcpy(&req->ip, ip, sizeof(struct in_addr)); req->cb_usr = cb_usr; req->data = data; nip.s_addr = htonl(ip->s_addr); /* evdns eats network byte order */ LIST_INSERT_HEAD(&ggdns->req_list, req, entry); ggdns->req_pending++; ereq = evdns_base_resolve_reverse(ggdns->evdns_base, &nip, 0, _cb_evdns_reverse, req); if (ereq == NULL) { printf("libggnet_dns WARNING: dns request for %d returned immediately\n", ip->s_addr); /* remove req from list and free it happened in the callback. */ return NULL; } req->ereq = ereq; return req; } void ggnet_dns_cancel(struct ggnet_dns *ggdns, struct ggnet_dns_req *req) { evdns_cancel_request(ggdns->evdns_base, req->ereq); /* remove req from list and free it happened in the callback. */ } static void _cb_evdns_reverse(int result, char type, int count, int ttl, void *addresses, void *arg) { struct ggnet_dns_req *req; char **name; if (count > 1) printf("libggnet_dns XXX: has %d PTR records !\n", count); // XXX req = arg; name = addresses; if (result != DNS_ERR_NONE || count == 0) req->cb_usr(&req->ip, NULL, req->data); else req->cb_usr(&req->ip, *name, req->data); LIST_REMOVE(req, entry); req->ggdns->req_pending--; free(req); }