1272343Sngie/* $NetBSD: h_resolv.c,v 1.2 2010/11/03 16:10:22 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * This code is derived from software contributed to The NetBSD Foundation 8272343Sngie * by Christos Zoulas. 9272343Sngie * 10272343Sngie * Redistribution and use in source and binary forms, with or without 11272343Sngie * modification, are permitted provided that the following conditions 12272343Sngie * are met: 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in the 17272343Sngie * documentation and/or other materials provided with the distribution. 18272343Sngie * 19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29272343Sngie * POSSIBILITY OF SUCH DAMAGE. 30272343Sngie */ 31272343Sngie 32272343Sngie#include <sys/cdefs.h> 33272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008\ 34272343Sngie The NetBSD Foundation, inc. All rights reserved."); 35272343Sngie__RCSID("$NetBSD: h_resolv.c,v 1.2 2010/11/03 16:10:22 christos Exp $"); 36272343Sngie 37272343Sngie#include <pthread.h> 38272343Sngie#include <stdio.h> 39272343Sngie#include <netdb.h> 40272343Sngie#include <stdlib.h> 41272343Sngie#include <unistd.h> 42272343Sngie#include <err.h> 43272343Sngie#include <string.h> 44272343Sngie#include <stringlist.h> 45272343Sngie 46272343Sngie#define NTHREADS 10 47272343Sngie#define NHOSTS 100 48272343Sngie#define WS " \t\n\r" 49272343Sngie 50272343Sngiestatic StringList *hosts = NULL; 51272343Sngiestatic int debug = 0; 52272343Sngiestatic int *ask = NULL; 53272343Sngiestatic int *got = NULL; 54272343Sngie 55272343Sngiestatic void usage(void) __attribute__((__noreturn__)); 56272343Sngiestatic void load(const char *); 57272343Sngiestatic void resolvone(int); 58272343Sngiestatic void *resolvloop(void *); 59272343Sngiestatic void run(int *); 60272343Sngie 61272343Sngiestatic pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; 62272343Sngie 63272343Sngiestatic void 64272343Sngieusage(void) 65272343Sngie{ 66272343Sngie (void)fprintf(stderr, 67272343Sngie "Usage: %s [-d] [-h <nhosts>] [-n <nthreads>] <file> ...\n", 68272343Sngie getprogname()); 69272343Sngie exit(1); 70272343Sngie} 71272343Sngie 72272343Sngiestatic void 73272343Sngieload(const char *fname) 74272343Sngie{ 75272343Sngie FILE *fp; 76272343Sngie size_t len; 77272343Sngie char *line; 78272343Sngie 79272343Sngie if ((fp = fopen(fname, "r")) == NULL) 80272343Sngie err(1, "Cannot open `%s'", fname); 81272343Sngie while ((line = fgetln(fp, &len)) != NULL) { 82272343Sngie char c = line[len]; 83272343Sngie char *ptr; 84272343Sngie line[len] = '\0'; 85272343Sngie for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) 86272343Sngie sl_add(hosts, strdup(ptr)); 87272343Sngie line[len] = c; 88272343Sngie } 89272343Sngie 90272343Sngie (void)fclose(fp); 91272343Sngie} 92272343Sngie 93272343Sngiestatic void 94272343Sngieresolvone(int n) 95272343Sngie{ 96272343Sngie char buf[1024]; 97272343Sngie pthread_t self = pthread_self(); 98272343Sngie size_t i = (random() & 0x0fffffff) % hosts->sl_cur; 99272343Sngie char *host = hosts->sl_str[i]; 100272343Sngie struct addrinfo *res; 101272343Sngie int error, len; 102272343Sngie if (debug) { 103272343Sngie len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n", 104272343Sngie self, n, host, (int)i); 105272343Sngie (void)write(STDOUT_FILENO, buf, len); 106272343Sngie } 107272343Sngie error = getaddrinfo(host, NULL, NULL, &res); 108272343Sngie if (debug) { 109272343Sngie len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 110272343Sngie self, host, error ? "not found" : "ok"); 111272343Sngie (void)write(STDOUT_FILENO, buf, len); 112272343Sngie } 113272343Sngie pthread_mutex_lock(&stats); 114272343Sngie ask[i]++; 115272343Sngie got[i] += error == 0; 116272343Sngie pthread_mutex_unlock(&stats); 117272343Sngie if (error == 0) 118272343Sngie freeaddrinfo(res); 119272343Sngie} 120272343Sngie 121272343Sngiestatic void * 122272343Sngieresolvloop(void *p) 123272343Sngie{ 124272343Sngie int *nhosts = (int *)p; 125272343Sngie if (*nhosts == 0) 126272343Sngie return NULL; 127272343Sngie do 128272343Sngie resolvone(*nhosts); 129272343Sngie while (--(*nhosts)); 130272343Sngie return NULL; 131272343Sngie} 132272343Sngie 133272343Sngiestatic void 134272343Sngierun(int *nhosts) 135272343Sngie{ 136272343Sngie pthread_t self = pthread_self(); 137272343Sngie if (pthread_create(&self, NULL, resolvloop, nhosts) != 0) 138272343Sngie err(1, "pthread_create"); 139272343Sngie} 140272343Sngie 141272343Sngieint 142272343Sngiemain(int argc, char *argv[]) 143272343Sngie{ 144272343Sngie int nthreads = NTHREADS; 145272343Sngie int nhosts = NHOSTS; 146272343Sngie int i, c, done, *nleft; 147272343Sngie hosts = sl_init(); 148272343Sngie 149272343Sngie srandom(1234); 150272343Sngie 151272343Sngie while ((c = getopt(argc, argv, "dh:n:")) != -1) 152272343Sngie switch (c) { 153272343Sngie case 'd': 154272343Sngie debug++; 155272343Sngie break; 156272343Sngie case 'h': 157272343Sngie nhosts = atoi(optarg); 158272343Sngie break; 159272343Sngie case 'n': 160272343Sngie nthreads = atoi(optarg); 161272343Sngie break; 162272343Sngie default: 163272343Sngie usage(); 164272343Sngie } 165272343Sngie 166272343Sngie for (i = optind; i < argc; i++) 167272343Sngie load(argv[i]); 168272343Sngie 169272343Sngie if (hosts->sl_cur == 0) 170272343Sngie usage(); 171272343Sngie 172272343Sngie if ((nleft = malloc(nthreads * sizeof(int))) == NULL) 173272343Sngie err(1, "malloc"); 174272343Sngie if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL) 175272343Sngie err(1, "calloc"); 176272343Sngie if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL) 177272343Sngie err(1, "calloc"); 178272343Sngie 179272343Sngie 180272343Sngie for (i = 0; i < nthreads; i++) { 181272343Sngie nleft[i] = nhosts; 182272343Sngie run(&nleft[i]); 183272343Sngie } 184272343Sngie 185272343Sngie for (done = 0; !done;) { 186272343Sngie done = 1; 187272343Sngie for (i = 0; i < nthreads; i++) { 188272343Sngie if (nleft[i] != 0) { 189272343Sngie done = 0; 190272343Sngie break; 191272343Sngie } 192272343Sngie } 193272343Sngie sleep(1); 194272343Sngie } 195272343Sngie c = 0; 196272343Sngie for (i = 0; i < (int)hosts->sl_cur; i++) { 197272343Sngie if (ask[i] != got[i] && got[i] != 0) { 198272343Sngie warnx("Error: host %s ask %d got %d\n", 199272343Sngie hosts->sl_str[i], ask[i], got[i]); 200272343Sngie c++; 201272343Sngie } 202272343Sngie } 203272343Sngie free(nleft); 204272343Sngie free(ask); 205272343Sngie free(got); 206272343Sngie sl_free(hosts, 1); 207272343Sngie return c; 208272343Sngie} 209