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