aboutsummaryrefslogtreecommitdiffstats
path: root/libglouglou/libggnet_dns.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglouglou/libggnet_dns.c')
-rw-r--r--libglouglou/libggnet_dns.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/libglouglou/libggnet_dns.c b/libglouglou/libggnet_dns.c
new file mode 100644
index 0000000..9685cde
--- /dev/null
+++ b/libglouglou/libggnet_dns.c
@@ -0,0 +1,113 @@
+#include <stdlib.h>
+#include <string.h>
+
+#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 req_reverse {
+ LIST_ENTRY(req_reverse) entry;
+ struct ggnet_dns *ggdns;
+ struct evdns_request *ereq;
+ struct in_addr ip;
+ void (*cb_usr)(struct in_addr *, char *, void *);
+ void *data;
+};
+
+struct ggnet_dns *
+ggnet_dns_new(struct event_base *ev_base)
+{
+ struct ggnet_dns *dns = NULL;
+
+ dns = calloc(1, sizeof(struct ggnet_dns));
+ if (!dns) {
+ printf("could not allocate ggnet_dns\n");
+ exit(1);
+ }
+ dns->ev_base = ev_base;
+ dns->evdns_base = evdns_base_new(ev_base, 1);
+ if (!dns->evdns_base)
+ goto err;
+ return dns;
+
+err:
+ if (dns)
+ free(dns);
+ return NULL;
+}
+
+void
+ggnet_dns_free(struct ggnet_dns *dns)
+{
+ evdns_base_free(dns->evdns_base, 1);
+ free(dns);
+}
+
+int
+ggnet_dns_reverse(struct ggnet_dns *dns,
+ struct in_addr *ip,
+ void (*cb_usr)(struct in_addr *, char *, void *),
+ void *data)
+{
+ struct evutil_addrinfo hints;
+ struct req_reverse *req;
+ struct evdns_request *ereq;
+
+ 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 req_reverse));
+ if (!req) {
+ printf("could not allocate req_reverse\n");
+ exit(1);
+ }
+ req->ggdns = dns;
+ memcpy(&req->ip, ip, sizeof(struct in_addr));
+ req->cb_usr = cb_usr;
+ req->data = data;
+
+ LIST_INSERT_HEAD(&dns->req_reverse_list, req, entry);
+ dns->req_reverse_pending++;
+ ereq = evdns_base_resolve_reverse(dns->evdns_base, ip, 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 0;
+ }
+ req->ereq = ereq;
+
+ return 1;
+}
+
+static void
+_cb_evdns_reverse(int result, char type, int count,
+ int ttl, void *addresses, void *arg)
+{
+ struct req_reverse *req;
+
+ req = arg;
+ if (type != DNS_PTR) {
+ printf("libggnet_dns WARNING: dns reverse for %d received non DNS_PTR\n",
+ req->ip.s_addr);
+ goto free;
+ }
+ req->cb_usr(&req->ip, addresses, req->data);
+
+free:
+ LIST_REMOVE(req, entry);
+ req->ggdns->req_reverse_pending--;
+ free(req);
+}