resolv.c revision 145857
1130803Smarcel/*	$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $	*/
298944Sobrien
3130803Smarcel/*-
4130803Smarcel * Copyright (c) 2004 The NetBSD Foundation, Inc.
598944Sobrien * All rights reserved.
698944Sobrien *
798944Sobrien * This code is derived from software contributed to The NetBSD Foundation
898944Sobrien * by Christos Zoulas.
998944Sobrien *
1098944Sobrien * Redistribution and use in source and binary forms, with or without
1198944Sobrien * modification, are permitted provided that the following conditions
1298944Sobrien * are met:
1398944Sobrien * 1. Redistributions of source code must retain the above copyright
1498944Sobrien *    notice, this list of conditions and the following disclaimer.
1598944Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1698944Sobrien *    notice, this list of conditions and the following disclaimer in the
1798944Sobrien *    documentation and/or other materials provided with the distribution.
1898944Sobrien * 3. All advertising materials mentioning features or use of this software
1998944Sobrien *    must display the following acknowledgement:
2098944Sobrien *        This product includes software developed by the NetBSD
2198944Sobrien *        Foundation, Inc. and its contributors.
2298944Sobrien * 4. Neither the name of The NetBSD Foundation nor the names of its
2398944Sobrien *    contributors may be used to endorse or promote products derived
2498944Sobrien *    from this software without specific prior written permission.
25130803Smarcel *
26130803Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27130803Smarcel * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28130803Smarcel * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29130803Smarcel * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30130803Smarcel * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3198944Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3298944Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3398944Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3498944Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3598944Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3698944Sobrien * POSSIBILITY OF SUCH DAMAGE.
3798944Sobrien */
3898944Sobrien#include <sys/cdefs.h>
3998944Sobrien__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $");
4098944Sobrien
4198944Sobrien#include <pthread.h>
4298944Sobrien#include <stdio.h>
4398944Sobrien#include <netdb.h>
4498944Sobrien#include <stdlib.h>
4598944Sobrien#include <unistd.h>
4698944Sobrien#include <err.h>
4798944Sobrien#include <string.h>
4898944Sobrien#include <stringlist.h>
49130803Smarcel
50130803Smarcel#define NTHREADS	10
51130803Smarcel#define NHOSTS		100
52130803Smarcel#define WS		" \t\n\r"
53130803Smarcel
54130803Smarcelstatic StringList *hosts = NULL;
55130803Smarcelstatic int debug = 0;
56130803Smarcelstatic int *ask = NULL;
5798944Sobrienstatic int *got = NULL;
5898944Sobrien
5998944Sobrienstatic void usage(void)  __attribute__((__noreturn__));
60130803Smarcelstatic void load(const char *);
61130803Smarcelstatic void resolvone(int);
62130803Smarcelstatic void *resolvloop(void *);
63130803Smarcelstatic void run(int *);
64130803Smarcel
6598944Sobrienstatic pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
66130803Smarcel
67130803Smarcelstatic void
68130803Smarcelusage(void)
69130803Smarcel{
70130803Smarcel	(void)fprintf(stderr,
71130803Smarcel	    "Usage: %s [-d] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
72130803Smarcel	    getprogname());
73130803Smarcel	exit(1);
74130803Smarcel}
75130803Smarcel
76130803Smarcelstatic void
77130803Smarcelload(const char *fname)
78130803Smarcel{
7998944Sobrien	FILE *fp;
8098944Sobrien	size_t len;
81130803Smarcel	char *line;
82130803Smarcel
83130803Smarcel	if ((fp = fopen(fname, "r")) == NULL)
84130803Smarcel		err(1, "Cannot open `%s'", fname);
85130803Smarcel	while ((line = fgetln(fp, &len)) != NULL) {
86130803Smarcel		char c = line[len];
87130803Smarcel		char *ptr;
88130803Smarcel		line[len] = '\0';
89130803Smarcel		for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS))
90130803Smarcel			sl_add(hosts, strdup(ptr));
91130803Smarcel		line[len] = c;
92130803Smarcel	}
93130803Smarcel
94130803Smarcel	(void)fclose(fp);
95130803Smarcel}
96130803Smarcel
97130803Smarcelstatic void
98130803Smarcelresolvone(int n)
99130803Smarcel{
100130803Smarcel	char buf[1024];
101130803Smarcel	pthread_t self = pthread_self();
102130803Smarcel	size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
10398944Sobrien	char *host = hosts->sl_str[i];
10498944Sobrien	struct addrinfo *res;
10598944Sobrien	int error, len;
10698944Sobrien	if (debug) {
10798944Sobrien		len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
10898944Sobrien		    self, n, host, (int)i);
10998944Sobrien		(void)write(STDOUT_FILENO, buf, len);
11098944Sobrien	}
11198944Sobrien	error = getaddrinfo(host, NULL, NULL, &res);
11298944Sobrien	if (debug) {
11398944Sobrien		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
11498944Sobrien		    self, host, error ? "not found" : "ok");
11598944Sobrien		(void)write(STDOUT_FILENO, buf, len);
11698944Sobrien	}
11798944Sobrien	pthread_mutex_lock(&stats);
11898944Sobrien	ask[i]++;
11998944Sobrien	got[i] += error == 0;
12098944Sobrien	pthread_mutex_unlock(&stats);
12198944Sobrien	if (error == 0)
12298944Sobrien		freeaddrinfo(res);
12398944Sobrien}
12498944Sobrien
12598944Sobrienstatic void *
12698944Sobrienresolvloop(void *p)
12798944Sobrien{
12898944Sobrien	int *nhosts = (int *)p;
12998944Sobrien	if (*nhosts == 0)
13098944Sobrien		return;
13198944Sobrien	do
13298944Sobrien		resolvone(*nhosts);
13398944Sobrien	while (--(*nhosts));
13498944Sobrien	return NULL;
13598944Sobrien}
13698944Sobrien
13798944Sobrienstatic void
13898944Sobrienrun(int *nhosts)
139130803Smarcel{
140130803Smarcel	pthread_t self = pthread_self();
141130803Smarcel	if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
142130803Smarcel		err(1, "pthread_create");
14398944Sobrien}
14498944Sobrien
14598944Sobrienint
14698944Sobrienmain(int argc, char *argv[])
14798944Sobrien{
14898944Sobrien	int nthreads = NTHREADS;
14998944Sobrien	int nhosts = NHOSTS;
15098944Sobrien	int i, c, done, *nleft;
15198944Sobrien	hosts = sl_init();
15298944Sobrien
153130803Smarcel	srandom(1234);
15498944Sobrien
155130803Smarcel	while ((c = getopt(argc, argv, "dh:n:")) != -1)
156130803Smarcel		switch (c) {
157130803Smarcel		case 'd':
158130803Smarcel			debug++;
159130803Smarcel			break;
160130803Smarcel		case 'h':
161130803Smarcel			nhosts = atoi(optarg);
162130803Smarcel			break;
163130803Smarcel		case 'n':
164130803Smarcel			nthreads = atoi(optarg);
165130803Smarcel			break;
166130803Smarcel		default:
167130803Smarcel			usage();
168130803Smarcel		}
169130803Smarcel
170130803Smarcel	for (i = optind; i < argc; i++)
171130803Smarcel		load(argv[i]);
172130803Smarcel
173130803Smarcel	if (hosts->sl_cur == 0)
174130803Smarcel		usage();
17598944Sobrien
176130803Smarcel	if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
177130803Smarcel		err(1, "malloc");
178130803Smarcel	if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
179130803Smarcel		err(1, "calloc");
180130803Smarcel	if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
181130803Smarcel		err(1, "calloc");
182130803Smarcel
183130803Smarcel
184130803Smarcel	for (i = 0; i < nthreads; i++) {
185130803Smarcel		nleft[i] = nhosts;
186130803Smarcel		run(&nleft[i]);
187130803Smarcel	}
188130803Smarcel
189130803Smarcel	for (done = 0; !done;) {
190130803Smarcel		done = 1;
191130803Smarcel		for (i = 0; i < nthreads; i++) {
192130803Smarcel			if (nleft[i] != 0) {
193130803Smarcel				done = 0;
194130803Smarcel				break;
195130803Smarcel			}
196130803Smarcel		}
197130803Smarcel		sleep(1);
198130803Smarcel	}
199130803Smarcel	c = 0;
200130803Smarcel	for (i = 0; i < hosts->sl_cur; i++) {
201130803Smarcel		if (ask[i] != got[i] && got[i] != 0) {
202130803Smarcel			warnx("Error: host %s ask %d got %d\n",
203130803Smarcel			    hosts->sl_str[i], ask[i], got[i]);
204130803Smarcel			c++;
205130803Smarcel		}
206130803Smarcel	}
207130803Smarcel	free(nleft);
208130803Smarcel	free(ask);
209130803Smarcel	free(got);
210130803Smarcel	sl_free(hosts, 1);
211130803Smarcel	return c;
212130803Smarcel}
213130803Smarcel