1*f0d208fdSchristos /* $NetBSD: h_resolv.c,v 1.3 2019/03/06 01:20:15 christos Exp $ */
2ac555471Sjmmv
3ac555471Sjmmv /*-
4ac555471Sjmmv * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
5ac555471Sjmmv * All rights reserved.
6ac555471Sjmmv *
7ac555471Sjmmv * This code is derived from software contributed to The NetBSD Foundation
8ac555471Sjmmv * by Christos Zoulas.
9ac555471Sjmmv *
10ac555471Sjmmv * Redistribution and use in source and binary forms, with or without
11ac555471Sjmmv * modification, are permitted provided that the following conditions
12ac555471Sjmmv * are met:
13ac555471Sjmmv * 1. Redistributions of source code must retain the above copyright
14ac555471Sjmmv * notice, this list of conditions and the following disclaimer.
15ac555471Sjmmv * 2. Redistributions in binary form must reproduce the above copyright
16ac555471Sjmmv * notice, this list of conditions and the following disclaimer in the
17ac555471Sjmmv * documentation and/or other materials provided with the distribution.
18ac555471Sjmmv *
19ac555471Sjmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20ac555471Sjmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21ac555471Sjmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22ac555471Sjmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23ac555471Sjmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ac555471Sjmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ac555471Sjmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ac555471Sjmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ac555471Sjmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ac555471Sjmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ac555471Sjmmv * POSSIBILITY OF SUCH DAMAGE.
30ac555471Sjmmv */
31ac555471Sjmmv
32ac555471Sjmmv #include <sys/cdefs.h>
33ac555471Sjmmv __COPYRIGHT("@(#) Copyright (c) 2008\
34ac555471Sjmmv The NetBSD Foundation, inc. All rights reserved.");
35*f0d208fdSchristos __RCSID("$NetBSD: h_resolv.c,v 1.3 2019/03/06 01:20:15 christos Exp $");
36ac555471Sjmmv
37ac555471Sjmmv #include <pthread.h>
38ac555471Sjmmv #include <stdio.h>
39ac555471Sjmmv #include <netdb.h>
40ac555471Sjmmv #include <stdlib.h>
41ac555471Sjmmv #include <unistd.h>
42ac555471Sjmmv #include <err.h>
43ac555471Sjmmv #include <string.h>
44ac555471Sjmmv #include <stringlist.h>
45ac555471Sjmmv
46ac555471Sjmmv #define NTHREADS 10
47ac555471Sjmmv #define NHOSTS 100
48ac555471Sjmmv #define WS " \t\n\r"
49ac555471Sjmmv
50ac555471Sjmmv static StringList *hosts = NULL;
51ac555471Sjmmv static int debug = 0;
52ac555471Sjmmv static int *ask = NULL;
53ac555471Sjmmv static int *got = NULL;
54ac555471Sjmmv
55ac555471Sjmmv static void usage(void) __attribute__((__noreturn__));
56ac555471Sjmmv static void load(const char *);
57ac555471Sjmmv static void resolvone(int);
58ac555471Sjmmv static void *resolvloop(void *);
59*f0d208fdSchristos static pthread_t run(int *);
60ac555471Sjmmv
61ac555471Sjmmv static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
62ac555471Sjmmv
63ac555471Sjmmv static void
usage(void)64ac555471Sjmmv usage(void)
65ac555471Sjmmv {
66ac555471Sjmmv (void)fprintf(stderr,
67ac555471Sjmmv "Usage: %s [-d] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
68ac555471Sjmmv getprogname());
69ac555471Sjmmv exit(1);
70ac555471Sjmmv }
71ac555471Sjmmv
72ac555471Sjmmv static void
load(const char * fname)73ac555471Sjmmv load(const char *fname)
74ac555471Sjmmv {
75ac555471Sjmmv FILE *fp;
76ac555471Sjmmv size_t len;
77ac555471Sjmmv char *line;
78ac555471Sjmmv
79ac555471Sjmmv if ((fp = fopen(fname, "r")) == NULL)
80*f0d208fdSchristos err(EXIT_FAILURE, "Cannot open `%s'", fname);
81ac555471Sjmmv while ((line = fgetln(fp, &len)) != NULL) {
82ac555471Sjmmv char c = line[len];
83ac555471Sjmmv char *ptr;
84ac555471Sjmmv line[len] = '\0';
85ac555471Sjmmv for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS))
86ac555471Sjmmv sl_add(hosts, strdup(ptr));
87ac555471Sjmmv line[len] = c;
88ac555471Sjmmv }
89ac555471Sjmmv
90ac555471Sjmmv (void)fclose(fp);
91ac555471Sjmmv }
92ac555471Sjmmv
93ac555471Sjmmv static void
resolvone(int n)94ac555471Sjmmv resolvone(int n)
95ac555471Sjmmv {
96ac555471Sjmmv char buf[1024];
97ac555471Sjmmv pthread_t self = pthread_self();
98ac555471Sjmmv size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
99ac555471Sjmmv char *host = hosts->sl_str[i];
100ac555471Sjmmv struct addrinfo *res;
101ac555471Sjmmv int error, len;
102ac555471Sjmmv if (debug) {
103ac555471Sjmmv len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
104ac555471Sjmmv self, n, host, (int)i);
105ac555471Sjmmv (void)write(STDOUT_FILENO, buf, len);
106ac555471Sjmmv }
107ac555471Sjmmv error = getaddrinfo(host, NULL, NULL, &res);
108ac555471Sjmmv if (debug) {
109ac555471Sjmmv len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
110ac555471Sjmmv self, host, error ? "not found" : "ok");
111ac555471Sjmmv (void)write(STDOUT_FILENO, buf, len);
112ac555471Sjmmv }
113ac555471Sjmmv pthread_mutex_lock(&stats);
114ac555471Sjmmv ask[i]++;
115ac555471Sjmmv got[i] += error == 0;
116ac555471Sjmmv pthread_mutex_unlock(&stats);
117ac555471Sjmmv if (error == 0)
118ac555471Sjmmv freeaddrinfo(res);
119ac555471Sjmmv }
120ac555471Sjmmv
121ac555471Sjmmv static void *
resolvloop(void * p)122ac555471Sjmmv resolvloop(void *p)
123ac555471Sjmmv {
124ac555471Sjmmv int *nhosts = (int *)p;
125ac555471Sjmmv if (*nhosts == 0)
126ac555471Sjmmv return NULL;
127ac555471Sjmmv do
128ac555471Sjmmv resolvone(*nhosts);
129ac555471Sjmmv while (--(*nhosts));
130ac555471Sjmmv return NULL;
131ac555471Sjmmv }
132ac555471Sjmmv
133*f0d208fdSchristos static pthread_t
run(int * nhosts)134ac555471Sjmmv run(int *nhosts)
135ac555471Sjmmv {
136ac555471Sjmmv pthread_t self = pthread_self();
137ac555471Sjmmv if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
138*f0d208fdSchristos err(EXIT_FAILURE, "pthread_create");
139*f0d208fdSchristos return self;
140ac555471Sjmmv }
141ac555471Sjmmv
142ac555471Sjmmv int
main(int argc,char * argv[])143ac555471Sjmmv main(int argc, char *argv[])
144ac555471Sjmmv {
145ac555471Sjmmv int nthreads = NTHREADS;
146*f0d208fdSchristos pthread_t *threads;
147ac555471Sjmmv int nhosts = NHOSTS;
148ac555471Sjmmv int i, c, done, *nleft;
149ac555471Sjmmv hosts = sl_init();
150ac555471Sjmmv
151ac555471Sjmmv srandom(1234);
152ac555471Sjmmv
153ac555471Sjmmv while ((c = getopt(argc, argv, "dh:n:")) != -1)
154ac555471Sjmmv switch (c) {
155ac555471Sjmmv case 'd':
156ac555471Sjmmv debug++;
157ac555471Sjmmv break;
158ac555471Sjmmv case 'h':
159ac555471Sjmmv nhosts = atoi(optarg);
160ac555471Sjmmv break;
161ac555471Sjmmv case 'n':
162ac555471Sjmmv nthreads = atoi(optarg);
163ac555471Sjmmv break;
164ac555471Sjmmv default:
165ac555471Sjmmv usage();
166ac555471Sjmmv }
167ac555471Sjmmv
168ac555471Sjmmv for (i = optind; i < argc; i++)
169ac555471Sjmmv load(argv[i]);
170ac555471Sjmmv
171ac555471Sjmmv if (hosts->sl_cur == 0)
172ac555471Sjmmv usage();
173ac555471Sjmmv
174ac555471Sjmmv if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
175*f0d208fdSchristos err(EXIT_FAILURE, "malloc");
176ac555471Sjmmv if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
177*f0d208fdSchristos err(EXIT_FAILURE, "calloc");
178ac555471Sjmmv if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
179*f0d208fdSchristos err(EXIT_FAILURE, "calloc");
180*f0d208fdSchristos if ((threads = malloc(nthreads * sizeof(pthread_t))) == NULL)
181*f0d208fdSchristos err(EXIT_FAILURE, "calloc");
182ac555471Sjmmv
183ac555471Sjmmv
184ac555471Sjmmv for (i = 0; i < nthreads; i++) {
185ac555471Sjmmv nleft[i] = nhosts;
186*f0d208fdSchristos threads[i] = run(&nleft[i]);
187ac555471Sjmmv }
188ac555471Sjmmv
189ac555471Sjmmv for (done = 0; !done;) {
190ac555471Sjmmv done = 1;
191ac555471Sjmmv for (i = 0; i < nthreads; i++) {
192ac555471Sjmmv if (nleft[i] != 0) {
193ac555471Sjmmv done = 0;
194ac555471Sjmmv break;
195ac555471Sjmmv }
196ac555471Sjmmv }
197ac555471Sjmmv sleep(1);
198ac555471Sjmmv }
199ac555471Sjmmv c = 0;
2000f10aa9dSchristos for (i = 0; i < (int)hosts->sl_cur; i++) {
201ac555471Sjmmv if (ask[i] != got[i] && got[i] != 0) {
202ac555471Sjmmv warnx("Error: host %s ask %d got %d\n",
203ac555471Sjmmv hosts->sl_str[i], ask[i], got[i]);
204ac555471Sjmmv c++;
205ac555471Sjmmv }
206ac555471Sjmmv }
207*f0d208fdSchristos for (i = 0; i < nthreads; i++)
208*f0d208fdSchristos pthread_join(threads[i], NULL);
209*f0d208fdSchristos free(threads);
210ac555471Sjmmv free(nleft);
211ac555471Sjmmv free(ask);
212ac555471Sjmmv free(got);
213ac555471Sjmmv sl_free(hosts, 1);
214ac555471Sjmmv return c;
215ac555471Sjmmv }
216