resolv_test.c revision 291362
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: head/tools/regression/lib/libc/resolv/resolv.c 291362 2015-11-26 07:58:22Z ngie $ */ 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 50enum method { 51 METHOD_GETADDRINFO, 52 METHOD_GETHOSTBY, 53 METHOD_GETIPNODEBY 54}; 55 56static StringList *hosts = NULL; 57static int debug = 0; 58static enum method method = METHOD_GETADDRINFO; 59static int reverse = 0; 60static int *ask = NULL; 61static int *got = NULL; 62 63static void usage(void) __attribute__((__noreturn__)); 64static void load(const char *); 65static void resolvone(int); 66static void *resolvloop(void *); 67static void run(int *); 68 69static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; 70 71static void 72usage(void) 73{ 74 (void)fprintf(stderr, 75 "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n", 76 getprogname()); 77 exit(1); 78} 79 80static void 81load(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 104static int 105resolv_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 138static int 139resolv_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 163static int 164resolv_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 193static void 194resolvone(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 227static void * 228resolvloop(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 239static void 240run(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 247int 248main(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} 327