1 /* 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static const char copyright[] = 36 "@(#) Copyright (c) 1980, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)whois.c 8.1 (Berkeley) 6/6/93"; 43 #endif 44 static const char rcsid[] = 45 "$FreeBSD$"; 46 #endif /* not lint */ 47 48 #include <sys/types.h> 49 #include <sys/socket.h> 50 #include <netinet/in.h> 51 #include <arpa/inet.h> 52 #include <err.h> 53 #include <netdb.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <string.h> 57 #include <sysexits.h> 58 #include <unistd.h> 59 60 #define NICHOST "whois.crsnic.net" 61 #define INICHOST "whois.networksolutions.com" 62 #define DNICHOST "whois.nic.mil" 63 #define GNICHOST "whois.nic.gov" 64 #define ANICHOST "whois.arin.net" 65 #define RNICHOST "whois.ripe.net" 66 #define PNICHOST "whois.apnic.net" 67 #define RUNICHOST "whois.ripn.net" 68 #define MNICHOST "whois.ra.net" 69 #define QNICHOST_TAIL ".whois-servers.net" 70 #define SNICHOST "whois.6bone.net" 71 #define WHOIS_PORT 43 72 73 #define WHOIS_RECURSE 0x01 74 #define WHOIS_INIC_FALLBACK 0x02 75 #define WHOIS_QUICK 0x04 76 77 static void usage __P((void)); 78 static void whois __P((char *, struct sockaddr_in *, int)); 79 80 int 81 main(argc, argv) 82 int argc; 83 char **argv; 84 { 85 int ch, i, j; 86 int use_qnichost, flags; 87 char *host; 88 char *qnichost; 89 struct servent *sp; 90 struct hostent *hp; 91 struct sockaddr_in sin; 92 93 #ifdef SOCKS 94 SOCKSinit(argv[0]); 95 #endif 96 97 host = NULL; 98 qnichost = NULL; 99 flags = 0; 100 use_qnichost = 0; 101 while ((ch = getopt(argc, argv, "adgh:impQrR6")) != -1) { 102 switch((char)ch) { 103 case 'a': 104 host = ANICHOST; 105 break; 106 case 'd': 107 host = DNICHOST; 108 break; 109 case 'g': 110 host = GNICHOST; 111 break; 112 case 'h': 113 host = optarg; 114 break; 115 case 'i': 116 host = INICHOST; 117 break; 118 case 'm': 119 host = MNICHOST; 120 break; 121 case 'p': 122 host = PNICHOST; 123 break; 124 case 'Q': 125 flags |= WHOIS_QUICK; 126 break; 127 case 'r': 128 host = RNICHOST; 129 break; 130 case 'R': 131 host = RUNICHOST; 132 break; 133 case '6': 134 host = SNICHOST; 135 break; 136 case '?': 137 default: 138 usage(); 139 } 140 } 141 argc -= optind; 142 argv += optind; 143 144 if (!argc) { 145 usage(); 146 } 147 148 memset(&sin, 0, sizeof(sin)); 149 sin.sin_len = sizeof(sin); 150 sin.sin_family = AF_INET; 151 sp = getservbyname("whois", "tcp"); 152 if (sp == NULL) { 153 sin.sin_port = htons(WHOIS_PORT); 154 } else { 155 sin.sin_port = sp->s_port; 156 } 157 158 /* 159 * If no nic host is specified, use whois-servers.net 160 * if there is a '.' in the name, else fall back to NICHOST. 161 */ 162 if (host == NULL) { 163 use_qnichost = 1; 164 host = NICHOST; 165 if (!(flags & WHOIS_QUICK)) { 166 flags |= WHOIS_INIC_FALLBACK | WHOIS_RECURSE; 167 } 168 } 169 while (argc--) { 170 if (use_qnichost) { 171 if (qnichost) { 172 free(qnichost); 173 qnichost = NULL; 174 } 175 for (i = j = 0; (*argv)[i]; i++) { 176 if ((*argv)[i] == '.') { 177 j = i; 178 } 179 } 180 if (j != 0) { 181 qnichost = (char *) calloc(i - j + 1 + 182 strlen(QNICHOST_TAIL), sizeof(char)); 183 if (!qnichost) { 184 err(1, "calloc"); 185 } 186 strcpy(qnichost, *argv + j + 1); 187 strcat(qnichost, QNICHOST_TAIL); 188 189 if (inet_aton(qnichost, &sin.sin_addr) == 0) { 190 hp = gethostbyname2(qnichost, AF_INET); 191 if (hp == NULL) { 192 free(qnichost); 193 qnichost = NULL; 194 } else { 195 sin.sin_addr = *(struct in_addr *)hp->h_addr_list[0]; 196 } 197 } 198 } 199 } 200 if (!qnichost && inet_aton(host, &sin.sin_addr) == 0) { 201 hp = gethostbyname2(host, AF_INET); 202 if (hp == NULL) { 203 errx(EX_NOHOST, "%s: %s", host, 204 hstrerror(h_errno)); 205 } 206 host = hp->h_name; 207 sin.sin_addr = *(struct in_addr *)hp->h_addr_list[0]; 208 } 209 210 whois(*argv++, &sin, flags); 211 } 212 exit(0); 213 } 214 215 static void 216 whois(name, sinp, flags) 217 char *name; 218 struct sockaddr_in *sinp; 219 int flags; 220 { 221 FILE *sfi, *sfo; 222 char *buf, *p, *nhost; 223 size_t len; 224 int s, nomatch; 225 226 s = socket(PF_INET, SOCK_STREAM, 0); 227 if (s < 0) { 228 err(EX_OSERR, "socket"); 229 } 230 231 if (connect(s, (struct sockaddr *)sinp, sizeof(*sinp)) < 0) { 232 err(EX_OSERR, "connect"); 233 } 234 235 sfi = fdopen(s, "r"); 236 sfo = fdopen(s, "w"); 237 if (sfi == NULL || sfo == NULL) { 238 err(EX_OSERR, "fdopen"); 239 } 240 (void)fprintf(sfo, "%s\r\n", name); 241 (void)fflush(sfo); 242 nhost = NULL; 243 nomatch = 0; 244 while ((buf = fgetln(sfi, &len))) { 245 if (buf[len - 2] == '\r') { 246 buf[len - 2] = '\0'; 247 } else { 248 buf[len - 1] = '\0'; 249 } 250 251 if ((flags & WHOIS_RECURSE) && !nhost && 252 (p = strstr(buf, "Whois Server: "))) { 253 p += sizeof("Whois Server: ") - 1; 254 if ((len = strcspn(p, " \t\n\r"))) { 255 if ((nhost = malloc(len + 1)) == NULL) { 256 err(1, "malloc"); 257 } 258 memcpy(nhost, p, len); 259 nhost[len] = '\0'; 260 } 261 } 262 if ((flags & WHOIS_INIC_FALLBACK) && !nhost && !nomatch && 263 (p = strstr(buf, "No match for \""))) { 264 p += sizeof("No match for \"") - 1; 265 if ((len = strcspn(p, "\"")) && 266 strncasecmp(name, p, len) == 0 && 267 name[len] == '\0' && 268 strchr(name, '.') == NULL) { 269 nomatch = 1; 270 } 271 } 272 (void)puts(buf); 273 } 274 275 /* Do second lookup as needed */ 276 if (nomatch && !nhost) { 277 (void)printf("Looking up %s at %s.\n\n", name, INICHOST); 278 nhost = INICHOST; 279 } 280 if (nhost) { 281 if (inet_aton(nhost, &sinp->sin_addr) == 0) { 282 struct hostent *hp = gethostbyname2(nhost, AF_INET); 283 if (hp == NULL) { 284 return; 285 } 286 sinp->sin_addr = *(struct in_addr *)hp->h_addr_list[0]; 287 } 288 if (!nomatch) { 289 free(nhost); 290 } 291 whois(name, sinp, 0); 292 } 293 } 294 295 static void 296 usage() 297 { 298 (void)fprintf(stderr, 299 "usage: whois [-adgimpQrR6] [-h hostname] name ...\n"); 300 exit(EX_USAGE); 301 } 302