1 /* $NetBSD: h_resolv.c,v 1.2 2010/11/03 16:10:22 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2004, 2008 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 32 #include <sys/cdefs.h> 33 __COPYRIGHT("@(#) Copyright (c) 2008\ 34 The NetBSD Foundation, inc. All rights reserved."); 35 __RCSID("$NetBSD: h_resolv.c,v 1.2 2010/11/03 16:10:22 christos Exp $"); 36 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 50 static StringList *hosts = NULL; 51 static int debug = 0; 52 static int *ask = NULL; 53 static int *got = NULL; 54 55 static void usage(void) __attribute__((__noreturn__)); 56 static void load(const char *); 57 static void resolvone(int); 58 static void *resolvloop(void *); 59 static void run(int *); 60 61 static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; 62 63 static void 64 usage(void) 65 { 66 (void)fprintf(stderr, 67 "Usage: %s [-d] [-h <nhosts>] [-n <nthreads>] <file> ...\n", 68 getprogname()); 69 exit(1); 70 } 71 72 static void 73 load(const char *fname) 74 { 75 FILE *fp; 76 size_t linecap; 77 char *line; 78 79 if ((fp = fopen(fname, "r")) == NULL) 80 err(1, "Cannot open `%s'", fname); 81 line = NULL; 82 linecap = 0; 83 while (getline(&line, &linecap, fp) >= 0) { 84 char *ptr; 85 86 for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) 87 sl_add(hosts, strdup(ptr)); 88 } 89 90 (void)fclose(fp); 91 } 92 93 static void 94 resolvone(int n) 95 { 96 char buf[1024]; 97 pthread_t self = pthread_self(); 98 size_t i = (random() & 0x0fffffff) % hosts->sl_cur; 99 char *host = hosts->sl_str[i]; 100 struct addrinfo *res; 101 int error, len; 102 if (debug) { 103 len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n", 104 self, n, host, (int)i); 105 (void)write(STDOUT_FILENO, buf, len); 106 } 107 error = getaddrinfo(host, NULL, NULL, &res); 108 if (debug) { 109 len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", 110 self, host, error ? "not found" : "ok"); 111 (void)write(STDOUT_FILENO, buf, len); 112 } 113 pthread_mutex_lock(&stats); 114 ask[i]++; 115 got[i] += error == 0; 116 pthread_mutex_unlock(&stats); 117 if (error == 0) 118 freeaddrinfo(res); 119 } 120 121 static void * 122 resolvloop(void *p) 123 { 124 int *nhosts = (int *)p; 125 if (*nhosts == 0) 126 return NULL; 127 do 128 resolvone(*nhosts); 129 while (--(*nhosts)); 130 return NULL; 131 } 132 133 static void 134 run(int *nhosts) 135 { 136 pthread_t self = pthread_self(); 137 if (pthread_create(&self, NULL, resolvloop, nhosts) != 0) 138 err(1, "pthread_create"); 139 } 140 141 int 142 main(int argc, char *argv[]) 143 { 144 int nthreads = NTHREADS; 145 int nhosts = NHOSTS; 146 int i, c, done, *nleft; 147 hosts = sl_init(); 148 149 srandom(1234); 150 151 while ((c = getopt(argc, argv, "dh:n:")) != -1) 152 switch (c) { 153 case 'd': 154 debug++; 155 break; 156 case 'h': 157 nhosts = atoi(optarg); 158 break; 159 case 'n': 160 nthreads = atoi(optarg); 161 break; 162 default: 163 usage(); 164 } 165 166 for (i = optind; i < argc; i++) 167 load(argv[i]); 168 169 if (hosts->sl_cur == 0) 170 usage(); 171 172 if ((nleft = malloc(nthreads * sizeof(int))) == NULL) 173 err(1, "malloc"); 174 if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL) 175 err(1, "calloc"); 176 if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL) 177 err(1, "calloc"); 178 179 180 for (i = 0; i < nthreads; i++) { 181 nleft[i] = nhosts; 182 run(&nleft[i]); 183 } 184 185 for (done = 0; !done;) { 186 done = 1; 187 for (i = 0; i < nthreads; i++) { 188 if (nleft[i] != 0) { 189 done = 0; 190 break; 191 } 192 } 193 sleep(1); 194 } 195 c = 0; 196 for (i = 0; i < (int)hosts->sl_cur; i++) { 197 if (ask[i] != got[i] && got[i] != 0) { 198 warnx("Error: host %s ask %d got %d\n", 199 hosts->sl_str[i], ask[i], got[i]); 200 c++; 201 } 202 } 203 free(nleft); 204 free(ask); 205 free(got); 206 sl_free(hosts, 1); 207 return c; 208 } 209