resolv_test.c revision 243346
1122394Sharti/*	$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $	*/
2122394Sharti
3122394Sharti/*-
4122394Sharti * Copyright (c) 2004 The NetBSD Foundation, Inc.
5122394Sharti * All rights reserved.
6122394Sharti *
7310901Sngie * This code is derived from software contributed to The NetBSD Foundation
8133211Sharti * by Christos Zoulas.
9133211Sharti *
10133211Sharti * Redistribution and use in source and binary forms, with or without
11133211Sharti * modification, are permitted provided that the following conditions
12133211Sharti * are met:
13122394Sharti * 1. Redistributions of source code must retain the above copyright
14122394Sharti *    notice, this list of conditions and the following disclaimer.
15122394Sharti * 2. Redistributions in binary form must reproduce the above copyright
16310901Sngie *    notice, this list of conditions and the following disclaimer in the
17133211Sharti *    documentation and/or other materials provided with the distribution.
18133211Sharti *
19133211Sharti * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20133211Sharti * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21133211Sharti * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22133211Sharti * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23133211Sharti * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24133211Sharti * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25133211Sharti * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26133211Sharti * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27133211Sharti * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28122394Sharti * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29156066Sharti * POSSIBILITY OF SUCH DAMAGE.
30122394Sharti */
31122394Sharti/* $FreeBSD: head/tools/regression/lib/libc/resolv/resolv.c 243346 2012-11-20 19:23:44Z emaste $ */
32122394Sharti#include <sys/cdefs.h>
33122394Sharti__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $");
34122394Sharti
35122394Sharti#include <sys/types.h>
36122394Sharti#include <sys/socket.h>
37122394Sharti#include <pthread.h>
38150920Sharti#include <stdio.h>
39133211Sharti#include <netdb.h>
40150920Sharti#include <stdlib.h>
41150920Sharti#include <unistd.h>
42150920Sharti#include <err.h>
43122394Sharti#include <string.h>
44156066Sharti#include <stringlist.h>
45156066Sharti
46122394Sharti#define NTHREADS	10
47122394Sharti#define NHOSTS		100
48122394Sharti#define WS		" \t\n\r"
49122394Sharti
50122394Shartienum method {
51122394Sharti	METHOD_GETADDRINFO,
52122394Sharti	METHOD_GETHOSTBY,
53122394Sharti	METHOD_GETIPNODEBY
54122394Sharti};
55122394Sharti
56122394Shartistatic StringList *hosts = NULL;
57122394Shartistatic int debug = 0;
58122394Shartistatic enum method method = METHOD_GETADDRINFO;
59122394Shartistatic int reverse = 0;
60122394Shartistatic int *ask = NULL;
61122394Shartistatic int *got = NULL;
62122394Sharti
63122394Shartistatic void usage(void)  __attribute__((__noreturn__));
64122394Shartistatic void load(const char *);
65122394Shartistatic void resolvone(int);
66122394Shartistatic void *resolvloop(void *);
67122394Shartistatic void run(int *);
68122394Sharti
69122394Shartistatic pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
70122394Sharti
71122394Shartistatic void
72122394Shartiusage(void)
73122394Sharti{
74122394Sharti	(void)fprintf(stderr,
75122394Sharti	    "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
76122394Sharti	    getprogname());
77122394Sharti	exit(1);
78122394Sharti}
79122394Sharti
80122394Shartistatic void
81122394Shartiload(const char *fname)
82122394Sharti{
83122394Sharti	FILE *fp;
84122394Sharti	size_t len;
85122394Sharti	char *line;
86122394Sharti
87122394Sharti	if ((fp = fopen(fname, "r")) == NULL)
88122394Sharti		err(1, "Cannot open `%s'", fname);
89122394Sharti	while ((line = fgetln(fp, &len)) != NULL) {
90122394Sharti		char c = line[len];
91122394Sharti		char *ptr;
92122394Sharti		line[len] = '\0';
93122394Sharti		for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS))
94122394Sharti			sl_add(hosts, strdup(ptr));
95122394Sharti		line[len] = c;
96122394Sharti	}
97122394Sharti
98122394Sharti	(void)fclose(fp);
99122394Sharti}
100122394Sharti
101122394Shartistatic int
102122394Shartiresolv_getaddrinfo(pthread_t self, char *host, int port)
103350638Semaste{
104350638Semaste	char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
105350638Semaste	struct addrinfo hints, *res;
106350638Semaste	int error, len;
107350638Semaste
108122394Sharti	snprintf(portstr, sizeof(portstr), "%d", port);
109122394Sharti	memset(&hints, 0, sizeof(hints));
110122394Sharti	hints.ai_family = AF_UNSPEC;
111122394Sharti	hints.ai_flags = AI_PASSIVE;
112122394Sharti	hints.ai_socktype = SOCK_STREAM;
113122394Sharti	error = getaddrinfo(host, portstr, &hints, &res);
114122394Sharti	if (debug) {
115122394Sharti		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
116122394Sharti		    self, host, error ? "not found" : "ok");
117122394Sharti		(void)write(STDOUT_FILENO, buf, len);
118122394Sharti	}
119122394Sharti	if (error == 0 && reverse) {
120122394Sharti		memset(hbuf, 0, sizeof(hbuf));
121122394Sharti		memset(pbuf, 0, sizeof(pbuf));
122122394Sharti		getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
123122394Sharti			    pbuf, sizeof(pbuf), 0);
124122394Sharti		if (debug) {
125122394Sharti			len = snprintf(buf, sizeof(buf),
126122394Sharti			    "%p: reverse %s %s\n", self, hbuf, pbuf);
127122394Sharti			(void)write(STDOUT_FILENO, buf, len);
128122394Sharti		}
129122394Sharti	}
130122394Sharti	if (error == 0)
131122394Sharti		freeaddrinfo(res);
132122394Sharti	return error;
133122394Sharti}
134122394Sharti
135122394Shartistatic int
136122394Shartiresolv_gethostby(pthread_t self, char *host)
137122394Sharti{
138122394Sharti	char buf[1024];
139122394Sharti	struct hostent *hp, *hp2;
140122394Sharti	int len;
141122394Sharti
142122394Sharti	hp = gethostbyname(host);
143122394Sharti	if (debug) {
144122394Sharti		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
145122394Sharti		    self, host, (hp == NULL) ? "not found" : "ok");
146122394Sharti		(void)write(STDOUT_FILENO, buf, len);
147122394Sharti	}
148122394Sharti	if (hp && reverse) {
149122394Sharti		memcpy(buf, hp->h_addr, hp->h_length);
150122394Sharti		hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype);
151122394Sharti		if (hp2 && debug) {
152122394Sharti			len = snprintf(buf, sizeof(buf),
153122394Sharti			    "%p: reverse %s\n", self, hp2->h_name);
154122394Sharti			(void)write(STDOUT_FILENO, buf, len);
155122394Sharti		}
156122394Sharti	}
157122394Sharti	return hp ? 0 : -1;
158122394Sharti}
159122394Sharti
160122394Shartistatic int
161122394Shartiresolv_getipnodeby(pthread_t self, char *host)
162122394Sharti{
163122394Sharti	char buf[1024];
164122394Sharti	struct hostent *hp, *hp2;
165122394Sharti	int len, h_error;
166122394Sharti
167122394Sharti	hp = getipnodebyname(host, AF_INET, 0, &h_error);
168122394Sharti	if (debug) {
169122394Sharti		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
170122394Sharti		    self, host, (hp == NULL) ? "not found" : "ok");
171122394Sharti		(void)write(STDOUT_FILENO, buf, len);
172122394Sharti	}
173122394Sharti	if (hp && reverse) {
174122394Sharti		memcpy(buf, hp->h_addr, hp->h_length);
175122394Sharti		hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype,
176122394Sharti		    &h_error);
177122394Sharti		if (hp2 && debug) {
178122394Sharti			len = snprintf(buf, sizeof(buf),
179122394Sharti			    "%p: reverse %s\n", self, hp2->h_name);
180122394Sharti			(void)write(STDOUT_FILENO, buf, len);
181122394Sharti		}
182122394Sharti		if (hp2)
183122394Sharti			freehostent(hp2);
184122394Sharti	}
185122394Sharti	if (hp)
186122394Sharti		freehostent(hp);
187122394Sharti	return hp ? 0 : -1;
188122394Sharti}
189122394Sharti
190122394Shartistatic void
191122394Shartiresolvone(int n)
192122394Sharti{
193122394Sharti	char buf[1024];
194122394Sharti	pthread_t self = pthread_self();
195122394Sharti	size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
196122394Sharti	char *host = hosts->sl_str[i];
197122394Sharti	struct addrinfo hints, *res;
198122394Sharti	int error, len;
199122394Sharti
200122394Sharti	if (debug) {
201122394Sharti		len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
202122394Sharti		    self, n, host, (int)i);
203122394Sharti		(void)write(STDOUT_FILENO, buf, len);
204216294Ssyrinx	}
205122394Sharti	switch (method) {
206122394Sharti	case METHOD_GETADDRINFO:
207122394Sharti		error = resolv_getaddrinfo(self, host, i);
208122394Sharti		break;
209122394Sharti	case METHOD_GETHOSTBY:
210122394Sharti		error = resolv_gethostby(self, host);
211122394Sharti		break;
212122394Sharti	case METHOD_GETIPNODEBY:
213122394Sharti		error = resolv_getipnodeby(self, host);
214122394Sharti		break;
215122394Sharti	default:
216122394Sharti		break;
217122394Sharti	}
218122394Sharti	pthread_mutex_lock(&stats);
219122394Sharti	ask[i]++;
220122394Sharti	got[i] += error == 0;
221122394Sharti	pthread_mutex_unlock(&stats);
222122394Sharti}
223216294Ssyrinx
224216294Ssyrinxstatic void *
225122394Shartiresolvloop(void *p)
226122394Sharti{
227122394Sharti	int *nhosts = (int *)p;
228122394Sharti	if (*nhosts == 0)
229122394Sharti		return NULL;
230122394Sharti	do
231122394Sharti		resolvone(*nhosts);
232122394Sharti	while (--(*nhosts));
233122394Sharti	return NULL;
234122394Sharti}
235122394Sharti
236122394Shartistatic void
237122394Shartirun(int *nhosts)
238122394Sharti{
239122394Sharti	pthread_t self = pthread_self();
240133211Sharti	if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
241122394Sharti		err(1, "pthread_create");
242122394Sharti}
243122394Sharti
244122394Shartiint
245122394Shartimain(int argc, char *argv[])
246122394Sharti{
247122394Sharti	int nthreads = NTHREADS;
248122394Sharti	int nhosts = NHOSTS;
249122394Sharti	int i, c, done, *nleft;
250122394Sharti	hosts = sl_init();
251122394Sharti
252122394Sharti	srandom(1234);
253122394Sharti
254122394Sharti	while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1)
255122394Sharti		switch (c) {
256124861Sharti		case 'A':
257124861Sharti			method = METHOD_GETADDRINFO;
258124861Sharti			break;
259124861Sharti		case 'd':
260124861Sharti			debug++;
261124861Sharti			break;
262124861Sharti		case 'h':
263122394Sharti			nhosts = atoi(optarg);
264122394Sharti			break;
265122394Sharti		case 'H':
266122394Sharti			method = METHOD_GETHOSTBY;
267122394Sharti			break;
268122394Sharti		case 'I':
269122394Sharti			method = METHOD_GETIPNODEBY;
270122394Sharti			break;
271122394Sharti		case 'n':
272122394Sharti			nthreads = atoi(optarg);
273122394Sharti			break;
274122394Sharti		case 'r':
275122394Sharti			reverse++;
276122394Sharti			break;
277122394Sharti		default:
278122394Sharti			usage();
279122394Sharti		}
280122394Sharti
281122394Sharti	for (i = optind; i < argc; i++)
282122394Sharti		load(argv[i]);
283122394Sharti
284122394Sharti	if (hosts->sl_cur == 0)
285122394Sharti		usage();
286122394Sharti
287122394Sharti	if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
288122394Sharti		err(1, "malloc");
289133211Sharti	if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
290122394Sharti		err(1, "calloc");
291122394Sharti	if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
292122394Sharti		err(1, "calloc");
293310901Sngie
294122394Sharti
295133211Sharti	for (i = 0; i < nthreads; i++) {
296122394Sharti		nleft[i] = nhosts;
297122394Sharti		run(&nleft[i]);
298133211Sharti	}
299122394Sharti
300122394Sharti	for (done = 0; !done;) {
301122394Sharti		done = 1;
302122394Sharti		for (i = 0; i < nthreads; i++) {
303122394Sharti			if (nleft[i] != 0) {
304122394Sharti				done = 0;
305122394Sharti				break;
306122394Sharti			}
307122394Sharti		}
308122394Sharti		sleep(1);
309122394Sharti	}
310122394Sharti	c = 0;
311122394Sharti	for (i = 0; i < hosts->sl_cur; i++) {
312122394Sharti		if (ask[i] != got[i] && got[i] != 0) {
313122394Sharti			warnx("Error: host %s ask %d got %d\n",
314122394Sharti			    hosts->sl_str[i], ask[i], got[i]);
315122394Sharti			c++;
316122394Sharti		}
317122394Sharti	}
318122394Sharti	free(nleft);
319122394Sharti	free(ask);
320122394Sharti	free(got);
321122394Sharti	sl_free(hosts, 1);
322122394Sharti	return c;
323122394Sharti}
324122394Sharti