1 /* $NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $ */
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
39 #include <sys/cdefs.h>
40 __RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $");
42 #include <sys/types.h>
43 #include <sys/socket.h>
51 #include <stringlist.h>
63 static StringList
*hosts
= NULL
;
65 static enum method method
= METHOD_GETADDRINFO
;
66 static int reverse
= 0;
67 static int *ask
= NULL
;
68 static int *got
= NULL
;
70 static void usage(void) __attribute__((__noreturn__
));
71 static void load(const char *);
72 static void resolvone(int);
73 static void *resolvloop(void *);
74 static void run(int *);
76 static pthread_mutex_t stats
= PTHREAD_MUTEX_INITIALIZER
;
82 "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
88 load(const char *fname
)
94 if ((fp
= fopen(fname
, "r")) == NULL
)
95 err(1, "Cannot open `%s'", fname
);
96 while ((line
= fgetln(fp
, &len
)) != NULL
) {
100 for (ptr
= strtok(line
, WS
); ptr
; ptr
= strtok(NULL
, WS
))
101 sl_add(hosts
, strdup(ptr
));
109 resolv_getaddrinfo(pthread_t self
, char *host
, int port
)
111 char portstr
[6], buf
[1024], hbuf
[NI_MAXHOST
], pbuf
[NI_MAXSERV
];
112 struct addrinfo hints
, *res
;
115 snprintf(portstr
, sizeof(portstr
), "%d", port
);
116 memset(&hints
, 0, sizeof(hints
));
117 hints
.ai_family
= AF_UNSPEC
;
118 hints
.ai_flags
= AI_PASSIVE
;
119 hints
.ai_socktype
= SOCK_STREAM
;
120 error
= getaddrinfo(host
, portstr
, &hints
, &res
);
122 len
= snprintf(buf
, sizeof(buf
), "%p: host %s %s\n",
123 self
, host
, error
? "not found" : "ok");
124 (void)write(STDOUT_FILENO
, buf
, len
);
126 if (error
== 0 && reverse
) {
127 memset(hbuf
, 0, sizeof(hbuf
));
128 memset(pbuf
, 0, sizeof(pbuf
));
129 getnameinfo(res
->ai_addr
, res
->ai_addrlen
, hbuf
, sizeof(hbuf
),
130 pbuf
, sizeof(pbuf
), 0);
132 len
= snprintf(buf
, sizeof(buf
),
133 "%p: reverse %s %s\n", self
, hbuf
, pbuf
);
134 (void)write(STDOUT_FILENO
, buf
, len
);
143 resolv_gethostby(pthread_t self
, char *host
)
146 struct hostent
*hp
, *hp2
;
149 hp
= gethostbyname(host
);
151 len
= snprintf(buf
, sizeof(buf
), "%p: host %s %s\n",
152 self
, host
, (hp
== NULL
) ? "not found" : "ok");
153 (void)write(STDOUT_FILENO
, buf
, len
);
156 memcpy(buf
, hp
->h_addr
, hp
->h_length
);
157 hp2
= gethostbyaddr(buf
, hp
->h_length
, hp
->h_addrtype
);
159 len
= snprintf(buf
, sizeof(buf
),
160 "%p: reverse %s\n", self
, hp2
->h_name
);
161 (void)write(STDOUT_FILENO
, buf
, len
);
168 resolv_getipnodeby(pthread_t self
, char *host
)
171 struct hostent
*hp
, *hp2
;
174 hp
= getipnodebyname(host
, AF_INET
, 0, &h_error
);
176 len
= snprintf(buf
, sizeof(buf
), "%p: host %s %s\n",
177 self
, host
, (hp
== NULL
) ? "not found" : "ok");
178 (void)write(STDOUT_FILENO
, buf
, len
);
181 memcpy(buf
, hp
->h_addr
, hp
->h_length
);
182 hp2
= getipnodebyaddr(buf
, hp
->h_length
, hp
->h_addrtype
,
185 len
= snprintf(buf
, sizeof(buf
),
186 "%p: reverse %s\n", self
, hp2
->h_name
);
187 (void)write(STDOUT_FILENO
, buf
, len
);
201 pthread_t self
= pthread_self();
202 size_t i
= (random() & 0x0fffffff) % hosts
->sl_cur
;
203 char *host
= hosts
->sl_str
[i
];
204 struct addrinfo hints
, *res
;
208 len
= snprintf(buf
, sizeof(buf
), "%p: %d resolving %s %d\n",
209 self
, n
, host
, (int)i
);
210 (void)write(STDOUT_FILENO
, buf
, len
);
213 case METHOD_GETADDRINFO
:
214 error
= resolv_getaddrinfo(self
, host
, i
);
216 case METHOD_GETHOSTBY
:
217 error
= resolv_gethostby(self
, host
);
219 case METHOD_GETIPNODEBY
:
220 error
= resolv_getipnodeby(self
, host
);
225 pthread_mutex_lock(&stats
);
227 got
[i
] += error
== 0;
228 pthread_mutex_unlock(&stats
);
234 int *nhosts
= (int *)p
;
246 pthread_t self
= pthread_self();
247 if (pthread_create(&self
, NULL
, resolvloop
, nhosts
) != 0)
248 err(1, "pthread_create");
252 main(int argc
, char *argv
[])
254 int nthreads
= NTHREADS
;
256 int i
, c
, done
, *nleft
;
261 while ((c
= getopt(argc
, argv
, "Adh:HIn:r")) != -1)
264 method
= METHOD_GETADDRINFO
;
270 nhosts
= atoi(optarg
);
273 method
= METHOD_GETHOSTBY
;
276 method
= METHOD_GETIPNODEBY
;
279 nthreads
= atoi(optarg
);
288 for (i
= optind
; i
< argc
; i
++)
291 if (hosts
->sl_cur
== 0)
294 if ((nleft
= malloc(nthreads
* sizeof(int))) == NULL
)
296 if ((ask
= calloc(hosts
->sl_cur
, sizeof(int))) == NULL
)
298 if ((got
= calloc(hosts
->sl_cur
, sizeof(int))) == NULL
)
302 for (i
= 0; i
< nthreads
; i
++) {
307 for (done
= 0; !done
;) {
309 for (i
= 0; i
< nthreads
; i
++) {
318 for (i
= 0; i
< hosts
->sl_cur
; i
++) {
319 if (ask
[i
] != got
[i
] && got
[i
] != 0) {
320 warnx("Error: host %s ask %d got %d\n",
321 hosts
->sl_str
[i
], ask
[i
], got
[i
]);