]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - tools/regression/lib/libc/resolv/resolv.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / tools / regression / lib / libc / resolv / resolv.c
1 /*      $NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $      */
2
3 /*-
4  * Copyright (c) 2004 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Christos Zoulas.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 /* $FreeBSD$ */
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $");
34
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <pthread.h>
38 #include <stdio.h>
39 #include <netdb.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <err.h>
43 #include <string.h>
44 #include <stringlist.h>
45
46 #define NTHREADS        10
47 #define NHOSTS          100
48 #define WS              " \t\n\r"
49
50 enum method {
51         METHOD_GETADDRINFO,
52         METHOD_GETHOSTBY,
53         METHOD_GETIPNODEBY
54 };
55
56 static StringList *hosts = NULL;
57 static int debug = 0;
58 static enum method method = METHOD_GETADDRINFO;
59 static int reverse = 0;
60 static int *ask = NULL;
61 static int *got = NULL;
62
63 static void usage(void)  __attribute__((__noreturn__));
64 static void load(const char *);
65 static void resolvone(int);
66 static void *resolvloop(void *);
67 static void run(int *);
68
69 static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
70
71 static void
72 usage(void)
73 {
74         (void)fprintf(stderr,
75             "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
76             getprogname());
77         exit(1);
78 }
79
80 static void
81 load(const char *fname)
82 {
83         FILE *fp;
84         size_t len;
85         char *line;
86
87         if ((fp = fopen(fname, "r")) == NULL)
88                 err(1, "Cannot open `%s'", fname);
89         while ((line = fgetln(fp, &len)) != NULL) {
90                 char c = line[len];
91                 char *ptr;
92                 line[len] = '\0';
93                 for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) {
94                         if (ptr == '\0' || ptr[0] == '#')
95                                 continue;
96                         sl_add(hosts, strdup(ptr));
97                 }
98                 line[len] = c;
99         }
100
101         (void)fclose(fp);
102 }
103
104 static int
105 resolv_getaddrinfo(pthread_t self, char *host, int port)
106 {
107         char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
108         struct addrinfo hints, *res;
109         int error, len;
110
111         snprintf(portstr, sizeof(portstr), "%d", port);
112         memset(&hints, 0, sizeof(hints));
113         hints.ai_family = AF_UNSPEC;
114         hints.ai_flags = AI_PASSIVE;
115         hints.ai_socktype = SOCK_STREAM;
116         error = getaddrinfo(host, portstr, &hints, &res);
117         if (debug) {
118                 len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
119                     self, host, error ? "not found" : "ok");
120                 (void)write(STDOUT_FILENO, buf, len);
121         }
122         if (error == 0 && reverse) {
123                 memset(hbuf, 0, sizeof(hbuf));
124                 memset(pbuf, 0, sizeof(pbuf));
125                 getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
126                             pbuf, sizeof(pbuf), 0);
127                 if (debug) {
128                         len = snprintf(buf, sizeof(buf),
129                             "%p: reverse %s %s\n", self, hbuf, pbuf);
130                         (void)write(STDOUT_FILENO, buf, len);
131                 }
132         }
133         if (error == 0)
134                 freeaddrinfo(res);
135         return error;
136 }
137
138 static int
139 resolv_gethostby(pthread_t self, char *host)
140 {
141         char buf[1024];
142         struct hostent *hp, *hp2;
143         int len;
144
145         hp = gethostbyname(host);
146         if (debug) {
147                 len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
148                     self, host, (hp == NULL) ? "not found" : "ok");
149                 (void)write(STDOUT_FILENO, buf, len);
150         }
151         if (hp && reverse) {
152                 memcpy(buf, hp->h_addr, hp->h_length);
153                 hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype);
154                 if (hp2 && debug) {
155                         len = snprintf(buf, sizeof(buf),
156                             "%p: reverse %s\n", self, hp2->h_name);
157                         (void)write(STDOUT_FILENO, buf, len);
158                 }
159         }
160         return hp ? 0 : -1;
161 }
162
163 static int
164 resolv_getipnodeby(pthread_t self, char *host)
165 {
166         char buf[1024];
167         struct hostent *hp, *hp2;
168         int len, h_error;
169
170         hp = getipnodebyname(host, AF_INET, 0, &h_error);
171         if (debug) {
172                 len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
173                     self, host, (hp == NULL) ? "not found" : "ok");
174                 (void)write(STDOUT_FILENO, buf, len);
175         }
176         if (hp && reverse) {
177                 memcpy(buf, hp->h_addr, hp->h_length);
178                 hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype,
179                     &h_error);
180                 if (hp2 && debug) {
181                         len = snprintf(buf, sizeof(buf),
182                             "%p: reverse %s\n", self, hp2->h_name);
183                         (void)write(STDOUT_FILENO, buf, len);
184                 }
185                 if (hp2)
186                         freehostent(hp2);
187         }
188         if (hp)
189                 freehostent(hp);
190         return hp ? 0 : -1;
191 }
192
193 static void
194 resolvone(int n)
195 {
196         char buf[1024];
197         pthread_t self = pthread_self();
198         size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
199         char *host = hosts->sl_str[i];
200         struct addrinfo hints, *res;
201         int error, len;
202
203         if (debug) {
204                 len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
205                     self, n, host, (int)i);
206                 (void)write(STDOUT_FILENO, buf, len);
207         }
208         switch (method) {
209         case METHOD_GETADDRINFO:
210                 error = resolv_getaddrinfo(self, host, i);
211                 break;
212         case METHOD_GETHOSTBY:
213                 error = resolv_gethostby(self, host);
214                 break;
215         case METHOD_GETIPNODEBY:
216                 error = resolv_getipnodeby(self, host);
217                 break;
218         default:
219                 break;
220         }
221         pthread_mutex_lock(&stats);
222         ask[i]++;
223         got[i] += error == 0;
224         pthread_mutex_unlock(&stats);
225 }
226
227 static void *
228 resolvloop(void *p)
229 {
230         int *nhosts = (int *)p;
231         if (*nhosts == 0)
232                 return NULL;
233         do
234                 resolvone(*nhosts);
235         while (--(*nhosts));
236         return NULL;
237 }
238
239 static void
240 run(int *nhosts)
241 {
242         pthread_t self = pthread_self();
243         if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
244                 err(1, "pthread_create");
245 }
246
247 int
248 main(int argc, char *argv[])
249 {
250         int nthreads = NTHREADS;
251         int nhosts = NHOSTS;
252         int i, c, done, *nleft;
253         hosts = sl_init();
254
255         srandom(1234);
256
257         while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1)
258                 switch (c) {
259                 case 'A':
260                         method = METHOD_GETADDRINFO;
261                         break;
262                 case 'd':
263                         debug++;
264                         break;
265                 case 'h':
266                         nhosts = atoi(optarg);
267                         break;
268                 case 'H':
269                         method = METHOD_GETHOSTBY;
270                         break;
271                 case 'I':
272                         method = METHOD_GETIPNODEBY;
273                         break;
274                 case 'n':
275                         nthreads = atoi(optarg);
276                         break;
277                 case 'r':
278                         reverse++;
279                         break;
280                 default:
281                         usage();
282                 }
283
284         for (i = optind; i < argc; i++)
285                 load(argv[i]);
286
287         if (hosts->sl_cur == 0)
288                 usage();
289
290         if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
291                 err(1, "malloc");
292         if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
293                 err(1, "calloc");
294         if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
295                 err(1, "calloc");
296
297
298         for (i = 0; i < nthreads; i++) {
299                 nleft[i] = nhosts;
300                 run(&nleft[i]);
301         }
302
303         for (done = 0; !done;) {
304                 done = 1;
305                 for (i = 0; i < nthreads; i++) {
306                         if (nleft[i] != 0) {
307                                 done = 0;
308                                 break;
309                         }
310                 }
311                 sleep(1);
312         }
313         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 }