resolv_test.c revision 291362
1227569Sphilip/*	$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $	*/
2227569Sphilip
3227569Sphilip/*-
4227569Sphilip * Copyright (c) 2004 The NetBSD Foundation, Inc.
5227569Sphilip * All rights reserved.
6227569Sphilip *
7227569Sphilip * This code is derived from software contributed to The NetBSD Foundation
8227569Sphilip * by Christos Zoulas.
9227569Sphilip *
10227569Sphilip * Redistribution and use in source and binary forms, with or without
11227569Sphilip * modification, are permitted provided that the following conditions
12227569Sphilip * are met:
13227569Sphilip * 1. Redistributions of source code must retain the above copyright
14227569Sphilip *    notice, this list of conditions and the following disclaimer.
15227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright
16227569Sphilip *    notice, this list of conditions and the following disclaimer in the
17227569Sphilip *    documentation and/or other materials provided with the distribution.
18227569Sphilip *
19227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20227569Sphilip * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21227569Sphilip * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22227569Sphilip * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23227569Sphilip * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24227569Sphilip * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25227569Sphilip * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26227569Sphilip * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27227569Sphilip * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28227569Sphilip * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29227569Sphilip * POSSIBILITY OF SUCH DAMAGE.
30227569Sphilip */
31227569Sphilip/* $FreeBSD: head/tools/regression/lib/libc/resolv/resolv.c 291362 2015-11-26 07:58:22Z ngie $ */
32227569Sphilip#include <sys/cdefs.h>
33272325Sgnn__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $");
34227569Sphilip
35227569Sphilip#include <sys/types.h>
36227569Sphilip#include <sys/socket.h>
37227569Sphilip#include <pthread.h>
38227569Sphilip#include <stdio.h>
39227569Sphilip#include <netdb.h>
40227569Sphilip#include <stdlib.h>
41227569Sphilip#include <unistd.h>
42227569Sphilip#include <err.h>
43227569Sphilip#include <string.h>
44227569Sphilip#include <stringlist.h>
45257176Sglebius
46227569Sphilip#define NTHREADS	10
47227569Sphilip#define NHOSTS		100
48227569Sphilip#define WS		" \t\n\r"
49227569Sphilip
50227569Sphilipenum method {
51227569Sphilip	METHOD_GETADDRINFO,
52227569Sphilip	METHOD_GETHOSTBY,
53227569Sphilip	METHOD_GETIPNODEBY
54227569Sphilip};
55227569Sphilip
56272325Sgnnstatic StringList *hosts = NULL;
57227569Sphilipstatic int debug = 0;
58227569Sphilipstatic enum method method = METHOD_GETADDRINFO;
59272325Sgnnstatic int reverse = 0;
60227569Sphilipstatic int *ask = NULL;
61227569Sphilipstatic int *got = NULL;
62272325Sgnn
63227569Sphilipstatic void usage(void)  __attribute__((__noreturn__));
64227569Sphilipstatic void load(const char *);
65272325Sgnnstatic void resolvone(int);
66227569Sphilipstatic void *resolvloop(void *);
67227569Sphilipstatic void run(int *);
68272325Sgnn
69227569Sphilipstatic pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
70227569Sphilip
71227569Sphilipstatic void
72227569Sphilipusage(void)
73227569Sphilip{
74272325Sgnn	(void)fprintf(stderr,
75227569Sphilip	    "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
76227569Sphilip	    getprogname());
77227569Sphilip	exit(1);
78272325Sgnn}
79227569Sphilip
80227569Sphilipstatic void
81272325Sgnnload(const char *fname)
82227569Sphilip{
83227569Sphilip	FILE *fp;
84272325Sgnn	size_t len;
85227569Sphilip	char *line;
86227569Sphilip
87227569Sphilip	if ((fp = fopen(fname, "r")) == NULL)
88227569Sphilip		err(1, "Cannot open `%s'", fname);
89227569Sphilip	while ((line = fgetln(fp, &len)) != NULL) {
90272328Sgnn		char c = line[len];
91272328Sgnn		char *ptr;
92272325Sgnn		line[len] = '\0';
93227569Sphilip		for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) {
94272325Sgnn			if (ptr == '\0' || ptr[0] == '#')
95227569Sphilip				continue;
96227569Sphilip			sl_add(hosts, strdup(ptr));
97227569Sphilip		}
98227569Sphilip		line[len] = c;
99227569Sphilip	}
100227569Sphilip
101227569Sphilip	(void)fclose(fp);
102227569Sphilip}
103227569Sphilip
104227569Sphilipstatic int
105227569Sphilipresolv_getaddrinfo(pthread_t self, char *host, int port)
106227569Sphilip{
107227569Sphilip	char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
108227569Sphilip	struct addrinfo hints, *res;
109227569Sphilip	int error, len;
110227569Sphilip
111272328Sgnn	snprintf(portstr, sizeof(portstr), "%d", port);
112227569Sphilip	memset(&hints, 0, sizeof(hints));
113227569Sphilip	hints.ai_family = AF_UNSPEC;
114227569Sphilip	hints.ai_flags = AI_PASSIVE;
115227569Sphilip	hints.ai_socktype = SOCK_STREAM;
116227569Sphilip	error = getaddrinfo(host, portstr, &hints, &res);
117227569Sphilip	if (debug) {
118227569Sphilip		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
119227569Sphilip		    self, host, error ? "not found" : "ok");
120227569Sphilip		(void)write(STDOUT_FILENO, buf, len);
121227569Sphilip	}
122227569Sphilip	if (error == 0 && reverse) {
123227569Sphilip		memset(hbuf, 0, sizeof(hbuf));
124227569Sphilip		memset(pbuf, 0, sizeof(pbuf));
125227569Sphilip		getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
126227569Sphilip			    pbuf, sizeof(pbuf), 0);
127227569Sphilip		if (debug) {
128227569Sphilip			len = snprintf(buf, sizeof(buf),
129227569Sphilip			    "%p: reverse %s %s\n", self, hbuf, pbuf);
130227569Sphilip			(void)write(STDOUT_FILENO, buf, len);
131227569Sphilip		}
132227569Sphilip	}
133227569Sphilip	if (error == 0)
134227569Sphilip		freeaddrinfo(res);
135227569Sphilip	return error;
136227569Sphilip}
137227569Sphilip
138272325Sgnnstatic int
139272325Sgnnresolv_gethostby(pthread_t self, char *host)
140272325Sgnn{
141227569Sphilip	char buf[1024];
142227569Sphilip	struct hostent *hp, *hp2;
143227569Sphilip	int len;
144227569Sphilip
145227569Sphilip	hp = gethostbyname(host);
146227569Sphilip	if (debug) {
147227569Sphilip		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
148227569Sphilip		    self, host, (hp == NULL) ? "not found" : "ok");
149227569Sphilip		(void)write(STDOUT_FILENO, buf, len);
150227569Sphilip	}
151227569Sphilip	if (hp && reverse) {
152227569Sphilip		memcpy(buf, hp->h_addr, hp->h_length);
153227569Sphilip		hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype);
154227569Sphilip		if (hp2 && debug) {
155227569Sphilip			len = snprintf(buf, sizeof(buf),
156227569Sphilip			    "%p: reverse %s\n", self, hp2->h_name);
157227569Sphilip			(void)write(STDOUT_FILENO, buf, len);
158227569Sphilip		}
159227569Sphilip	}
160227569Sphilip	return hp ? 0 : -1;
161227569Sphilip}
162227569Sphilip
163227569Sphilipstatic int
164227569Sphilipresolv_getipnodeby(pthread_t self, char *host)
165227569Sphilip{
166227569Sphilip	char buf[1024];
167227569Sphilip	struct hostent *hp, *hp2;
168227569Sphilip	int len, h_error;
169227569Sphilip
170227569Sphilip	hp = getipnodebyname(host, AF_INET, 0, &h_error);
171227569Sphilip	if (debug) {
172227569Sphilip		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
173227569Sphilip		    self, host, (hp == NULL) ? "not found" : "ok");
174227569Sphilip		(void)write(STDOUT_FILENO, buf, len);
175227569Sphilip	}
176227569Sphilip	if (hp && reverse) {
177227569Sphilip		memcpy(buf, hp->h_addr, hp->h_length);
178227569Sphilip		hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype,
179227569Sphilip		    &h_error);
180227569Sphilip		if (hp2 && debug) {
181227569Sphilip			len = snprintf(buf, sizeof(buf),
182227569Sphilip			    "%p: reverse %s\n", self, hp2->h_name);
183227569Sphilip			(void)write(STDOUT_FILENO, buf, len);
184227569Sphilip		}
185227569Sphilip		if (hp2)
186227569Sphilip			freehostent(hp2);
187227569Sphilip	}
188227569Sphilip	if (hp)
189227569Sphilip		freehostent(hp);
190227569Sphilip	return hp ? 0 : -1;
191227569Sphilip}
192227569Sphilip
193227569Sphilipstatic void
194227569Sphilipresolvone(int n)
195227569Sphilip{
196227569Sphilip	char buf[1024];
197227569Sphilip	pthread_t self = pthread_self();
198227569Sphilip	size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
199227569Sphilip	char *host = hosts->sl_str[i];
200227569Sphilip	struct addrinfo hints, *res;
201227569Sphilip	int error, len;
202272325Sgnn
203227569Sphilip	if (debug) {
204227569Sphilip		len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
205227569Sphilip		    self, n, host, (int)i);
206227569Sphilip		(void)write(STDOUT_FILENO, buf, len);
207227569Sphilip	}
208227569Sphilip	switch (method) {
209227569Sphilip	case METHOD_GETADDRINFO:
210227569Sphilip		error = resolv_getaddrinfo(self, host, i);
211227569Sphilip		break;
212227569Sphilip	case METHOD_GETHOSTBY:
213227569Sphilip		error = resolv_gethostby(self, host);
214272328Sgnn		break;
215272328Sgnn	case METHOD_GETIPNODEBY:
216272328Sgnn		error = resolv_getipnodeby(self, host);
217272325Sgnn		break;
218227569Sphilip	default:
219227569Sphilip		break;
220227569Sphilip	}
221227569Sphilip	pthread_mutex_lock(&stats);
222227569Sphilip	ask[i]++;
223227569Sphilip	got[i] += error == 0;
224227569Sphilip	pthread_mutex_unlock(&stats);
225227569Sphilip}
226227569Sphilip
227227569Sphilipstatic void *
228227569Sphilipresolvloop(void *p)
229227569Sphilip{
230227569Sphilip	int *nhosts = (int *)p;
231227569Sphilip	if (*nhosts == 0)
232227569Sphilip		return NULL;
233227569Sphilip	do
234227569Sphilip		resolvone(*nhosts);
235227569Sphilip	while (--(*nhosts));
236227569Sphilip	return NULL;
237227569Sphilip}
238227569Sphilip
239227569Sphilipstatic void
240227569Sphiliprun(int *nhosts)
241227569Sphilip{
242227569Sphilip	pthread_t self = pthread_self();
243227569Sphilip	if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
244227569Sphilip		err(1, "pthread_create");
245227569Sphilip}
246227569Sphilip
247227569Sphilipint
248227569Sphilipmain(int argc, char *argv[])
249227569Sphilip{
250227569Sphilip	int nthreads = NTHREADS;
251272325Sgnn	int nhosts = NHOSTS;
252272325Sgnn	int i, c, done, *nleft;
253227569Sphilip	hosts = sl_init();
254272328Sgnn
255272328Sgnn	srandom(1234);
256272328Sgnn
257272328Sgnn	while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1)
258227569Sphilip		switch (c) {
259227569Sphilip		case 'A':
260227569Sphilip			method = METHOD_GETADDRINFO;
261227569Sphilip			break;
262227569Sphilip		case 'd':
263227569Sphilip			debug++;
264227569Sphilip			break;
265227569Sphilip		case 'h':
266227569Sphilip			nhosts = atoi(optarg);
267227569Sphilip			break;
268227569Sphilip		case 'H':
269227569Sphilip			method = METHOD_GETHOSTBY;
270227569Sphilip			break;
271227569Sphilip		case 'I':
272227569Sphilip			method = METHOD_GETIPNODEBY;
273227569Sphilip			break;
274227569Sphilip		case 'n':
275227569Sphilip			nthreads = atoi(optarg);
276227569Sphilip			break;
277227569Sphilip		case 'r':
278227569Sphilip			reverse++;
279227569Sphilip			break;
280227569Sphilip		default:
281227569Sphilip			usage();
282227569Sphilip		}
283227569Sphilip
284227569Sphilip	for (i = optind; i < argc; i++)
285227569Sphilip		load(argv[i]);
286227569Sphilip
287227569Sphilip	if (hosts->sl_cur == 0)
288227569Sphilip		usage();
289227569Sphilip
290227569Sphilip	if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
291227569Sphilip		err(1, "malloc");
292227569Sphilip	if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
293227569Sphilip		err(1, "calloc");
294227569Sphilip	if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
295227569Sphilip		err(1, "calloc");
296227569Sphilip
297227569Sphilip
298227569Sphilip	for (i = 0; i < nthreads; i++) {
299227569Sphilip		nleft[i] = nhosts;
300227569Sphilip		run(&nleft[i]);
301227569Sphilip	}
302227569Sphilip
303227569Sphilip	for (done = 0; !done;) {
304227569Sphilip		done = 1;
305227569Sphilip		for (i = 0; i < nthreads; i++) {
306227569Sphilip			if (nleft[i] != 0) {
307227569Sphilip				done = 0;
308227569Sphilip				break;
309227569Sphilip			}
310227569Sphilip		}
311272325Sgnn		sleep(1);
312227569Sphilip	}
313227569Sphilip	c = 0;
314	for (i = 0; i < hosts->sl_cur; i++) {
315		if (ask[i] != got[i] && got[i] != 0) {
316			warnx("Error: host %s ask %d got %d\n",
317			    hosts->sl_str[i], ask[i], got[i]);
318			c++;
319		}
320	}
321	free(nleft);
322	free(ask);
323	free(got);
324	sl_free(hosts, 1);
325	return c;
326}
327