resolv_test.c revision 291362
1227569Sphilip/* $NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $ */ 2227569Sphilip 3227569Sphilip/*- 4227569Sphilip * Copyright (c) 2004 The NetBSD Foundation, Inc. 5227569Sphilip * All rights reserved. 6227569Sphilip * 7227569Sphilip * This code is derived from software contributed to The NetBSD Foundation 8227569Sphilip * by Christos Zoulas. 9227569Sphilip * 10227569Sphilip * Redistribution and use in source and binary forms, with or without 11227569Sphilip * modification, are permitted provided that the following conditions 12227569Sphilip * are met: 13227569Sphilip * 1. Redistributions of source code must retain the above copyright 14227569Sphilip * notice, this list of conditions and the following disclaimer. 15227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright 16227569Sphilip * notice, this list of conditions and the following disclaimer in the 17227569Sphilip * documentation and/or other materials provided with the distribution. 18227569Sphilip * 19227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20227569Sphilip * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21227569Sphilip * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22227569Sphilip * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23227569Sphilip * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24227569Sphilip * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25227569Sphilip * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26227569Sphilip * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27227569Sphilip * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28227569Sphilip * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29227569Sphilip * POSSIBILITY OF SUCH DAMAGE. 30227569Sphilip */ 31227569Sphilip/* $FreeBSD: head/tools/regression/lib/libc/resolv/resolv.c 291362 2015-11-26 07:58:22Z ngie $ */ 32227569Sphilip#include <sys/cdefs.h> 33272325Sgnn__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $"); 34227569Sphilip 35227569Sphilip#include <sys/types.h> 36227569Sphilip#include <sys/socket.h> 37227569Sphilip#include <pthread.h> 38227569Sphilip#include <stdio.h> 39227569Sphilip#include <netdb.h> 40227569Sphilip#include <stdlib.h> 41227569Sphilip#include <unistd.h> 42227569Sphilip#include <err.h> 43227569Sphilip#include <string.h> 44227569Sphilip#include <stringlist.h> 45257176Sglebius 46227569Sphilip#define NTHREADS 10 47227569Sphilip#define NHOSTS 100 48227569Sphilip#define WS " \t\n\r" 49227569Sphilip 50227569Sphilipenum method { 51227569Sphilip METHOD_GETADDRINFO, 52227569Sphilip METHOD_GETHOSTBY, 53227569Sphilip METHOD_GETIPNODEBY 54227569Sphilip}; 55227569Sphilip 56272325Sgnnstatic StringList *hosts = NULL; 57227569Sphilipstatic int debug = 0; 58227569Sphilipstatic enum method method = METHOD_GETADDRINFO; 59272325Sgnnstatic int reverse = 0; 60227569Sphilipstatic int *ask = NULL; 61227569Sphilipstatic int *got = NULL; 62272325Sgnn 63227569Sphilipstatic void usage(void) __attribute__((__noreturn__)); 64227569Sphilipstatic void load(const char *); 65272325Sgnnstatic void resolvone(int); 66227569Sphilipstatic void *resolvloop(void *); 67227569Sphilipstatic void run(int *); 68272325Sgnn 69227569Sphilipstatic pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; 70227569Sphilip 71227569Sphilipstatic void 72227569Sphilipusage(void) 73227569Sphilip{ 74272325Sgnn (void)fprintf(stderr, 75227569Sphilip "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n", 76227569Sphilip getprogname()); 77227569Sphilip exit(1); 78272325Sgnn} 79227569Sphilip 80227569Sphilipstatic void 81272325Sgnnload(const char *fname) 82227569Sphilip{ 83227569Sphilip FILE *fp; 84272325Sgnn size_t len; 85227569Sphilip char *line; 86227569Sphilip 87227569Sphilip if ((fp = fopen(fname, "r")) == NULL) 88227569Sphilip err(1, "Cannot open `%s'", fname); 89227569Sphilip while ((line = fgetln(fp, &len)) != NULL) { 90272328Sgnn char c = line[len]; 91272328Sgnn char *ptr; 92272325Sgnn line[len] = '\0'; 93227569Sphilip for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) { 94272325Sgnn if (ptr == '\0' || ptr[0] == '#') 95227569Sphilip continue; 96227569Sphilip sl_add(hosts, strdup(ptr)); 97227569Sphilip } 98227569Sphilip line[len] = c; 99227569Sphilip } 100227569Sphilip 101227569Sphilip (void)fclose(fp); 102227569Sphilip} 103227569Sphilip 104227569Sphilipstatic int 105227569Sphilipresolv_getaddrinfo(pthread_t self, char *host, int port) 106227569Sphilip{ 107227569Sphilip char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 108227569Sphilip struct addrinfo hints, *res; 109227569Sphilip int error, len; 110227569Sphilip 111272328Sgnn snprintf(portstr, sizeof(portstr), "%d", port); 112227569Sphilip memset(&hints, 0, sizeof(hints)); 113227569Sphilip hints.ai_family = AF_UNSPEC; 114227569Sphilip hints.ai_flags = AI_PASSIVE; 115227569Sphilip hints.ai_socktype = SOCK_STREAM; 116227569Sphilip error = getaddrinfo(host, portstr, &hints, &res); 117227569Sphilip if (debug) { 118227569Sphilip len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 119227569Sphilip self, host, error ? "not found" : "ok"); 120227569Sphilip (void)write(STDOUT_FILENO, buf, len); 121227569Sphilip } 122227569Sphilip if (error == 0 && reverse) { 123227569Sphilip memset(hbuf, 0, sizeof(hbuf)); 124227569Sphilip memset(pbuf, 0, sizeof(pbuf)); 125227569Sphilip getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), 126227569Sphilip pbuf, sizeof(pbuf), 0); 127227569Sphilip if (debug) { 128227569Sphilip len = snprintf(buf, sizeof(buf), 129227569Sphilip "%p: reverse %s %s\n", self, hbuf, pbuf); 130227569Sphilip (void)write(STDOUT_FILENO, buf, len); 131227569Sphilip } 132227569Sphilip } 133227569Sphilip if (error == 0) 134227569Sphilip freeaddrinfo(res); 135227569Sphilip return error; 136227569Sphilip} 137227569Sphilip 138272325Sgnnstatic int 139272325Sgnnresolv_gethostby(pthread_t self, char *host) 140272325Sgnn{ 141227569Sphilip char buf[1024]; 142227569Sphilip struct hostent *hp, *hp2; 143227569Sphilip int len; 144227569Sphilip 145227569Sphilip hp = gethostbyname(host); 146227569Sphilip if (debug) { 147227569Sphilip len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 148227569Sphilip self, host, (hp == NULL) ? "not found" : "ok"); 149227569Sphilip (void)write(STDOUT_FILENO, buf, len); 150227569Sphilip } 151227569Sphilip if (hp && reverse) { 152227569Sphilip memcpy(buf, hp->h_addr, hp->h_length); 153227569Sphilip hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype); 154227569Sphilip if (hp2 && debug) { 155227569Sphilip len = snprintf(buf, sizeof(buf), 156227569Sphilip "%p: reverse %s\n", self, hp2->h_name); 157227569Sphilip (void)write(STDOUT_FILENO, buf, len); 158227569Sphilip } 159227569Sphilip } 160227569Sphilip return hp ? 0 : -1; 161227569Sphilip} 162227569Sphilip 163227569Sphilipstatic int 164227569Sphilipresolv_getipnodeby(pthread_t self, char *host) 165227569Sphilip{ 166227569Sphilip char buf[1024]; 167227569Sphilip struct hostent *hp, *hp2; 168227569Sphilip int len, h_error; 169227569Sphilip 170227569Sphilip hp = getipnodebyname(host, AF_INET, 0, &h_error); 171227569Sphilip if (debug) { 172227569Sphilip len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 173227569Sphilip self, host, (hp == NULL) ? "not found" : "ok"); 174227569Sphilip (void)write(STDOUT_FILENO, buf, len); 175227569Sphilip } 176227569Sphilip if (hp && reverse) { 177227569Sphilip memcpy(buf, hp->h_addr, hp->h_length); 178227569Sphilip hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype, 179227569Sphilip &h_error); 180227569Sphilip if (hp2 && debug) { 181227569Sphilip len = snprintf(buf, sizeof(buf), 182227569Sphilip "%p: reverse %s\n", self, hp2->h_name); 183227569Sphilip (void)write(STDOUT_FILENO, buf, len); 184227569Sphilip } 185227569Sphilip if (hp2) 186227569Sphilip freehostent(hp2); 187227569Sphilip } 188227569Sphilip if (hp) 189227569Sphilip freehostent(hp); 190227569Sphilip return hp ? 0 : -1; 191227569Sphilip} 192227569Sphilip 193227569Sphilipstatic void 194227569Sphilipresolvone(int n) 195227569Sphilip{ 196227569Sphilip char buf[1024]; 197227569Sphilip pthread_t self = pthread_self(); 198227569Sphilip size_t i = (random() & 0x0fffffff) % hosts->sl_cur; 199227569Sphilip char *host = hosts->sl_str[i]; 200227569Sphilip struct addrinfo hints, *res; 201227569Sphilip int error, len; 202272325Sgnn 203227569Sphilip if (debug) { 204227569Sphilip len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n", 205227569Sphilip self, n, host, (int)i); 206227569Sphilip (void)write(STDOUT_FILENO, buf, len); 207227569Sphilip } 208227569Sphilip switch (method) { 209227569Sphilip case METHOD_GETADDRINFO: 210227569Sphilip error = resolv_getaddrinfo(self, host, i); 211227569Sphilip break; 212227569Sphilip case METHOD_GETHOSTBY: 213227569Sphilip error = resolv_gethostby(self, host); 214272328Sgnn break; 215272328Sgnn case METHOD_GETIPNODEBY: 216272328Sgnn error = resolv_getipnodeby(self, host); 217272325Sgnn break; 218227569Sphilip default: 219227569Sphilip break; 220227569Sphilip } 221227569Sphilip pthread_mutex_lock(&stats); 222227569Sphilip ask[i]++; 223227569Sphilip got[i] += error == 0; 224227569Sphilip pthread_mutex_unlock(&stats); 225227569Sphilip} 226227569Sphilip 227227569Sphilipstatic void * 228227569Sphilipresolvloop(void *p) 229227569Sphilip{ 230227569Sphilip int *nhosts = (int *)p; 231227569Sphilip if (*nhosts == 0) 232227569Sphilip return NULL; 233227569Sphilip do 234227569Sphilip resolvone(*nhosts); 235227569Sphilip while (--(*nhosts)); 236227569Sphilip return NULL; 237227569Sphilip} 238227569Sphilip 239227569Sphilipstatic void 240227569Sphiliprun(int *nhosts) 241227569Sphilip{ 242227569Sphilip pthread_t self = pthread_self(); 243227569Sphilip if (pthread_create(&self, NULL, resolvloop, nhosts) != 0) 244227569Sphilip err(1, "pthread_create"); 245227569Sphilip} 246227569Sphilip 247227569Sphilipint 248227569Sphilipmain(int argc, char *argv[]) 249227569Sphilip{ 250227569Sphilip int nthreads = NTHREADS; 251272325Sgnn int nhosts = NHOSTS; 252272325Sgnn int i, c, done, *nleft; 253227569Sphilip hosts = sl_init(); 254272328Sgnn 255272328Sgnn srandom(1234); 256272328Sgnn 257272328Sgnn while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1) 258227569Sphilip switch (c) { 259227569Sphilip case 'A': 260227569Sphilip method = METHOD_GETADDRINFO; 261227569Sphilip break; 262227569Sphilip case 'd': 263227569Sphilip debug++; 264227569Sphilip break; 265227569Sphilip case 'h': 266227569Sphilip nhosts = atoi(optarg); 267227569Sphilip break; 268227569Sphilip case 'H': 269227569Sphilip method = METHOD_GETHOSTBY; 270227569Sphilip break; 271227569Sphilip case 'I': 272227569Sphilip method = METHOD_GETIPNODEBY; 273227569Sphilip break; 274227569Sphilip case 'n': 275227569Sphilip nthreads = atoi(optarg); 276227569Sphilip break; 277227569Sphilip case 'r': 278227569Sphilip reverse++; 279227569Sphilip break; 280227569Sphilip default: 281227569Sphilip usage(); 282227569Sphilip } 283227569Sphilip 284227569Sphilip for (i = optind; i < argc; i++) 285227569Sphilip load(argv[i]); 286227569Sphilip 287227569Sphilip if (hosts->sl_cur == 0) 288227569Sphilip usage(); 289227569Sphilip 290227569Sphilip if ((nleft = malloc(nthreads * sizeof(int))) == NULL) 291227569Sphilip err(1, "malloc"); 292227569Sphilip if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL) 293227569Sphilip err(1, "calloc"); 294227569Sphilip if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL) 295227569Sphilip err(1, "calloc"); 296227569Sphilip 297227569Sphilip 298227569Sphilip for (i = 0; i < nthreads; i++) { 299227569Sphilip nleft[i] = nhosts; 300227569Sphilip run(&nleft[i]); 301227569Sphilip } 302227569Sphilip 303227569Sphilip for (done = 0; !done;) { 304227569Sphilip done = 1; 305227569Sphilip for (i = 0; i < nthreads; i++) { 306227569Sphilip if (nleft[i] != 0) { 307227569Sphilip done = 0; 308227569Sphilip break; 309227569Sphilip } 310227569Sphilip } 311272325Sgnn sleep(1); 312227569Sphilip } 313227569Sphilip 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