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