1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#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);
}
|