resolv.c revision 145857
1130803Smarcel/* $NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $ */ 298944Sobrien 3130803Smarcel/*- 4130803Smarcel * Copyright (c) 2004 The NetBSD Foundation, Inc. 598944Sobrien * All rights reserved. 698944Sobrien * 798944Sobrien * This code is derived from software contributed to The NetBSD Foundation 898944Sobrien * by Christos Zoulas. 998944Sobrien * 1098944Sobrien * Redistribution and use in source and binary forms, with or without 1198944Sobrien * modification, are permitted provided that the following conditions 1298944Sobrien * are met: 1398944Sobrien * 1. Redistributions of source code must retain the above copyright 1498944Sobrien * notice, this list of conditions and the following disclaimer. 1598944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1698944Sobrien * notice, this list of conditions and the following disclaimer in the 1798944Sobrien * documentation and/or other materials provided with the distribution. 1898944Sobrien * 3. All advertising materials mentioning features or use of this software 1998944Sobrien * must display the following acknowledgement: 2098944Sobrien * This product includes software developed by the NetBSD 2198944Sobrien * Foundation, Inc. and its contributors. 2298944Sobrien * 4. Neither the name of The NetBSD Foundation nor the names of its 2398944Sobrien * contributors may be used to endorse or promote products derived 2498944Sobrien * from this software without specific prior written permission. 25130803Smarcel * 26130803Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27130803Smarcel * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28130803Smarcel * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29130803Smarcel * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30130803Smarcel * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3198944Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3298944Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3398944Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3498944Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3598944Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3698944Sobrien * POSSIBILITY OF SUCH DAMAGE. 3798944Sobrien */ 3898944Sobrien#include <sys/cdefs.h> 3998944Sobrien__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $"); 4098944Sobrien 4198944Sobrien#include <pthread.h> 4298944Sobrien#include <stdio.h> 4398944Sobrien#include <netdb.h> 4498944Sobrien#include <stdlib.h> 4598944Sobrien#include <unistd.h> 4698944Sobrien#include <err.h> 4798944Sobrien#include <string.h> 4898944Sobrien#include <stringlist.h> 49130803Smarcel 50130803Smarcel#define NTHREADS 10 51130803Smarcel#define NHOSTS 100 52130803Smarcel#define WS " \t\n\r" 53130803Smarcel 54130803Smarcelstatic StringList *hosts = NULL; 55130803Smarcelstatic int debug = 0; 56130803Smarcelstatic int *ask = NULL; 5798944Sobrienstatic int *got = NULL; 5898944Sobrien 5998944Sobrienstatic void usage(void) __attribute__((__noreturn__)); 60130803Smarcelstatic void load(const char *); 61130803Smarcelstatic void resolvone(int); 62130803Smarcelstatic void *resolvloop(void *); 63130803Smarcelstatic void run(int *); 64130803Smarcel 6598944Sobrienstatic pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; 66130803Smarcel 67130803Smarcelstatic void 68130803Smarcelusage(void) 69130803Smarcel{ 70130803Smarcel (void)fprintf(stderr, 71130803Smarcel "Usage: %s [-d] [-h <nhosts>] [-n <nthreads>] <file> ...\n", 72130803Smarcel getprogname()); 73130803Smarcel exit(1); 74130803Smarcel} 75130803Smarcel 76130803Smarcelstatic void 77130803Smarcelload(const char *fname) 78130803Smarcel{ 7998944Sobrien FILE *fp; 8098944Sobrien size_t len; 81130803Smarcel char *line; 82130803Smarcel 83130803Smarcel if ((fp = fopen(fname, "r")) == NULL) 84130803Smarcel err(1, "Cannot open `%s'", fname); 85130803Smarcel while ((line = fgetln(fp, &len)) != NULL) { 86130803Smarcel char c = line[len]; 87130803Smarcel char *ptr; 88130803Smarcel line[len] = '\0'; 89130803Smarcel for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) 90130803Smarcel sl_add(hosts, strdup(ptr)); 91130803Smarcel line[len] = c; 92130803Smarcel } 93130803Smarcel 94130803Smarcel (void)fclose(fp); 95130803Smarcel} 96130803Smarcel 97130803Smarcelstatic void 98130803Smarcelresolvone(int n) 99130803Smarcel{ 100130803Smarcel char buf[1024]; 101130803Smarcel pthread_t self = pthread_self(); 102130803Smarcel size_t i = (random() & 0x0fffffff) % hosts->sl_cur; 10398944Sobrien char *host = hosts->sl_str[i]; 10498944Sobrien struct addrinfo *res; 10598944Sobrien int error, len; 10698944Sobrien if (debug) { 10798944Sobrien len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n", 10898944Sobrien self, n, host, (int)i); 10998944Sobrien (void)write(STDOUT_FILENO, buf, len); 11098944Sobrien } 11198944Sobrien error = getaddrinfo(host, NULL, NULL, &res); 11298944Sobrien if (debug) { 11398944Sobrien len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 11498944Sobrien self, host, error ? "not found" : "ok"); 11598944Sobrien (void)write(STDOUT_FILENO, buf, len); 11698944Sobrien } 11798944Sobrien pthread_mutex_lock(&stats); 11898944Sobrien ask[i]++; 11998944Sobrien got[i] += error == 0; 12098944Sobrien pthread_mutex_unlock(&stats); 12198944Sobrien if (error == 0) 12298944Sobrien freeaddrinfo(res); 12398944Sobrien} 12498944Sobrien 12598944Sobrienstatic void * 12698944Sobrienresolvloop(void *p) 12798944Sobrien{ 12898944Sobrien int *nhosts = (int *)p; 12998944Sobrien if (*nhosts == 0) 13098944Sobrien return; 13198944Sobrien do 13298944Sobrien resolvone(*nhosts); 13398944Sobrien while (--(*nhosts)); 13498944Sobrien return NULL; 13598944Sobrien} 13698944Sobrien 13798944Sobrienstatic void 13898944Sobrienrun(int *nhosts) 139130803Smarcel{ 140130803Smarcel pthread_t self = pthread_self(); 141130803Smarcel if (pthread_create(&self, NULL, resolvloop, nhosts) != 0) 142130803Smarcel err(1, "pthread_create"); 14398944Sobrien} 14498944Sobrien 14598944Sobrienint 14698944Sobrienmain(int argc, char *argv[]) 14798944Sobrien{ 14898944Sobrien int nthreads = NTHREADS; 14998944Sobrien int nhosts = NHOSTS; 15098944Sobrien int i, c, done, *nleft; 15198944Sobrien hosts = sl_init(); 15298944Sobrien 153130803Smarcel srandom(1234); 15498944Sobrien 155130803Smarcel while ((c = getopt(argc, argv, "dh:n:")) != -1) 156130803Smarcel switch (c) { 157130803Smarcel case 'd': 158130803Smarcel debug++; 159130803Smarcel break; 160130803Smarcel case 'h': 161130803Smarcel nhosts = atoi(optarg); 162130803Smarcel break; 163130803Smarcel case 'n': 164130803Smarcel nthreads = atoi(optarg); 165130803Smarcel break; 166130803Smarcel default: 167130803Smarcel usage(); 168130803Smarcel } 169130803Smarcel 170130803Smarcel for (i = optind; i < argc; i++) 171130803Smarcel load(argv[i]); 172130803Smarcel 173130803Smarcel if (hosts->sl_cur == 0) 174130803Smarcel usage(); 17598944Sobrien 176130803Smarcel if ((nleft = malloc(nthreads * sizeof(int))) == NULL) 177130803Smarcel err(1, "malloc"); 178130803Smarcel if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL) 179130803Smarcel err(1, "calloc"); 180130803Smarcel if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL) 181130803Smarcel err(1, "calloc"); 182130803Smarcel 183130803Smarcel 184130803Smarcel for (i = 0; i < nthreads; i++) { 185130803Smarcel nleft[i] = nhosts; 186130803Smarcel run(&nleft[i]); 187130803Smarcel } 188130803Smarcel 189130803Smarcel for (done = 0; !done;) { 190130803Smarcel done = 1; 191130803Smarcel for (i = 0; i < nthreads; i++) { 192130803Smarcel if (nleft[i] != 0) { 193130803Smarcel done = 0; 194130803Smarcel break; 195130803Smarcel } 196130803Smarcel } 197130803Smarcel sleep(1); 198130803Smarcel } 199130803Smarcel c = 0; 200130803Smarcel for (i = 0; i < hosts->sl_cur; i++) { 201130803Smarcel if (ask[i] != got[i] && got[i] != 0) { 202130803Smarcel warnx("Error: host %s ask %d got %d\n", 203130803Smarcel hosts->sl_str[i], ask[i], got[i]); 204130803Smarcel c++; 205130803Smarcel } 206130803Smarcel } 207130803Smarcel free(nleft); 208130803Smarcel free(ask); 209130803Smarcel free(got); 210130803Smarcel sl_free(hosts, 1); 211130803Smarcel return c; 212130803Smarcel} 213130803Smarcel