Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / libevent / dist / test / regress_dns.c
blob2b4af8b4ac94628feb4a04934a90aa96bd735dab
1 /* $NetBSD$ */
2 /*
3 * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu>
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
29 #ifdef WIN32
30 #include <winsock2.h>
31 #include <windows.h>
32 #endif
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #ifdef HAVE_SYS_TIME_H
41 #include <sys/time.h>
42 #endif
43 #include <sys/queue.h>
44 #ifndef WIN32
45 #include <sys/socket.h>
46 #include <signal.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49 #include <unistd.h>
50 #endif
51 #ifdef HAVE_NETINET_IN6_H
52 #include <netinet/in6.h>
53 #endif
54 #ifdef HAVE_NETDB_H
55 #include <netdb.h>
56 #endif
57 #include <fcntl.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <string.h>
61 #include <errno.h>
63 #include "event.h"
64 #include "evdns.h"
65 #include "log.h"
67 static int dns_ok = 0;
68 static int dns_err = 0;
70 void dns_suite(void);
72 static void
73 dns_gethostbyname_cb(int result, char type, int count, int ttl,
74 void *addresses, void *arg)
76 dns_ok = dns_err = 0;
78 if (result == DNS_ERR_TIMEOUT) {
79 fprintf(stdout, "[Timed out] ");
80 dns_err = result;
81 goto out;
84 if (result != DNS_ERR_NONE) {
85 fprintf(stdout, "[Error code %d] ", result);
86 goto out;
89 fprintf(stderr, "type: %d, count: %d, ttl: %d: ", type, count, ttl);
91 switch (type) {
92 case DNS_IPv6_AAAA: {
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];
96 int i;
97 /* a resolution that's not valid does not help */
98 if (ttl < 0)
99 goto out;
100 for (i = 0; i < count; ++i) {
101 const char *b = inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf));
102 if (b)
103 fprintf(stderr, "%s ", b);
104 else
105 fprintf(stderr, "%s ", strerror(errno));
107 #endif
108 break;
110 case DNS_IPv4_A: {
111 struct in_addr *in_addrs = addresses;
112 int i;
113 /* a resolution that's not valid does not help */
114 if (ttl < 0)
115 goto out;
116 for (i = 0; i < count; ++i)
117 fprintf(stderr, "%s ", inet_ntoa(in_addrs[i]));
118 break;
120 case DNS_PTR:
121 /* may get at most one PTR */
122 if (count != 1)
123 goto out;
125 fprintf(stderr, "%s ", *(char **)addresses);
126 break;
127 default:
128 goto out;
131 dns_ok = type;
133 out:
134 event_loopexit(NULL);
137 static void
138 dns_gethostbyname(void)
140 fprintf(stdout, "Simple DNS resolve: ");
141 dns_ok = 0;
142 evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL);
143 event_dispatch();
145 if (dns_ok == DNS_IPv4_A) {
146 fprintf(stdout, "OK\n");
147 } else {
148 fprintf(stdout, "FAILED\n");
149 exit(1);
153 static void
154 dns_gethostbyname6(void)
156 fprintf(stdout, "IPv6 DNS resolve: ");
157 dns_ok = 0;
158 evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL);
159 event_dispatch();
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");
165 } else {
166 fprintf(stdout, "FAILED (%d)\n", dns_ok);
167 exit(1);
171 static void
172 dns_gethostbyaddr(void)
174 struct in_addr in;
175 in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */
176 fprintf(stdout, "Simple reverse DNS resolve: ");
177 dns_ok = 0;
178 evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL);
179 event_dispatch();
181 if (dns_ok == DNS_PTR) {
182 fprintf(stdout, "OK\n");
183 } else {
184 fprintf(stdout, "FAILED\n");
185 exit(1);
189 static int n_server_responses = 0;
191 static void
192 dns_server_request_cb(struct evdns_server_request *req, void *data)
194 int i, r;
195 const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa";
196 for (i = 0; i < req->nquestions; ++i) {
197 struct in_addr ans;
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);
204 if (r<0)
205 dns_ok = 0;
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",
211 1, addr6, 123);
212 if (r<0)
213 dns_ok = 0;
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);
219 if (r<0)
220 dns_ok = 0;
221 } else {
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);
226 dns_ok = 0;
229 r = evdns_server_request_respond(req, 0);
230 if (r<0) {
231 fprintf(stdout, "Couldn't send reply. ");
232 dns_ok = 0;
236 static void
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);
242 dns_ok = 0;
243 goto out;
245 if (count != 1) {
246 fprintf(stdout, "Unexpected answer count %d. ", count);
247 dns_ok = 0;
248 goto out;
250 switch (type) {
251 case DNS_IPv4_A: {
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);
256 dns_ok = 0;
257 goto out;
259 break;
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)
266 || ttl != 123) {
267 const char *b = inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf));
268 fprintf(stdout, "Bad IPv6 response \"%s\" %d. ", b, ttl);
269 dns_ok = 0;
270 goto out;
272 #endif
273 break;
275 case DNS_PTR: {
276 char **addrs = addresses;
277 if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") || ttl != 54321) {
278 fprintf(stdout, "Bad PTR response \"%s\" %d. ",
279 addrs[0], ttl);
280 dns_ok = 0;
281 goto out;
283 break;
285 default:
286 fprintf(stdout, "Bad response type %d. ", type);
287 dns_ok = 0;
290 out:
291 if (++n_server_responses == 3) {
292 event_loopexit(NULL);
296 static void
297 dns_server(void)
299 int sock;
300 struct sockaddr_in my_addr;
301 struct evdns_server_port *port;
302 struct in_addr resolve_addr;
304 dns_ok = 1;
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");
312 exit(1);
315 /* Now configure a nameserver port. */
316 sock = socket(AF_INET, SOCK_DGRAM, 0);
317 if (sock == -1) {
318 perror("socket");
319 exit(1);
321 #ifdef WIN32
323 u_long nonblocking = 1;
324 ioctlsocket(sock, FIONBIO, &nonblocking);
326 #else
327 fcntl(sock, F_SETFL, O_NONBLOCK);
328 #endif
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) {
334 perror("bind");
335 exit (1);
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);
348 event_dispatch();
350 if (dns_ok) {
351 fprintf(stdout, "OK\n");
352 } else {
353 fprintf(stdout, "FAILED\n");
354 exit(1);
357 evdns_close_server_port(port);
358 evdns_shutdown(0); /* remove ourself as nameserver. */
359 #ifdef WIN32
360 closesocket(sock);
361 #else
362 close(sock);
363 #endif
366 void
367 dns_suite(void)
369 dns_server(); /* Do this before we call evdns_init. */
371 evdns_init();
372 dns_gethostbyname();
373 dns_gethostbyname6();
374 dns_gethostbyaddr();
376 evdns_shutdown(0);