aboutsummaryrefslogblamecommitdiffstats
path: root/libglouglou/libggnet_dns.c
blob: c6f8ccec3c39825a7c2ef9d83b8a0fcf3c72070f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                                      


                                         











                                                         

    


                            


    
                                       
 

                                              

 
                      
                                          


                                                                 
 



































                                                                                         




                                                                    

                                                                        



                                                   
                                                      
 















                                                                                 
 
#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 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);
}