summaryrefslogtreecommitdiffstats
path: root/third_party/libevent/test/regress_dns.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libevent/test/regress_dns.c')
-rw-r--r--third_party/libevent/test/regress_dns.c376
1 files changed, 376 insertions, 0 deletions
diff --git a/third_party/libevent/test/regress_dns.c b/third_party/libevent/test/regress_dns.c
new file mode 100644
index 0000000..8191192
--- /dev/null
+++ b/third_party/libevent/test/regress_dns.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/queue.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "event.h"
+#include "evdns.h"
+#include "log.h"
+
+static int dns_ok = 0;
+static int dns_err = 0;
+
+void dns_suite(void);
+
+static void
+dns_gethostbyname_cb(int result, char type, int count, int ttl,
+ void *addresses, void *arg)
+{
+ dns_ok = dns_err = 0;
+
+ if (result == DNS_ERR_TIMEOUT) {
+ fprintf(stdout, "[Timed out] ");
+ dns_err = result;
+ goto out;
+ }
+
+ if (result != DNS_ERR_NONE) {
+ fprintf(stdout, "[Error code %d] ", result);
+ goto out;
+ }
+
+ fprintf(stderr, "type: %d, count: %d, ttl: %d: ", type, count, ttl);
+
+ switch (type) {
+ case DNS_IPv6_AAAA: {
+#if defined(HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_NTOP)
+ struct in6_addr *in6_addrs = addresses;
+ char buf[INET6_ADDRSTRLEN+1];
+ int i;
+ /* a resolution that's not valid does not help */
+ if (ttl < 0)
+ goto out;
+ for (i = 0; i < count; ++i) {
+ const char *b = inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf));
+ if (b)
+ fprintf(stderr, "%s ", b);
+ else
+ fprintf(stderr, "%s ", strerror(errno));
+ }
+#endif
+ break;
+ }
+ case DNS_IPv4_A: {
+ struct in_addr *in_addrs = addresses;
+ int i;
+ /* a resolution that's not valid does not help */
+ if (ttl < 0)
+ goto out;
+ for (i = 0; i < count; ++i)
+ fprintf(stderr, "%s ", inet_ntoa(in_addrs[i]));
+ break;
+ }
+ case DNS_PTR:
+ /* may get at most one PTR */
+ if (count != 1)
+ goto out;
+
+ fprintf(stderr, "%s ", *(char **)addresses);
+ break;
+ default:
+ goto out;
+ }
+
+ dns_ok = type;
+
+out:
+ event_loopexit(NULL);
+}
+
+static void
+dns_gethostbyname(void)
+{
+ fprintf(stdout, "Simple DNS resolve: ");
+ dns_ok = 0;
+ evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL);
+ event_dispatch();
+
+ if (dns_ok == DNS_IPv4_A) {
+ fprintf(stdout, "OK\n");
+ } else {
+ fprintf(stdout, "FAILED\n");
+ exit(1);
+ }
+}
+
+static void
+dns_gethostbyname6(void)
+{
+ fprintf(stdout, "IPv6 DNS resolve: ");
+ dns_ok = 0;
+ evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL);
+ event_dispatch();
+
+ if (dns_ok == DNS_IPv6_AAAA) {
+ fprintf(stdout, "OK\n");
+ } else if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) {
+ fprintf(stdout, "SKIPPED\n");
+ } else {
+ fprintf(stdout, "FAILED (%d)\n", dns_ok);
+ exit(1);
+ }
+}
+
+static void
+dns_gethostbyaddr(void)
+{
+ struct in_addr in;
+ in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */
+ fprintf(stdout, "Simple reverse DNS resolve: ");
+ dns_ok = 0;
+ evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL);
+ event_dispatch();
+
+ if (dns_ok == DNS_PTR) {
+ fprintf(stdout, "OK\n");
+ } else {
+ fprintf(stdout, "FAILED\n");
+ exit(1);
+ }
+}
+
+static int n_server_responses = 0;
+
+static void
+dns_server_request_cb(struct evdns_server_request *req, void *data)
+{
+ int i, r;
+ const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa";
+ for (i = 0; i < req->nquestions; ++i) {
+ struct in_addr ans;
+ ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */
+ if (req->questions[i]->type == EVDNS_TYPE_A &&
+ req->questions[i]->dns_question_class == EVDNS_CLASS_INET &&
+ !strcmp(req->questions[i]->name, "zz.example.com")) {
+ r = evdns_server_request_add_a_reply(req, "zz.example.com",
+ 1, &ans.s_addr, 12345);
+ if (r<0)
+ dns_ok = 0;
+ } else if (req->questions[i]->type == EVDNS_TYPE_AAAA &&
+ req->questions[i]->dns_question_class == EVDNS_CLASS_INET &&
+ !strcmp(req->questions[i]->name, "zz.example.com")) {
+ char addr6[17] = "abcdefghijklmnop";
+ r = evdns_server_request_add_aaaa_reply(req, "zz.example.com",
+ 1, addr6, 123);
+ if (r<0)
+ dns_ok = 0;
+ } else if (req->questions[i]->type == EVDNS_TYPE_PTR &&
+ req->questions[i]->dns_question_class == EVDNS_CLASS_INET &&
+ !strcmp(req->questions[i]->name, TEST_ARPA)) {
+ r = evdns_server_request_add_ptr_reply(req, NULL, TEST_ARPA,
+ "ZZ.EXAMPLE.COM", 54321);
+ if (r<0)
+ dns_ok = 0;
+ } else {
+ fprintf(stdout, "Unexpected question %d %d \"%s\" ",
+ req->questions[i]->type,
+ req->questions[i]->dns_question_class,
+ req->questions[i]->name);
+ dns_ok = 0;
+ }
+ }
+ r = evdns_server_request_respond(req, 0);
+ if (r<0) {
+ fprintf(stdout, "Couldn't send reply. ");
+ dns_ok = 0;
+ }
+}
+
+static void
+dns_server_gethostbyname_cb(int result, char type, int count, int ttl,
+ void *addresses, void *arg)
+{
+ if (result != DNS_ERR_NONE) {
+ fprintf(stdout, "Unexpected result %d. ", result);
+ dns_ok = 0;
+ goto out;
+ }
+ if (count != 1) {
+ fprintf(stdout, "Unexpected answer count %d. ", count);
+ dns_ok = 0;
+ goto out;
+ }
+ switch (type) {
+ case DNS_IPv4_A: {
+ struct in_addr *in_addrs = addresses;
+ if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) {
+ fprintf(stdout, "Bad IPv4 response \"%s\" %d. ",
+ inet_ntoa(in_addrs[0]), ttl);
+ dns_ok = 0;
+ goto out;
+ }
+ break;
+ }
+ case DNS_IPv6_AAAA: {
+#if defined (HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_NTOP)
+ struct in6_addr *in6_addrs = addresses;
+ char buf[INET6_ADDRSTRLEN+1];
+ if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16)
+ || ttl != 123) {
+ const char *b = inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf));
+ fprintf(stdout, "Bad IPv6 response \"%s\" %d. ", b, ttl);
+ dns_ok = 0;
+ goto out;
+ }
+#endif
+ break;
+ }
+ case DNS_PTR: {
+ char **addrs = addresses;
+ if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") || ttl != 54321) {
+ fprintf(stdout, "Bad PTR response \"%s\" %d. ",
+ addrs[0], ttl);
+ dns_ok = 0;
+ goto out;
+ }
+ break;
+ }
+ default:
+ fprintf(stdout, "Bad response type %d. ", type);
+ dns_ok = 0;
+ }
+
+ out:
+ if (++n_server_responses == 3) {
+ event_loopexit(NULL);
+ }
+}
+
+static void
+dns_server(void)
+{
+ int sock;
+ struct sockaddr_in my_addr;
+ struct evdns_server_port *port;
+ struct in_addr resolve_addr;
+
+ dns_ok = 1;
+ fprintf(stdout, "DNS server support: ");
+
+ /* Add ourself as the only nameserver, and make sure we really are
+ * the only nameserver. */
+ evdns_nameserver_ip_add("127.0.0.1:35353");
+ if (evdns_count_nameservers() != 1) {
+ fprintf(stdout, "Couldn't set up.\n");
+ exit(1);
+ }
+
+ /* Now configure a nameserver port. */
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ perror("socket");
+ exit(1);
+ }
+#ifdef WIN32
+ {
+ u_long nonblocking = 1;
+ ioctlsocket(sock, FIONBIO, &nonblocking);
+ }
+#else
+ fcntl(sock, F_SETFL, O_NONBLOCK);
+#endif
+ memset(&my_addr, 0, sizeof(my_addr));
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = htons(35353);
+ my_addr.sin_addr.s_addr = htonl(0x7f000001UL);
+ if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) {
+ perror("bind");
+ exit (1);
+ }
+ port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL);
+
+ /* Send two queries. */
+ evdns_resolve_ipv4("zz.example.com", DNS_QUERY_NO_SEARCH,
+ dns_server_gethostbyname_cb, NULL);
+ evdns_resolve_ipv6("zz.example.com", DNS_QUERY_NO_SEARCH,
+ dns_server_gethostbyname_cb, NULL);
+ resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */
+ evdns_resolve_reverse(&resolve_addr, 0,
+ dns_server_gethostbyname_cb, NULL);
+
+ event_dispatch();
+
+ if (dns_ok) {
+ fprintf(stdout, "OK\n");
+ } else {
+ fprintf(stdout, "FAILED\n");
+ exit(1);
+ }
+
+ evdns_close_server_port(port);
+ evdns_shutdown(0); /* remove ourself as nameserver. */
+#ifdef WIN32
+ closesocket(sock);
+#else
+ close(sock);
+#endif
+}
+
+void
+dns_suite(void)
+{
+ dns_server(); /* Do this before we call evdns_init. */
+
+ evdns_init();
+ dns_gethostbyname();
+ dns_gethostbyname6();
+ dns_gethostbyaddr();
+
+ evdns_shutdown(0);
+}