]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/regression/lib/libc/resolv/resolv.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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                         sl_add(hosts, strdup(ptr));
95                 line[len] = c;
96         }
97
98         (void)fclose(fp);
99 }
100
101 static int
102 resolv_getaddrinfo(pthread_t self, char *host, int port)
103 {
104         char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
105         struct addrinfo hints, *res;
106         int error, len;
107
108         snprintf(portstr, sizeof(portstr), "%d", port);
109         memset(&hints, 0, sizeof(hints));
110         hints.ai_family = AF_UNSPEC;
111         hints.ai_flags = AI_PASSIVE;
112         hints.ai_socktype = SOCK_STREAM;
113         error = getaddrinfo(host, portstr, &hints, &res);
114         if (debug) {
115                 len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
116                     self, host, error ? "not found" : "ok");
117                 (void)write(STDOUT_FILENO, buf, len);
118         }
119         if (error == 0 && reverse) {
120                 memset(hbuf, 0, sizeof(hbuf));
121                 memset(pbuf, 0, sizeof(pbuf));
122                 getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
123                             pbuf, sizeof(pbuf), 0);
124                 if (debug) {
125                         len = snprintf(buf, sizeof(buf),
126                             "%p: reverse %s %s\n", self, hbuf, pbuf);
127                         (void)write(STDOUT_FILENO, buf, len);
128                 }
129         }
130         if (error == 0)
131                 freeaddrinfo(res);
132         return error;
133 }
134
135 static int
136 resolv_gethostby(pthread_t self, char *host)
137 {
138         char buf[1024];
139         struct hostent *hp, *hp2;
140         int len;
141
142         hp = gethostbyname(host);
143         if (debug) {
144                 len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
145                     self, host, (hp == NULL) ? "not found" : "ok");
146                 (void)write(STDOUT_FILENO, buf, len);
147         }
148         if (hp && reverse) {
149                 memcpy(buf, hp->h_addr, hp->h_length);
150                 hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype);
151                 if (hp2 && debug) {
152                         len = snprintf(buf, sizeof(buf),
153                             "%p: reverse %s\n", self, hp2->h_name);
154                         (void)write(STDOUT_FILENO, buf, len);
155                 }
156         }
157         return hp ? 0 : -1;
158 }
159
160 static int
161 resolv_getipnodeby(pthread_t self, char *host)
162 {
163         char buf[1024];
164         struct hostent *hp, *hp2;
165         int len, h_error;
166
167         hp = getipnodebyname(host, AF_INET, 0, &h_error);
168         if (debug) {
169                 len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
170                     self, host, (hp == NULL) ? "not found" : "ok");
171                 (void)write(STDOUT_FILENO, buf, len);
172         }
173         if (hp && reverse) {
174                 memcpy(buf, hp->h_addr, hp->h_length);
175                 hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype,
176                     &h_error);
177                 if (hp2 && debug) {
178                         len = snprintf(buf, sizeof(buf),
179                             "%p: reverse %s\n", self, hp2->h_name);
180                         (void)write(STDOUT_FILENO, buf, len);
181                 }
182                 if (hp2)
183                         freehostent(hp2);
184         }
185         if (hp)
186                 freehostent(hp);
187         return hp ? 0 : -1;
188 }
189
190 static void
191 resolvone(int n)
192 {
193         char buf[1024];
194         pthread_t self = pthread_self();
195         size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
196         char *host = hosts->sl_str[i];
197         struct addrinfo hints, *res;
198         int error, len;
199
200         if (debug) {
201                 len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
202                     self, n, host, (int)i);
203                 (void)write(STDOUT_FILENO, buf, len);
204         }
205         switch (method) {
206         case METHOD_GETADDRINFO:
207                 error = resolv_getaddrinfo(self, host, i);
208                 break;
209         case METHOD_GETHOSTBY:
210                 error = resolv_gethostby(self, host);
211                 break;
212         case METHOD_GETIPNODEBY:
213                 error = resolv_getipnodeby(self, host);
214                 break;
215         default:
216                 break;
217         }
218         pthread_mutex_lock(&stats);
219         ask[i]++;
220         got[i] += error == 0;
221         pthread_mutex_unlock(&stats);
222 }
223
224 static void *
225 resolvloop(void *p)
226 {
227         int *nhosts = (int *)p;
228         if (*nhosts == 0)
229                 return;
230         do
231                 resolvone(*nhosts);
232         while (--(*nhosts));
233         return NULL;
234 }
235
236 static void
237 run(int *nhosts)
238 {
239         pthread_t self = pthread_self();
240         if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
241                 err(1, "pthread_create");
242 }
243
244 int
245 main(int argc, char *argv[])
246 {
247         int nthreads = NTHREADS;
248         int nhosts = NHOSTS;
249         int i, c, done, *nleft;
250         hosts = sl_init();
251
252         srandom(1234);
253
254         while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1)
255                 switch (c) {
256                 case 'A':
257                         method = METHOD_GETADDRINFO;
258                         break;
259                 case 'd':
260                         debug++;
261                         break;
262                 case 'h':
263                         nhosts = atoi(optarg);
264                         break;
265                 case 'H':
266                         method = METHOD_GETHOSTBY;
267                         break;
268                 case 'I':
269                         method = METHOD_GETIPNODEBY;
270                         break;
271                 case 'n':
272                         nthreads = atoi(optarg);
273                         break;
274                 case 'r':
275                         reverse++;
276                         break;
277                 default:
278                         usage();
279                 }
280
281         for (i = optind; i < argc; i++)
282                 load(argv[i]);
283
284         if (hosts->sl_cur == 0)
285                 usage();
286
287         if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
288                 err(1, "malloc");
289         if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
290                 err(1, "calloc");
291         if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
292                 err(1, "calloc");
293
294
295         for (i = 0; i < nthreads; i++) {
296                 nleft[i] = nhosts;
297                 run(&nleft[i]);
298         }
299
300         for (done = 0; !done;) {
301                 done = 1;
302                 for (i = 0; i < nthreads; i++) {
303                         if (nleft[i] != 0) {
304                                 done = 0;
305                                 break;
306                         }
307                 }
308                 sleep(1);
309         }
310         c = 0;
311         for (i = 0; i < hosts->sl_cur; i++) {
312                 if (ask[i] != got[i] && got[i] != 0) {
313                         warnx("Error: host %s ask %d got %d\n",
314                             hosts->sl_str[i], ask[i], got[i]);
315                         c++;
316                 }
317         }
318         free(nleft);
319         free(ask);
320         free(got);
321         sl_free(hosts, 1);
322         return c;
323 }