Annotation of embedaddon/libevent/test/regress_dns.c, revision 1.1
1.1 ! misho 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_ADDRSTRLEN)
! 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,sizeof(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_INET &&
! 200: !strcmp(req->questions[i]->name, "zz.example.com")) {
! 201: r = evdns_server_request_add_a_reply(req, "zz.example.com",
! 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 == EVDNS_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 == EVDNS_CLASS_INET &&
! 215: !strcmp(req->questions[i]->name, TEST_ARPA)) {
! 216: r = evdns_server_request_add_ptr_reply(req, NULL, TEST_ARPA,
! 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 *arg)
! 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_ADDRSTRLEN)
! 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,sizeof(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, NULL);
! 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>