resolv_test.c revision 145860
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 * 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. 25 * 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. 37 */ 38/* $FreeBSD: head/tools/regression/lib/libc/resolv/resolv.c 145860 2005-05-04 12:02:10Z ume $ */ 39#include <sys/cdefs.h> 40__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $"); 41 42#include <sys/types.h> 43#include <sys/socket.h> 44#include <pthread.h> 45#include <stdio.h> 46#include <netdb.h> 47#include <stdlib.h> 48#include <unistd.h> 49#include <err.h> 50#include <string.h> 51#include <stringlist.h> 52 53#define NTHREADS 10 54#define NHOSTS 100 55#define WS " \t\n\r" 56 57enum method { 58 METHOD_GETADDRINFO, 59 METHOD_GETHOSTBY, 60 METHOD_GETIPNODEBY 61}; 62 63static StringList *hosts = NULL; 64static int debug = 0; 65static enum method method = METHOD_GETADDRINFO; 66static int reverse = 0; 67static int *ask = NULL; 68static int *got = NULL; 69 70static void usage(void) __attribute__((__noreturn__)); 71static void load(const char *); 72static void resolvone(int); 73static void *resolvloop(void *); 74static void run(int *); 75 76static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; 77 78static void 79usage(void) 80{ 81 (void)fprintf(stderr, 82 "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n", 83 getprogname()); 84 exit(1); 85} 86 87static void 88load(const char *fname) 89{ 90 FILE *fp; 91 size_t len; 92 char *line; 93 94 if ((fp = fopen(fname, "r")) == NULL) 95 err(1, "Cannot open `%s'", fname); 96 while ((line = fgetln(fp, &len)) != NULL) { 97 char c = line[len]; 98 char *ptr; 99 line[len] = '\0'; 100 for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) 101 sl_add(hosts, strdup(ptr)); 102 line[len] = c; 103 } 104 105 (void)fclose(fp); 106} 107 108static int 109resolv_getaddrinfo(pthread_t self, char *host, int port) 110{ 111 char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 112 struct addrinfo hints, *res; 113 int error, len; 114 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); 121 if (debug) { 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); 125 } 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); 131 if (debug) { 132 len = snprintf(buf, sizeof(buf), 133 "%p: reverse %s %s\n", self, hbuf, pbuf); 134 (void)write(STDOUT_FILENO, buf, len); 135 } 136 } 137 if (error == 0) 138 freeaddrinfo(res); 139 return error; 140} 141 142static int 143resolv_gethostby(pthread_t self, char *host) 144{ 145 char buf[1024]; 146 struct hostent *hp, *hp2; 147 int len; 148 149 hp = gethostbyname(host); 150 if (debug) { 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); 154 } 155 if (hp && reverse) { 156 memcpy(buf, hp->h_addr, hp->h_length); 157 hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype); 158 if (hp2 && debug) { 159 len = snprintf(buf, sizeof(buf), 160 "%p: reverse %s\n", self, hp2->h_name); 161 (void)write(STDOUT_FILENO, buf, len); 162 } 163 } 164 return hp ? 0 : -1; 165} 166 167static int 168resolv_getipnodeby(pthread_t self, char *host) 169{ 170 char buf[1024]; 171 struct hostent *hp, *hp2; 172 int len, h_error; 173 174 hp = getipnodebyname(host, AF_INET, 0, &h_error); 175 if (debug) { 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); 179 } 180 if (hp && reverse) { 181 memcpy(buf, hp->h_addr, hp->h_length); 182 hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype, 183 &h_error); 184 if (hp2 && debug) { 185 len = snprintf(buf, sizeof(buf), 186 "%p: reverse %s\n", self, hp2->h_name); 187 (void)write(STDOUT_FILENO, buf, len); 188 } 189 if (hp2) 190 freehostent(hp2); 191 } 192 if (hp) 193 freehostent(hp); 194 return hp ? 0 : -1; 195} 196 197static void 198resolvone(int n) 199{ 200 char buf[1024]; 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; 205 int error, len; 206 207 if (debug) { 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); 211 } 212 switch (method) { 213 case METHOD_GETADDRINFO: 214 error = resolv_getaddrinfo(self, host, i); 215 break; 216 case METHOD_GETHOSTBY: 217 error = resolv_gethostby(self, host); 218 break; 219 case METHOD_GETIPNODEBY: 220 error = resolv_getipnodeby(self, host); 221 break; 222 default: 223 break; 224 } 225 pthread_mutex_lock(&stats); 226 ask[i]++; 227 got[i] += error == 0; 228 pthread_mutex_unlock(&stats); 229} 230 231static void * 232resolvloop(void *p) 233{ 234 int *nhosts = (int *)p; 235 if (*nhosts == 0) 236 return; 237 do 238 resolvone(*nhosts); 239 while (--(*nhosts)); 240 return NULL; 241} 242 243static void 244run(int *nhosts) 245{ 246 pthread_t self = pthread_self(); 247 if (pthread_create(&self, NULL, resolvloop, nhosts) != 0) 248 err(1, "pthread_create"); 249} 250 251int 252main(int argc, char *argv[]) 253{ 254 int nthreads = NTHREADS; 255 int nhosts = NHOSTS; 256 int i, c, done, *nleft; 257 hosts = sl_init(); 258 259 srandom(1234); 260 261 while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1) 262 switch (c) { 263 case 'A': 264 method = METHOD_GETADDRINFO; 265 break; 266 case 'd': 267 debug++; 268 break; 269 case 'h': 270 nhosts = atoi(optarg); 271 break; 272 case 'H': 273 method = METHOD_GETHOSTBY; 274 break; 275 case 'I': 276 method = METHOD_GETIPNODEBY; 277 break; 278 case 'n': 279 nthreads = atoi(optarg); 280 break; 281 case 'r': 282 reverse++; 283 break; 284 default: 285 usage(); 286 } 287 288 for (i = optind; i < argc; i++) 289 load(argv[i]); 290 291 if (hosts->sl_cur == 0) 292 usage(); 293 294 if ((nleft = malloc(nthreads * sizeof(int))) == NULL) 295 err(1, "malloc"); 296 if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL) 297 err(1, "calloc"); 298 if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL) 299 err(1, "calloc"); 300 301 302 for (i = 0; i < nthreads; i++) { 303 nleft[i] = nhosts; 304 run(&nleft[i]); 305 } 306 307 for (done = 0; !done;) { 308 done = 1; 309 for (i = 0; i < nthreads; i++) { 310 if (nleft[i] != 0) { 311 done = 0; 312 break; 313 } 314 } 315 sleep(1); 316 } 317 c = 0; 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]); 322 c++; 323 } 324 } 325 free(nleft); 326 free(ask); 327 free(got); 328 sl_free(hosts, 1); 329 return c; 330} 331