PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/src/netbsd/src/usr.bin/whois/whois.c

https://bitbucket.org/killerpenguinassassins/open_distrib_devel
C | 329 lines | 264 code | 27 blank | 38 comment | 76 complexity | 8317253c320f98227ee7ec33e8ef0f99 MD5 | raw file
Possible License(s): CC0-1.0, MIT, LGPL-2.0, LGPL-3.0, WTFPL, GPL-2.0, BSD-2-Clause, AGPL-3.0, CC-BY-SA-3.0, MPL-2.0, JSON, BSD-3-Clause-No-Nuclear-License-2014, LGPL-2.1, CPL-1.0, AGPL-1.0, 0BSD, ISC, Apache-2.0, GPL-3.0, IPL-1.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /* $NetBSD: whois.c,v 1.35 2011/08/17 13:57:12 christos Exp $ */
  2. /* $OpenBSD: whois.c,v 1.28 2003/09/18 22:16:15 fgsch Exp $ */
  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. Neither the name of the University nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. */
  31. #include <sys/cdefs.h>
  32. #ifndef lint
  33. __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
  34. The Regents of the University of California. All rights reserved.");
  35. #endif /* not lint */
  36. #ifndef lint
  37. #if 0
  38. static const char sccsid[] = "@(#)whois.c 8.1 (Berkeley) 6/6/93";
  39. #else
  40. __RCSID("$NetBSD: whois.c,v 1.35 2011/08/17 13:57:12 christos Exp $");
  41. #endif
  42. #endif /* not lint */
  43. #include <sys/types.h>
  44. #include <sys/socket.h>
  45. #include <netinet/in.h>
  46. #include <arpa/inet.h>
  47. #include <netdb.h>
  48. #include <ctype.h>
  49. #include <err.h>
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include <unistd.h>
  54. #include <errno.h>
  55. #define ANICHOST "whois.arin.net"
  56. #define BNICHOST "whois.registro.br"
  57. #define CNICHOST "whois.corenic.net"
  58. #define DNICHOST "whois.nic.mil"
  59. #define FNICHOST "whois.afrinic.net"
  60. #define GNICHOST "whois.nic.gov"
  61. #define INICHOST "whois.networksolutions.com"
  62. #define LNICHOST "whois.lacnic.net"
  63. #define MNICHOST "whois.ra.net"
  64. #define NICHOST "whois.crsnic.net"
  65. #define PNICHOST "whois.apnic.net"
  66. #define QNICHOST_TAIL ".whois-servers.net"
  67. #define RNICHOST "whois.ripe.net"
  68. #define RUNICHOST "whois.ripn.net"
  69. #define SNICHOST "whois.6bone.net"
  70. #define WHOIS_PORT "whois"
  71. #define WHOIS_SERVER_ID "Whois Server:"
  72. #define WHOIS_RECURSE 0x01
  73. #define WHOIS_QUICK 0x02
  74. static const char *port_whois = WHOIS_PORT;
  75. static const char *ip_whois[] =
  76. { LNICHOST, RNICHOST, PNICHOST, FNICHOST, BNICHOST, NULL };
  77. static void usage(void) __dead;
  78. static int whois(const char *, const char *, const char *, int);
  79. static const char *choose_server(const char *, const char *);
  80. int
  81. main(int argc, char *argv[])
  82. {
  83. int ch, flags, rval;
  84. const char *host, *name, *country;
  85. #ifdef SOCKS
  86. SOCKSinit(argv[0]);
  87. #endif
  88. country = host = NULL;
  89. flags = rval = 0;
  90. while ((ch = getopt(argc, argv, "6Aac:dfgh:ilmp:qQRr")) != -1)
  91. switch(ch) {
  92. case 'a':
  93. host = ANICHOST;
  94. break;
  95. case 'A':
  96. host = PNICHOST;
  97. break;
  98. case 'c':
  99. country = optarg;
  100. break;
  101. case 'd':
  102. host = DNICHOST;
  103. break;
  104. case 'f':
  105. host = FNICHOST;
  106. break;
  107. case 'g':
  108. host = GNICHOST;
  109. break;
  110. case 'h':
  111. host = optarg;
  112. break;
  113. case 'i':
  114. host = INICHOST;
  115. break;
  116. case 'l':
  117. host = LNICHOST;
  118. break;
  119. case 'm':
  120. host = MNICHOST;
  121. break;
  122. case 'p':
  123. port_whois = optarg;
  124. break;
  125. case 'q':
  126. /* deprecated, now the default */
  127. break;
  128. case 'Q':
  129. flags |= WHOIS_QUICK;
  130. break;
  131. case 'r':
  132. host = RNICHOST;
  133. break;
  134. case 'R':
  135. host = RUNICHOST;
  136. break;
  137. case '6':
  138. host = SNICHOST;
  139. break;
  140. default:
  141. usage();
  142. }
  143. argc -= optind;
  144. argv += optind;
  145. if (!argc || (country != NULL && host != NULL))
  146. usage();
  147. if (host == NULL && country == NULL && !(flags & WHOIS_QUICK))
  148. flags |= WHOIS_RECURSE;
  149. for (name = *argv; (name = *argv) != NULL; argv++)
  150. rval += whois(name, host ? host : choose_server(name, country),
  151. port_whois, flags);
  152. return rval;
  153. }
  154. static int
  155. whois(const char *query, const char *server, const char *port, int flags)
  156. {
  157. FILE *sfi, *sfo;
  158. char *buf, *p, *nhost, *nbuf = NULL;
  159. size_t len;
  160. int i, s, error;
  161. const char *reason = NULL, *fmt;
  162. struct addrinfo hints, *res, *ai;
  163. (void)memset(&hints, 0, sizeof(hints));
  164. hints.ai_flags = 0;
  165. hints.ai_family = AF_UNSPEC;
  166. hints.ai_socktype = SOCK_STREAM;
  167. error = getaddrinfo(server, port, &hints, &res);
  168. if (error) {
  169. warnx("%s: %s", server, gai_strerror(error));
  170. return (1);
  171. }
  172. for (s = -1, ai = res; ai != NULL; ai = ai->ai_next) {
  173. s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  174. if (s < 0) {
  175. error = errno;
  176. reason = "socket";
  177. continue;
  178. }
  179. if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
  180. error = errno;
  181. reason = "connect";
  182. close(s);
  183. s = -1;
  184. continue;
  185. }
  186. break; /*okay*/
  187. }
  188. if (s < 0) {
  189. if (reason) {
  190. errno = error;
  191. warn("%s: %s", server, reason);
  192. } else
  193. warnx("Unknown error in connection attempt");
  194. freeaddrinfo(res);
  195. return (1);
  196. }
  197. if (strcmp(server, "whois.denic.de") == 0 ||
  198. strcmp(server, "de.whois-servers.net") == 0)
  199. fmt = "-T dn,ace -C ISO-8859-1";
  200. else
  201. fmt = "";
  202. sfi = fdopen(s, "r");
  203. sfo = fdopen(s, "w");
  204. if (sfi == NULL || sfo == NULL)
  205. err(1, "fdopen");
  206. (void)fprintf(sfo, "%s%s\r\n", fmt, query);
  207. (void)fflush(sfo);
  208. nhost = NULL;
  209. while ((buf = fgetln(sfi, &len)) != NULL) {
  210. p = buf + len - 1;
  211. if (isspace((unsigned char)*p)) {
  212. do
  213. *p = '\0';
  214. while (p > buf && isspace((unsigned char)*--p));
  215. } else {
  216. if ((nbuf = malloc(len + 1)) == NULL)
  217. err(1, "malloc");
  218. (void)memcpy(nbuf, buf, len);
  219. nbuf[len] = '\0';
  220. buf = nbuf;
  221. }
  222. (void)puts(buf);
  223. if (nhost != NULL || !(flags & WHOIS_RECURSE))
  224. continue;
  225. if ((p = strstr(buf, WHOIS_SERVER_ID))) {
  226. p += sizeof(WHOIS_SERVER_ID) - 1;
  227. while (isblank((unsigned char)*p))
  228. p++;
  229. if ((len = strcspn(p, " \t\n\r"))) {
  230. if ((nhost = malloc(len + 1)) == NULL)
  231. err(1, "malloc");
  232. (void)memcpy(nhost, p, len);
  233. nhost[len] = '\0';
  234. }
  235. } else if (strcmp(server, ANICHOST) == 0) {
  236. for (p = buf; *p != '\0'; p++)
  237. *p = tolower((unsigned char)*p);
  238. for (i = 0; ip_whois[i] != NULL; i++) {
  239. if (strstr(buf, ip_whois[i]) != NULL) {
  240. nhost = strdup(ip_whois[i]);
  241. if (nhost == NULL)
  242. err(1, "strdup");
  243. break;
  244. }
  245. }
  246. }
  247. }
  248. if (nbuf != NULL)
  249. free(nbuf);
  250. if (nhost != NULL) {
  251. error = whois(query, nhost, port, 0);
  252. free(nhost);
  253. }
  254. freeaddrinfo(res);
  255. (void)fclose(sfi);
  256. (void)fclose(sfo);
  257. return (error);
  258. }
  259. /*
  260. * If no country is specified determine the top level domain from the query.
  261. * If the TLD is a number, query ARIN, otherwise, use TLD.whois-server.net.
  262. * If the domain does not contain '.', check to see if it is an NSI handle
  263. * (starts with '!') or a CORE handle (COCO-[0-9]+ or COHO-[0-9]+).
  264. * Fall back to NICHOST for the non-handle case.
  265. */
  266. static const char *
  267. choose_server(const char *name, const char *country)
  268. {
  269. static char *server;
  270. char *nserver;
  271. const char *qhead;
  272. char *ep;
  273. size_t len;
  274. if (country != NULL)
  275. qhead = country;
  276. else if ((qhead = strrchr(name, '.')) == NULL) {
  277. if (*name == '!')
  278. return (INICHOST);
  279. else if ((strncasecmp(name, "COCO-", 5) == 0 ||
  280. strncasecmp(name, "COHO-", 5) == 0) &&
  281. strtol(name + 5, &ep, 10) > 0 && *ep == '\0')
  282. return (CNICHOST);
  283. else
  284. return (NICHOST);
  285. } else if (isdigit((unsigned char)*(++qhead)))
  286. return (ANICHOST);
  287. len = strlen(qhead) + sizeof(QNICHOST_TAIL);
  288. if ((nserver = realloc(server, len)) == NULL)
  289. err(1, "realloc");
  290. server = nserver;
  291. (void)strlcpy(server, qhead, len);
  292. (void)strlcat(server, QNICHOST_TAIL, len);
  293. return (server);
  294. }
  295. static void
  296. usage(void)
  297. {
  298. (void)fprintf(stderr,
  299. "usage: %s [-6AadgilmQRr] [-c country-code | -h hostname] "
  300. "[-p port] name ...\n", getprogname());
  301. exit(1);
  302. }