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