1272343Sngie/* $NetBSD: h_resolv.c,v 1.2 2010/11/03 16:10:22 christos Exp $ */
2272343Sngie
3272343Sngie/*-
4272343Sngie * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
5272343Sngie * All rights reserved.
6272343Sngie *
7272343Sngie * This code is derived from software contributed to The NetBSD Foundation
8272343Sngie * by Christos Zoulas.
9272343Sngie *
10272343Sngie * Redistribution and use in source and binary forms, with or without
11272343Sngie * modification, are permitted provided that the following conditions
12272343Sngie * are met:
13272343Sngie * 1. Redistributions of source code must retain the above copyright
14272343Sngie *    notice, this list of conditions and the following disclaimer.
15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
16272343Sngie *    notice, this list of conditions and the following disclaimer in the
17272343Sngie *    documentation and/or other materials provided with the distribution.
18272343Sngie *
19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22272343Sngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29272343Sngie * POSSIBILITY OF SUCH DAMAGE.
30272343Sngie */
31272343Sngie
32272343Sngie#include <sys/cdefs.h>
33272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008\
34272343Sngie The NetBSD Foundation, inc. All rights reserved.");
35272343Sngie__RCSID("$NetBSD: h_resolv.c,v 1.2 2010/11/03 16:10:22 christos Exp $");
36272343Sngie
37272343Sngie#include <pthread.h>
38272343Sngie#include <stdio.h>
39272343Sngie#include <netdb.h>
40272343Sngie#include <stdlib.h>
41272343Sngie#include <unistd.h>
42272343Sngie#include <err.h>
43272343Sngie#include <string.h>
44272343Sngie#include <stringlist.h>
45272343Sngie
46272343Sngie#define NTHREADS    10
47272343Sngie#define NHOSTS        100
48272343Sngie#define WS        " \t\n\r"
49272343Sngie
50272343Sngiestatic StringList *hosts = NULL;
51272343Sngiestatic int debug = 0;
52272343Sngiestatic int *ask = NULL;
53272343Sngiestatic int *got = NULL;
54272343Sngie
55272343Sngiestatic void usage(void)  __attribute__((__noreturn__));
56272343Sngiestatic void load(const char *);
57272343Sngiestatic void resolvone(int);
58272343Sngiestatic void *resolvloop(void *);
59272343Sngiestatic void run(int *);
60272343Sngie
61272343Sngiestatic pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
62272343Sngie
63272343Sngiestatic void
64272343Sngieusage(void)
65272343Sngie{
66272343Sngie	(void)fprintf(stderr,
67272343Sngie		"Usage: %s [-d] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
68272343Sngie		getprogname());
69272343Sngie	exit(1);
70272343Sngie}
71272343Sngie
72272343Sngiestatic void
73272343Sngieload(const char *fname)
74272343Sngie{
75272343Sngie	FILE *fp;
76272343Sngie	size_t len;
77272343Sngie	char *line;
78272343Sngie
79272343Sngie	if ((fp = fopen(fname, "r")) == NULL)
80272343Sngie		err(1, "Cannot open `%s'", fname);
81272343Sngie	while ((line = fgetln(fp, &len)) != NULL) {
82272343Sngie		char c = line[len];
83272343Sngie		char *ptr;
84272343Sngie		line[len] = '\0';
85272343Sngie		for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS))
86272343Sngie			sl_add(hosts, strdup(ptr));
87272343Sngie		line[len] = c;
88272343Sngie	}
89272343Sngie
90272343Sngie	(void)fclose(fp);
91272343Sngie}
92272343Sngie
93272343Sngiestatic void
94272343Sngieresolvone(int n)
95272343Sngie{
96272343Sngie	char buf[1024];
97272343Sngie	pthread_t self = pthread_self();
98272343Sngie	size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
99272343Sngie	char *host = hosts->sl_str[i];
100272343Sngie	struct addrinfo *res;
101272343Sngie	int error, len;
102272343Sngie	if (debug) {
103272343Sngie		len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
104272343Sngie			self, n, host, (int)i);
105272343Sngie		(void)write(STDOUT_FILENO, buf, len);
106272343Sngie	}
107272343Sngie	error = getaddrinfo(host, NULL, NULL, &res);
108272343Sngie	if (debug) {
109272343Sngie		len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
110272343Sngie			self, host, error ? "not found" : "ok");
111272343Sngie		(void)write(STDOUT_FILENO, buf, len);
112272343Sngie	}
113272343Sngie	pthread_mutex_lock(&stats);
114272343Sngie	ask[i]++;
115272343Sngie	got[i] += error == 0;
116272343Sngie	pthread_mutex_unlock(&stats);
117272343Sngie	if (error == 0)
118272343Sngie		freeaddrinfo(res);
119272343Sngie}
120272343Sngie
121272343Sngiestatic void *
122272343Sngieresolvloop(void *p)
123272343Sngie{
124272343Sngie	int *nhosts = (int *)p;
125272343Sngie	if (*nhosts == 0)
126272343Sngie		return NULL;
127272343Sngie	do
128272343Sngie		resolvone(*nhosts);
129272343Sngie	while (--(*nhosts));
130272343Sngie	return NULL;
131272343Sngie}
132272343Sngie
133272343Sngiestatic void
134272343Sngierun(int *nhosts)
135272343Sngie{
136272343Sngie	pthread_t self = pthread_self();
137272343Sngie	if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
138272343Sngie		err(1, "pthread_create");
139272343Sngie}
140272343Sngie
141272343Sngieint
142272343Sngiemain(int argc, char *argv[])
143272343Sngie{
144272343Sngie	int nthreads = NTHREADS;
145272343Sngie	int nhosts = NHOSTS;
146272343Sngie	int i, c, done, *nleft;
147272343Sngie	hosts = sl_init();
148272343Sngie
149272343Sngie	srandom(1234);
150272343Sngie
151272343Sngie	while ((c = getopt(argc, argv, "dh:n:")) != -1)
152272343Sngie		switch (c) {
153272343Sngie		case 'd':
154272343Sngie			debug++;
155272343Sngie			break;
156272343Sngie		case 'h':
157272343Sngie			nhosts = atoi(optarg);
158272343Sngie			break;
159272343Sngie		case 'n':
160272343Sngie			nthreads = atoi(optarg);
161272343Sngie			break;
162272343Sngie		default:
163272343Sngie			usage();
164272343Sngie		}
165272343Sngie
166272343Sngie	for (i = optind; i < argc; i++)
167272343Sngie		load(argv[i]);
168272343Sngie
169272343Sngie	if (hosts->sl_cur == 0)
170272343Sngie		usage();
171272343Sngie
172272343Sngie	if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
173272343Sngie		err(1, "malloc");
174272343Sngie	if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
175272343Sngie		err(1, "calloc");
176272343Sngie	if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
177272343Sngie		err(1, "calloc");
178272343Sngie
179272343Sngie
180272343Sngie	for (i = 0; i < nthreads; i++) {
181272343Sngie		nleft[i] = nhosts;
182272343Sngie		run(&nleft[i]);
183272343Sngie	}
184272343Sngie
185272343Sngie	for (done = 0; !done;) {
186272343Sngie		done = 1;
187272343Sngie		for (i = 0; i < nthreads; i++) {
188272343Sngie			if (nleft[i] != 0) {
189272343Sngie				done = 0;
190272343Sngie				break;
191272343Sngie			}
192272343Sngie		}
193272343Sngie		sleep(1);
194272343Sngie	}
195272343Sngie	c = 0;
196272343Sngie	for (i = 0; i < (int)hosts->sl_cur; i++) {
197272343Sngie		if (ask[i] != got[i] && got[i] != 0) {
198272343Sngie			warnx("Error: host %s ask %d got %d\n",
199272343Sngie				hosts->sl_str[i], ask[i], got[i]);
200272343Sngie			c++;
201272343Sngie		}
202272343Sngie	}
203272343Sngie	free(nleft);
204272343Sngie	free(ask);
205272343Sngie	free(got);
206272343Sngie	sl_free(hosts, 1);
207272343Sngie	return c;
208272343Sngie}
209