1145857Sume/* $NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $ */ 2145857Sume 3145857Sume/*- 4145857Sume * Copyright (c) 2004 The NetBSD Foundation, Inc. 5145857Sume * All rights reserved. 6145857Sume * 7145857Sume * This code is derived from software contributed to The NetBSD Foundation 8145857Sume * by Christos Zoulas. 9145857Sume * 10145857Sume * Redistribution and use in source and binary forms, with or without 11145857Sume * modification, are permitted provided that the following conditions 12145857Sume * are met: 13145857Sume * 1. Redistributions of source code must retain the above copyright 14145857Sume * notice, this list of conditions and the following disclaimer. 15145857Sume * 2. Redistributions in binary form must reproduce the above copyright 16145857Sume * notice, this list of conditions and the following disclaimer in the 17145857Sume * documentation and/or other materials provided with the distribution. 18145857Sume * 19145857Sume * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20145857Sume * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21145857Sume * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22145857Sume * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23145857Sume * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24145857Sume * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25145857Sume * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26145857Sume * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27145857Sume * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28145857Sume * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29145857Sume * POSSIBILITY OF SUCH DAMAGE. 30145857Sume */ 31145860Sume/* $FreeBSD: releng/10.2/tools/regression/lib/libc/resolv/resolv.c 243346 2012-11-20 19:23:44Z emaste $ */ 32145857Sume#include <sys/cdefs.h> 33145857Sume__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $"); 34145857Sume 35145860Sume#include <sys/types.h> 36145860Sume#include <sys/socket.h> 37145857Sume#include <pthread.h> 38145857Sume#include <stdio.h> 39145857Sume#include <netdb.h> 40145857Sume#include <stdlib.h> 41145857Sume#include <unistd.h> 42145857Sume#include <err.h> 43145857Sume#include <string.h> 44145857Sume#include <stringlist.h> 45145857Sume 46145857Sume#define NTHREADS 10 47145857Sume#define NHOSTS 100 48145857Sume#define WS " \t\n\r" 49145857Sume 50145860Sumeenum method { 51145860Sume METHOD_GETADDRINFO, 52145860Sume METHOD_GETHOSTBY, 53145860Sume METHOD_GETIPNODEBY 54145860Sume}; 55145860Sume 56145857Sumestatic StringList *hosts = NULL; 57145857Sumestatic int debug = 0; 58145860Sumestatic enum method method = METHOD_GETADDRINFO; 59145860Sumestatic int reverse = 0; 60145857Sumestatic int *ask = NULL; 61145857Sumestatic int *got = NULL; 62145857Sume 63145857Sumestatic void usage(void) __attribute__((__noreturn__)); 64145857Sumestatic void load(const char *); 65145857Sumestatic void resolvone(int); 66145857Sumestatic void *resolvloop(void *); 67145857Sumestatic void run(int *); 68145857Sume 69145857Sumestatic pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; 70145857Sume 71145857Sumestatic void 72145857Sumeusage(void) 73145857Sume{ 74145857Sume (void)fprintf(stderr, 75145860Sume "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n", 76145857Sume getprogname()); 77145857Sume exit(1); 78145857Sume} 79145857Sume 80145857Sumestatic void 81145857Sumeload(const char *fname) 82145857Sume{ 83145857Sume FILE *fp; 84145857Sume size_t len; 85145857Sume char *line; 86145857Sume 87145857Sume if ((fp = fopen(fname, "r")) == NULL) 88145857Sume err(1, "Cannot open `%s'", fname); 89145857Sume while ((line = fgetln(fp, &len)) != NULL) { 90145857Sume char c = line[len]; 91145857Sume char *ptr; 92145857Sume line[len] = '\0'; 93145857Sume for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) 94145857Sume sl_add(hosts, strdup(ptr)); 95145857Sume line[len] = c; 96145857Sume } 97145857Sume 98145857Sume (void)fclose(fp); 99145857Sume} 100145857Sume 101145860Sumestatic int 102145860Sumeresolv_getaddrinfo(pthread_t self, char *host, int port) 103145860Sume{ 104145860Sume char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 105145860Sume struct addrinfo hints, *res; 106145860Sume int error, len; 107145860Sume 108145860Sume snprintf(portstr, sizeof(portstr), "%d", port); 109145860Sume memset(&hints, 0, sizeof(hints)); 110145860Sume hints.ai_family = AF_UNSPEC; 111145860Sume hints.ai_flags = AI_PASSIVE; 112145860Sume hints.ai_socktype = SOCK_STREAM; 113145860Sume error = getaddrinfo(host, portstr, &hints, &res); 114145860Sume if (debug) { 115145860Sume len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 116145860Sume self, host, error ? "not found" : "ok"); 117145860Sume (void)write(STDOUT_FILENO, buf, len); 118145860Sume } 119145860Sume if (error == 0 && reverse) { 120145860Sume memset(hbuf, 0, sizeof(hbuf)); 121145860Sume memset(pbuf, 0, sizeof(pbuf)); 122145860Sume getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), 123145860Sume pbuf, sizeof(pbuf), 0); 124145860Sume if (debug) { 125145860Sume len = snprintf(buf, sizeof(buf), 126145860Sume "%p: reverse %s %s\n", self, hbuf, pbuf); 127145860Sume (void)write(STDOUT_FILENO, buf, len); 128145860Sume } 129145860Sume } 130145860Sume if (error == 0) 131145860Sume freeaddrinfo(res); 132145860Sume return error; 133145860Sume} 134145860Sume 135145860Sumestatic int 136145860Sumeresolv_gethostby(pthread_t self, char *host) 137145860Sume{ 138145860Sume char buf[1024]; 139145860Sume struct hostent *hp, *hp2; 140145860Sume int len; 141145860Sume 142145860Sume hp = gethostbyname(host); 143145860Sume if (debug) { 144145860Sume len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 145145860Sume self, host, (hp == NULL) ? "not found" : "ok"); 146145860Sume (void)write(STDOUT_FILENO, buf, len); 147145860Sume } 148145860Sume if (hp && reverse) { 149145860Sume memcpy(buf, hp->h_addr, hp->h_length); 150145860Sume hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype); 151145860Sume if (hp2 && debug) { 152145860Sume len = snprintf(buf, sizeof(buf), 153145860Sume "%p: reverse %s\n", self, hp2->h_name); 154145860Sume (void)write(STDOUT_FILENO, buf, len); 155145860Sume } 156145860Sume } 157145860Sume return hp ? 0 : -1; 158145860Sume} 159145860Sume 160145860Sumestatic int 161145860Sumeresolv_getipnodeby(pthread_t self, char *host) 162145860Sume{ 163145860Sume char buf[1024]; 164145860Sume struct hostent *hp, *hp2; 165145860Sume int len, h_error; 166145860Sume 167145860Sume hp = getipnodebyname(host, AF_INET, 0, &h_error); 168145860Sume if (debug) { 169145860Sume len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 170145860Sume self, host, (hp == NULL) ? "not found" : "ok"); 171145860Sume (void)write(STDOUT_FILENO, buf, len); 172145860Sume } 173145860Sume if (hp && reverse) { 174145860Sume memcpy(buf, hp->h_addr, hp->h_length); 175145860Sume hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype, 176145860Sume &h_error); 177145860Sume if (hp2 && debug) { 178145860Sume len = snprintf(buf, sizeof(buf), 179145860Sume "%p: reverse %s\n", self, hp2->h_name); 180145860Sume (void)write(STDOUT_FILENO, buf, len); 181145860Sume } 182145860Sume if (hp2) 183145860Sume freehostent(hp2); 184145860Sume } 185145860Sume if (hp) 186145860Sume freehostent(hp); 187145860Sume return hp ? 0 : -1; 188145860Sume} 189145860Sume 190145857Sumestatic void 191145857Sumeresolvone(int n) 192145857Sume{ 193145857Sume char buf[1024]; 194145857Sume pthread_t self = pthread_self(); 195145857Sume size_t i = (random() & 0x0fffffff) % hosts->sl_cur; 196145857Sume char *host = hosts->sl_str[i]; 197145860Sume struct addrinfo hints, *res; 198145857Sume int error, len; 199145860Sume 200145857Sume if (debug) { 201145857Sume len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n", 202145857Sume self, n, host, (int)i); 203145857Sume (void)write(STDOUT_FILENO, buf, len); 204145857Sume } 205145860Sume switch (method) { 206145860Sume case METHOD_GETADDRINFO: 207145860Sume error = resolv_getaddrinfo(self, host, i); 208145860Sume break; 209145860Sume case METHOD_GETHOSTBY: 210145860Sume error = resolv_gethostby(self, host); 211145860Sume break; 212145860Sume case METHOD_GETIPNODEBY: 213145860Sume error = resolv_getipnodeby(self, host); 214145860Sume break; 215145860Sume default: 216145860Sume break; 217145857Sume } 218145857Sume pthread_mutex_lock(&stats); 219145857Sume ask[i]++; 220145857Sume got[i] += error == 0; 221145857Sume pthread_mutex_unlock(&stats); 222145857Sume} 223145857Sume 224145857Sumestatic void * 225145857Sumeresolvloop(void *p) 226145857Sume{ 227145857Sume int *nhosts = (int *)p; 228145857Sume if (*nhosts == 0) 229243346Semaste return NULL; 230145857Sume do 231145857Sume resolvone(*nhosts); 232145857Sume while (--(*nhosts)); 233145857Sume return NULL; 234145857Sume} 235145857Sume 236145857Sumestatic void 237145857Sumerun(int *nhosts) 238145857Sume{ 239145857Sume pthread_t self = pthread_self(); 240145857Sume if (pthread_create(&self, NULL, resolvloop, nhosts) != 0) 241145857Sume err(1, "pthread_create"); 242145857Sume} 243145857Sume 244145857Sumeint 245145857Sumemain(int argc, char *argv[]) 246145857Sume{ 247145857Sume int nthreads = NTHREADS; 248145857Sume int nhosts = NHOSTS; 249145857Sume int i, c, done, *nleft; 250145857Sume hosts = sl_init(); 251145857Sume 252145857Sume srandom(1234); 253145857Sume 254145860Sume while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1) 255145857Sume switch (c) { 256145860Sume case 'A': 257145860Sume method = METHOD_GETADDRINFO; 258145860Sume break; 259145857Sume case 'd': 260145857Sume debug++; 261145857Sume break; 262145857Sume case 'h': 263145857Sume nhosts = atoi(optarg); 264145857Sume break; 265145860Sume case 'H': 266145860Sume method = METHOD_GETHOSTBY; 267145860Sume break; 268145860Sume case 'I': 269145860Sume method = METHOD_GETIPNODEBY; 270145860Sume break; 271145857Sume case 'n': 272145857Sume nthreads = atoi(optarg); 273145857Sume break; 274145860Sume case 'r': 275145860Sume reverse++; 276145860Sume break; 277145857Sume default: 278145857Sume usage(); 279145857Sume } 280145857Sume 281145857Sume for (i = optind; i < argc; i++) 282145857Sume load(argv[i]); 283145857Sume 284145857Sume if (hosts->sl_cur == 0) 285145857Sume usage(); 286145857Sume 287145857Sume if ((nleft = malloc(nthreads * sizeof(int))) == NULL) 288145857Sume err(1, "malloc"); 289145857Sume if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL) 290145857Sume err(1, "calloc"); 291145857Sume if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL) 292145857Sume err(1, "calloc"); 293145857Sume 294145857Sume 295145857Sume for (i = 0; i < nthreads; i++) { 296145857Sume nleft[i] = nhosts; 297145857Sume run(&nleft[i]); 298145857Sume } 299145857Sume 300145857Sume for (done = 0; !done;) { 301145857Sume done = 1; 302145857Sume for (i = 0; i < nthreads; i++) { 303145857Sume if (nleft[i] != 0) { 304145857Sume done = 0; 305145857Sume break; 306145857Sume } 307145857Sume } 308145857Sume sleep(1); 309145857Sume } 310145857Sume c = 0; 311145857Sume for (i = 0; i < hosts->sl_cur; i++) { 312145857Sume if (ask[i] != got[i] && got[i] != 0) { 313145857Sume warnx("Error: host %s ask %d got %d\n", 314145857Sume hosts->sl_str[i], ask[i], got[i]); 315145857Sume c++; 316145857Sume } 317145857Sume } 318145857Sume free(nleft); 319145857Sume free(ask); 320145857Sume free(got); 321145857Sume sl_free(hosts, 1); 322145857Sume return c; 323145857Sume} 324