3 * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <sys/types.h>
40 #ifdef HAVE_SYS_TIME_H
43 #include <sys/queue.h>
45 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
51 #ifdef HAVE_NETINET_IN6_H
52 #include <netinet/in6.h>
67 static int dns_ok
= 0;
68 static int dns_err
= 0;
73 dns_gethostbyname_cb(int result
, char type
, int count
, int ttl
,
74 void *addresses
, void *arg
)
78 if (result
== DNS_ERR_TIMEOUT
) {
79 fprintf(stdout
, "[Timed out] ");
84 if (result
!= DNS_ERR_NONE
) {
85 fprintf(stdout
, "[Error code %d] ", result
);
89 fprintf(stderr
, "type: %d, count: %d, ttl: %d: ", type
, count
, ttl
);
93 #if defined(HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN)
94 struct in6_addr
*in6_addrs
= addresses
;
95 char buf
[INET6_ADDRSTRLEN
+1];
97 /* a resolution that's not valid does not help */
100 for (i
= 0; i
< count
; ++i
) {
101 const char *b
= inet_ntop(AF_INET6
, &in6_addrs
[i
], buf
,sizeof(buf
));
103 fprintf(stderr
, "%s ", b
);
105 fprintf(stderr
, "%s ", strerror(errno
));
111 struct in_addr
*in_addrs
= addresses
;
113 /* a resolution that's not valid does not help */
116 for (i
= 0; i
< count
; ++i
)
117 fprintf(stderr
, "%s ", inet_ntoa(in_addrs
[i
]));
121 /* may get at most one PTR */
125 fprintf(stderr
, "%s ", *(char **)addresses
);
134 event_loopexit(NULL
);
138 dns_gethostbyname(void)
140 fprintf(stdout
, "Simple DNS resolve: ");
142 evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb
, NULL
);
145 if (dns_ok
== DNS_IPv4_A
) {
146 fprintf(stdout
, "OK\n");
148 fprintf(stdout
, "FAILED\n");
154 dns_gethostbyname6(void)
156 fprintf(stdout
, "IPv6 DNS resolve: ");
158 evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb
, NULL
);
161 if (dns_ok
== DNS_IPv6_AAAA
) {
162 fprintf(stdout
, "OK\n");
163 } else if (!dns_ok
&& dns_err
== DNS_ERR_TIMEOUT
) {
164 fprintf(stdout
, "SKIPPED\n");
166 fprintf(stdout
, "FAILED (%d)\n", dns_ok
);
172 dns_gethostbyaddr(void)
175 in
.s_addr
= htonl(0x7f000001ul
); /* 127.0.0.1 */
176 fprintf(stdout
, "Simple reverse DNS resolve: ");
178 evdns_resolve_reverse(&in
, 0, dns_gethostbyname_cb
, NULL
);
181 if (dns_ok
== DNS_PTR
) {
182 fprintf(stdout
, "OK\n");
184 fprintf(stdout
, "FAILED\n");
189 static int n_server_responses
= 0;
192 dns_server_request_cb(struct evdns_server_request
*req
, void *data
)
195 const char TEST_ARPA
[] = "11.11.168.192.in-addr.arpa";
196 for (i
= 0; i
< req
->nquestions
; ++i
) {
198 ans
.s_addr
= htonl(0xc0a80b0bUL
); /* 192.168.11.11 */
199 if (req
->questions
[i
]->type
== EVDNS_TYPE_A
&&
200 req
->questions
[i
]->dns_question_class
== EVDNS_CLASS_INET
&&
201 !strcmp(req
->questions
[i
]->name
, "zz.example.com")) {
202 r
= evdns_server_request_add_a_reply(req
, "zz.example.com",
203 1, &ans
.s_addr
, 12345);
206 } else if (req
->questions
[i
]->type
== EVDNS_TYPE_AAAA
&&
207 req
->questions
[i
]->dns_question_class
== EVDNS_CLASS_INET
&&
208 !strcmp(req
->questions
[i
]->name
, "zz.example.com")) {
209 char addr6
[17] = "abcdefghijklmnop";
210 r
= evdns_server_request_add_aaaa_reply(req
, "zz.example.com",
214 } else if (req
->questions
[i
]->type
== EVDNS_TYPE_PTR
&&
215 req
->questions
[i
]->dns_question_class
== EVDNS_CLASS_INET
&&
216 !strcmp(req
->questions
[i
]->name
, TEST_ARPA
)) {
217 r
= evdns_server_request_add_ptr_reply(req
, NULL
, TEST_ARPA
,
218 "ZZ.EXAMPLE.COM", 54321);
222 fprintf(stdout
, "Unexpected question %d %d \"%s\" ",
223 req
->questions
[i
]->type
,
224 req
->questions
[i
]->dns_question_class
,
225 req
->questions
[i
]->name
);
229 r
= evdns_server_request_respond(req
, 0);
231 fprintf(stdout
, "Couldn't send reply. ");
237 dns_server_gethostbyname_cb(int result
, char type
, int count
, int ttl
,
238 void *addresses
, void *arg
)
240 if (result
!= DNS_ERR_NONE
) {
241 fprintf(stdout
, "Unexpected result %d. ", result
);
246 fprintf(stdout
, "Unexpected answer count %d. ", count
);
252 struct in_addr
*in_addrs
= addresses
;
253 if (in_addrs
[0].s_addr
!= htonl(0xc0a80b0bUL
) || ttl
!= 12345) {
254 fprintf(stdout
, "Bad IPv4 response \"%s\" %d. ",
255 inet_ntoa(in_addrs
[0]), ttl
);
261 case DNS_IPv6_AAAA
: {
262 #if defined (HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN)
263 struct in6_addr
*in6_addrs
= addresses
;
264 char buf
[INET6_ADDRSTRLEN
+1];
265 if (memcmp(&in6_addrs
[0].s6_addr
, "abcdefghijklmnop", 16)
267 const char *b
= inet_ntop(AF_INET6
, &in6_addrs
[0],buf
,sizeof(buf
));
268 fprintf(stdout
, "Bad IPv6 response \"%s\" %d. ", b
, ttl
);
276 char **addrs
= addresses
;
277 if (strcmp(addrs
[0], "ZZ.EXAMPLE.COM") || ttl
!= 54321) {
278 fprintf(stdout
, "Bad PTR response \"%s\" %d. ",
286 fprintf(stdout
, "Bad response type %d. ", type
);
291 if (++n_server_responses
== 3) {
292 event_loopexit(NULL
);
300 struct sockaddr_in my_addr
;
301 struct evdns_server_port
*port
;
302 struct in_addr resolve_addr
;
305 fprintf(stdout
, "DNS server support: ");
307 /* Add ourself as the only nameserver, and make sure we really are
308 * the only nameserver. */
309 evdns_nameserver_ip_add("127.0.0.1:35353");
310 if (evdns_count_nameservers() != 1) {
311 fprintf(stdout
, "Couldn't set up.\n");
315 /* Now configure a nameserver port. */
316 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
323 u_long nonblocking
= 1;
324 ioctlsocket(sock
, FIONBIO
, &nonblocking
);
327 fcntl(sock
, F_SETFL
, O_NONBLOCK
);
329 memset(&my_addr
, 0, sizeof(my_addr
));
330 my_addr
.sin_family
= AF_INET
;
331 my_addr
.sin_port
= htons(35353);
332 my_addr
.sin_addr
.s_addr
= htonl(0x7f000001UL
);
333 if (bind(sock
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
)) < 0) {
337 port
= evdns_add_server_port(sock
, 0, dns_server_request_cb
, NULL
);
339 /* Send two queries. */
340 evdns_resolve_ipv4("zz.example.com", DNS_QUERY_NO_SEARCH
,
341 dns_server_gethostbyname_cb
, NULL
);
342 evdns_resolve_ipv6("zz.example.com", DNS_QUERY_NO_SEARCH
,
343 dns_server_gethostbyname_cb
, NULL
);
344 resolve_addr
.s_addr
= htonl(0xc0a80b0bUL
); /* 192.168.11.11 */
345 evdns_resolve_reverse(&resolve_addr
, 0,
346 dns_server_gethostbyname_cb
, NULL
);
351 fprintf(stdout
, "OK\n");
353 fprintf(stdout
, "FAILED\n");
357 evdns_close_server_port(port
);
358 evdns_shutdown(0); /* remove ourself as nameserver. */
369 dns_server(); /* Do this before we call evdns_init. */
373 dns_gethostbyname6();