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