File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libevent / test / regress_dns.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:02:54 2012 UTC (12 years, 8 months ago) by misho
Branches: libevent, MAIN
CVS tags: v1_4_14bp0, v1_4_14b, HEAD
libevent

    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>