| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu> | |
| 3 * All rights reserved. | |
| 4 * | |
| 5 * Redistribution and use in source and binary forms, with or without | |
| 6 * modification, are permitted provided that the following conditions | |
| 7 * are met: | |
| 8 * 1. Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | |
| 11 * notice, this list of conditions and the following disclaimer in the | |
| 12 * documentation and/or other materials provided with the distribution. | |
| 13 * 3. The name of the author may not be used to endorse or promote products | |
| 14 * derived from this software without specific prior written permission. | |
| 15 * | |
| 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
| 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
| 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
| 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
| 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
| 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 */ | |
| 27 | |
| 28 #ifdef WIN32 | |
| 29 #include <winsock2.h> | |
| 30 #include <windows.h> | |
| 31 #endif | |
| 32 | |
| 33 #ifdef HAVE_CONFIG_H | |
| 34 #include "config.h" | |
| 35 #endif | |
| 36 | |
| 37 #include <sys/types.h> | |
| 38 #include <sys/stat.h> | |
| 39 #ifdef HAVE_SYS_TIME_H | |
| 40 #include <sys/time.h> | |
| 41 #endif | |
| 42 #include <sys/queue.h> | |
| 43 #ifndef WIN32 | |
| 44 #include <sys/socket.h> | |
| 45 #include <signal.h> | |
| 46 #include <netinet/in.h> | |
| 47 #include <arpa/inet.h> | |
| 48 #include <unistd.h> | |
| 49 #endif | |
| 50 #ifdef HAVE_NETINET_IN6_H | |
| 51 #include <netinet/in6.h> | |
| 52 #endif | |
| 53 #ifdef HAVE_NETDB_H | |
| 54 #include <netdb.h> | |
| 55 #endif | |
| 56 #include <fcntl.h> | |
| 57 #include <stdlib.h> | |
| 58 #include <stdio.h> | |
| 59 #include <string.h> | |
| 60 #include <errno.h> | |
| 61 | |
| 62 #include "event.h" | |
| 63 #include "evdns.h" | |
| 64 #include "log.h" | |
| 65 | |
| 66 static int dns_ok = 0; | |
| 67 static int dns_err = 0; | |
| 68 | |
| 69 void dns_suite(void); | |
| 70 | |
| 71 static void | |
| 72 dns_gethostbyname_cb(int result, char type, int count, int ttl, | |
| 73 void *addresses, void *arg) | |
| 74 { | |
| 75 dns_ok = dns_err = 0; | |
| 76 | |
| 77 if (result == DNS_ERR_TIMEOUT) { | |
| 78 fprintf(stdout, "[Timed out] "); | |
| 79 dns_err = result; | |
| 80 goto out; | |
| 81 } | |
| 82 | |
| 83 if (result != DNS_ERR_NONE) { | |
| 84 fprintf(stdout, "[Error code %d] ", result); | |
| 85 goto out; | |
| 86 } | |
| 87 | |
| 88 fprintf(stderr, "type: %d, count: %d, ttl: %d: ", type, count, ttl); | |
| 89 | |
| 90 switch (type) { | |
| 91 case DNS_IPv6_AAAA: { | |
| 92 #if defined(HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_NTOP) && defined(INET6_AD
DRSTRLEN) | |
| 93 struct in6_addr *in6_addrs = addresses; | |
| 94 char buf[INET6_ADDRSTRLEN+1]; | |
| 95 int i; | |
| 96 /* a resolution that's not valid does not help */ | |
| 97 if (ttl < 0) | |
| 98 goto out; | |
| 99 for (i = 0; i < count; ++i) { | |
| 100 const char *b = inet_ntop(AF_INET6, &in6_addrs[i], buf,s
izeof(buf)); | |
| 101 if (b) | |
| 102 fprintf(stderr, "%s ", b); | |
| 103 else | |
| 104 fprintf(stderr, "%s ", strerror(errno)); | |
| 105 } | |
| 106 #endif | |
| 107 break; | |
| 108 } | |
| 109 case DNS_IPv4_A: { | |
| 110 struct in_addr *in_addrs = addresses; | |
| 111 int i; | |
| 112 /* a resolution that's not valid does not help */ | |
| 113 if (ttl < 0) | |
| 114 goto out; | |
| 115 for (i = 0; i < count; ++i) | |
| 116 fprintf(stderr, "%s ", inet_ntoa(in_addrs[i])); | |
| 117 break; | |
| 118 } | |
| 119 case DNS_PTR: | |
| 120 /* may get at most one PTR */ | |
| 121 if (count != 1) | |
| 122 goto out; | |
| 123 | |
| 124 fprintf(stderr, "%s ", *(char **)addresses); | |
| 125 break; | |
| 126 default: | |
| 127 goto out; | |
| 128 } | |
| 129 | |
| 130 dns_ok = type; | |
| 131 | |
| 132 out: | |
| 133 event_loopexit(NULL); | |
| 134 } | |
| 135 | |
| 136 static void | |
| 137 dns_gethostbyname(void) | |
| 138 { | |
| 139 fprintf(stdout, "Simple DNS resolve: "); | |
| 140 dns_ok = 0; | |
| 141 evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL); | |
| 142 event_dispatch(); | |
| 143 | |
| 144 if (dns_ok == DNS_IPv4_A) { | |
| 145 fprintf(stdout, "OK\n"); | |
| 146 } else { | |
| 147 fprintf(stdout, "FAILED\n"); | |
| 148 exit(1); | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 static void | |
| 153 dns_gethostbyname6(void) | |
| 154 { | |
| 155 fprintf(stdout, "IPv6 DNS resolve: "); | |
| 156 dns_ok = 0; | |
| 157 evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL); | |
| 158 event_dispatch(); | |
| 159 | |
| 160 if (dns_ok == DNS_IPv6_AAAA) { | |
| 161 fprintf(stdout, "OK\n"); | |
| 162 } else if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) { | |
| 163 fprintf(stdout, "SKIPPED\n"); | |
| 164 } else { | |
| 165 fprintf(stdout, "FAILED (%d)\n", dns_ok); | |
| 166 exit(1); | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 static void | |
| 171 dns_gethostbyaddr(void) | |
| 172 { | |
| 173 struct in_addr in; | |
| 174 in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ | |
| 175 fprintf(stdout, "Simple reverse DNS resolve: "); | |
| 176 dns_ok = 0; | |
| 177 evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL); | |
| 178 event_dispatch(); | |
| 179 | |
| 180 if (dns_ok == DNS_PTR) { | |
| 181 fprintf(stdout, "OK\n"); | |
| 182 } else { | |
| 183 fprintf(stdout, "FAILED\n"); | |
| 184 exit(1); | |
| 185 } | |
| 186 } | |
| 187 | |
| 188 static int n_server_responses = 0; | |
| 189 | |
| 190 static void | |
| 191 dns_server_request_cb(struct evdns_server_request *req, void *data) | |
| 192 { | |
| 193 int i, r; | |
| 194 const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa"; | |
| 195 for (i = 0; i < req->nquestions; ++i) { | |
| 196 struct in_addr ans; | |
| 197 ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ | |
| 198 if (req->questions[i]->type == EVDNS_TYPE_A && | |
| 199 req->questions[i]->dns_question_class == EVDNS_CLASS_INE
T && | |
| 200 !strcmp(req->questions[i]->name, "zz.example.com")) { | |
| 201 r = evdns_server_request_add_a_reply(req, "zz.example.co
m", | |
| 202
1, &ans.s_addr, 12345); | |
| 203 if (r<0) | |
| 204 dns_ok = 0; | |
| 205 } else if (req->questions[i]->type == EVDNS_TYPE_AAAA && | |
| 206 req->questions[i]->dns_question_class == EVDN
S_CLASS_INET && | |
| 207 !strcmp(req->questions[i]->name, "zz.example.
com")) { | |
| 208 char addr6[17] = "abcdefghijklmnop"; | |
| 209 r = evdns_server_request_add_aaaa_reply(req, "zz.example
.com", | |
| 210
1, addr6, 123); | |
| 211 if (r<0) | |
| 212 dns_ok = 0; | |
| 213 } else if (req->questions[i]->type == EVDNS_TYPE_PTR && | |
| 214 req->questions[i]->dns_question_class == EVDN
S_CLASS_INET && | |
| 215 !strcmp(req->questions[i]->name, TEST_ARPA))
{ | |
| 216 r = evdns_server_request_add_ptr_reply(req, NULL, TEST_A
RPA, | |
| 217 "ZZ.EXAMPLE.COM", 54321); | |
| 218 if (r<0) | |
| 219 dns_ok = 0; | |
| 220 } else { | |
| 221 fprintf(stdout, "Unexpected question %d %d \"%s\" ", | |
| 222 req->questions[i]->type, | |
| 223 req->questions[i]->dns_question_class, | |
| 224 req->questions[i]->name); | |
| 225 dns_ok = 0; | |
| 226 } | |
| 227 } | |
| 228 r = evdns_server_request_respond(req, 0); | |
| 229 if (r<0) { | |
| 230 fprintf(stdout, "Couldn't send reply. "); | |
| 231 dns_ok = 0; | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 static void | |
| 236 dns_server_gethostbyname_cb(int result, char type, int count, int ttl, | |
| 237 void *addresses, void *a
rg) | |
| 238 { | |
| 239 if (result != DNS_ERR_NONE) { | |
| 240 fprintf(stdout, "Unexpected result %d. ", result); | |
| 241 dns_ok = 0; | |
| 242 goto out; | |
| 243 } | |
| 244 if (count != 1) { | |
| 245 fprintf(stdout, "Unexpected answer count %d. ", count); | |
| 246 dns_ok = 0; | |
| 247 goto out; | |
| 248 } | |
| 249 switch (type) { | |
| 250 case DNS_IPv4_A: { | |
| 251 struct in_addr *in_addrs = addresses; | |
| 252 if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) { | |
| 253 fprintf(stdout, "Bad IPv4 response \"%s\" %d. ", | |
| 254 inet_ntoa(in_addrs[0]), ttl); | |
| 255 dns_ok = 0; | |
| 256 goto out; | |
| 257 } | |
| 258 break; | |
| 259 } | |
| 260 case DNS_IPv6_AAAA: { | |
| 261 #if defined (HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_NTOP) && defined(INET6_A
DDRSTRLEN) | |
| 262 struct in6_addr *in6_addrs = addresses; | |
| 263 char buf[INET6_ADDRSTRLEN+1]; | |
| 264 if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16) | |
| 265 || ttl != 123) { | |
| 266 const char *b = inet_ntop(AF_INET6, &in6_addrs[0],buf,si
zeof(buf)); | |
| 267 fprintf(stdout, "Bad IPv6 response \"%s\" %d. ", b, ttl)
; | |
| 268 dns_ok = 0; | |
| 269 goto out; | |
| 270 } | |
| 271 #endif | |
| 272 break; | |
| 273 } | |
| 274 case DNS_PTR: { | |
| 275 char **addrs = addresses; | |
| 276 if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") || ttl != 54321) { | |
| 277 fprintf(stdout, "Bad PTR response \"%s\" %d. ", | |
| 278 addrs[0], ttl); | |
| 279 dns_ok = 0; | |
| 280 goto out; | |
| 281 } | |
| 282 break; | |
| 283 } | |
| 284 default: | |
| 285 fprintf(stdout, "Bad response type %d. ", type); | |
| 286 dns_ok = 0; | |
| 287 } | |
| 288 | |
| 289 out: | |
| 290 if (++n_server_responses == 3) { | |
| 291 event_loopexit(NULL); | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 static void | |
| 296 dns_server(void) | |
| 297 { | |
| 298 int sock; | |
| 299 struct sockaddr_in my_addr; | |
| 300 struct evdns_server_port *port; | |
| 301 struct in_addr resolve_addr; | |
| 302 | |
| 303 dns_ok = 1; | |
| 304 fprintf(stdout, "DNS server support: "); | |
| 305 | |
| 306 /* Add ourself as the only nameserver, and make sure we really are | |
| 307 * the only nameserver. */ | |
| 308 evdns_nameserver_ip_add("127.0.0.1:35353"); | |
| 309 if (evdns_count_nameservers() != 1) { | |
| 310 fprintf(stdout, "Couldn't set up.\n"); | |
| 311 exit(1); | |
| 312 } | |
| 313 | |
| 314 /* Now configure a nameserver port. */ | |
| 315 sock = socket(AF_INET, SOCK_DGRAM, 0); | |
| 316 if (sock == -1) { | |
| 317 perror("socket"); | |
| 318 exit(1); | |
| 319 } | |
| 320 #ifdef WIN32 | |
| 321 { | |
| 322 u_long nonblocking = 1; | |
| 323 ioctlsocket(sock, FIONBIO, &nonblocking); | |
| 324 } | |
| 325 #else | |
| 326 fcntl(sock, F_SETFL, O_NONBLOCK); | |
| 327 #endif | |
| 328 memset(&my_addr, 0, sizeof(my_addr)); | |
| 329 my_addr.sin_family = AF_INET; | |
| 330 my_addr.sin_port = htons(35353); | |
| 331 my_addr.sin_addr.s_addr = htonl(0x7f000001UL); | |
| 332 if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) { | |
| 333 perror("bind"); | |
| 334 exit (1); | |
| 335 } | |
| 336 port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL); | |
| 337 | |
| 338 /* Send two queries. */ | |
| 339 evdns_resolve_ipv4("zz.example.com", DNS_QUERY_NO_SEARCH, | |
| 340 dns_server_gethostbyname_cb, NULL); | |
| 341 evdns_resolve_ipv6("zz.example.com", DNS_QUERY_NO_SEARCH, | |
| 342 dns_server_gethostbyname_cb, NULL); | |
| 343 resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ | |
| 344 evdns_resolve_reverse(&resolve_addr, 0, | |
| 345 dns_server_gethostbyname_cb, N
ULL); | |
| 346 | |
| 347 event_dispatch(); | |
| 348 | |
| 349 if (dns_ok) { | |
| 350 fprintf(stdout, "OK\n"); | |
| 351 } else { | |
| 352 fprintf(stdout, "FAILED\n"); | |
| 353 exit(1); | |
| 354 } | |
| 355 | |
| 356 evdns_close_server_port(port); | |
| 357 evdns_shutdown(0); /* remove ourself as nameserver. */ | |
| 358 #ifdef WIN32 | |
| 359 closesocket(sock); | |
| 360 #else | |
| 361 close(sock); | |
| 362 #endif | |
| 363 } | |
| 364 | |
| 365 void | |
| 366 dns_suite(void) | |
| 367 { | |
| 368 dns_server(); /* Do this before we call evdns_init. */ | |
| 369 | |
| 370 evdns_init(); | |
| 371 dns_gethostbyname(); | |
| 372 dns_gethostbyname6(); | |
| 373 dns_gethostbyaddr(); | |
| 374 | |
| 375 evdns_shutdown(0); | |
| 376 } | |
| OLD | NEW |