aboutsummaryrefslogtreecommitdiff
path: root/networking/whois.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/whois.c')
-rw-r--r--networking/whois.c147
1 files changed, 131 insertions, 16 deletions
diff --git a/networking/whois.c b/networking/whois.c
index bf330334a..c9dfcf5ee 100644
--- a/networking/whois.c
+++ b/networking/whois.c
@@ -21,43 +21,158 @@
21//kbuild:lib-$(CONFIG_WHOIS) += whois.o 21//kbuild:lib-$(CONFIG_WHOIS) += whois.o
22 22
23//usage:#define whois_trivial_usage 23//usage:#define whois_trivial_usage
24//usage: "[-h SERVER] [-p PORT] NAME..." 24//usage: "[-i] [-h SERVER] [-p PORT] NAME..."
25//usage:#define whois_full_usage "\n\n" 25//usage:#define whois_full_usage "\n\n"
26//usage: "Query WHOIS info about NAME\n" 26//usage: "Query WHOIS info about NAME\n"
27//usage: "\n -i Show redirect results too"
27//usage: "\n -h,-p Server to query" 28//usage: "\n -h,-p Server to query"
28 29
29#include "libbb.h" 30#include "libbb.h"
30 31
31static void pipe_out(int fd) 32enum {
33 OPT_i = (1 << 0),
34};
35
36static char *query(const char *host, int port, const char *domain)
32{ 37{
38 int fd;
33 FILE *fp; 39 FILE *fp;
34 char buf[1024]; 40 bool success;
41 char *redir = NULL;
42 const char *pfx = "";
43 char linebuf[1024];
44 char *buf = NULL;
45 unsigned bufpos = 0;
35 46
47 again:
48 printf("[Querying %s:%d '%s%s']\n", host, port, pfx, domain);
49 fd = create_and_connect_stream_or_die(host, port);
50 success = 0;
51 fdprintf(fd, "%s%s\r\n", pfx, domain);
36 fp = xfdopen_for_read(fd); 52 fp = xfdopen_for_read(fd);
37 while (fgets(buf, sizeof(buf), fp)) {
38 char *p = strpbrk(buf, "\r\n");
39 if (p)
40 *p = '\0';
41 puts(buf);
42 }
43 53
54 while (fgets(linebuf, sizeof(linebuf), fp)) {
55 unsigned len = strcspn(linebuf, "\r\n");
56 linebuf[len++] = '\n';
57
58 buf = xrealloc(buf, bufpos + len + 1);
59 memcpy(buf + bufpos, linebuf, len);
60 bufpos += len;
61 buf[bufpos] = '\0';
62
63 if (!redir || !success) {
64 trim(linebuf);
65 str_tolower(linebuf);
66 if (!success) {
67 success = is_prefixed_with(linebuf, "domain:")
68 || is_prefixed_with(linebuf, "domain name:");
69 }
70 else if (!redir) {
71 char *p = is_prefixed_with(linebuf, "whois server:");
72 if (!p)
73 p = is_prefixed_with(linebuf, "whois:");
74 if (p)
75 redir = xstrdup(skip_whitespace(p));
76 }
77 }
78 }
44 fclose(fp); /* closes fd too */ 79 fclose(fp); /* closes fd too */
80 if (!success && !pfx[0]) {
81 /*
82 * Looking at /etc/jwhois.conf, some whois servers use
83 * "domain = DOMAIN", "DOMAIN ID <DOMAIN>"
84 * and "domain=DOMAIN_WITHOUT_LAST_COMPONENT"
85 * formats, but those are rare.
86 * (There are a few even more contrived ones.)
87 * We are trying only "domain DOMAIN", the typical one.
88 */
89 pfx = "domain ";
90 bufpos = 0;
91 goto again;
92 }
93
94 /* Success */
95 if (redir && strcmp(redir, host) == 0) {
96 /* Redirect to self does not count */
97 free(redir);
98 redir = NULL;
99 }
100 if (!redir || (option_mask32 & OPT_i)) {
101 /* Output saved text */
102 printf("[%s]\n%s", host, buf ? buf : "");
103 }
104 free(buf);
105 return redir;
106}
107
108static void recursive_query(const char *host, int port, const char *domain)
109{
110 char *free_me = NULL;
111 char *redir;
112 again:
113 redir = query(host, port, domain);
114 free(free_me);
115 if (redir) {
116 printf("[Redirected to %s]\n", redir);
117 host = free_me = redir;
118 port = 43;
119 goto again;
120 }
45} 121}
46 122
123/* One of "big" whois implementations has these options:
124 *
125 * $ whois --help
126 * jwhois version 4.0, Copyright (C) 1999-2007 Free Software Foundation, Inc.
127 * -v, --verbose verbose debug output
128 * -c FILE, --config=FILE use FILE as configuration file
129 * -h HOST, --host=HOST explicitly query HOST
130 * -n, --no-redirect disable content redirection
131 * -s, --no-whoisservers disable whois-servers.net service support
132 * -a, --raw disable reformatting of the query
133 * -i, --display-redirections display all redirects instead of hiding them
134 * -p PORT, --port=PORT use port number PORT (in conjunction with HOST)
135 * -r, --rwhois force an rwhois query to be made
136 * --rwhois-display=DISPLAY sets the display option in rwhois queries
137 * --rwhois-limit=LIMIT sets the maximum number of matches to return
138 *
139 * Example of its output:
140 * $ whois cnn.com
141 * [Querying whois.verisign-grs.com]
142 * [Redirected to whois.corporatedomains.com]
143 * [Querying whois.corporatedomains.com]
144 * [whois.corporatedomains.com]
145 * ...text of the reply...
146 *
147 * With -i, reply from each server is printed, after all redirects are done:
148 * [Querying whois.verisign-grs.com]
149 * [Redirected to whois.corporatedomains.com]
150 * [Querying whois.corporatedomains.com]
151 * [whois.verisign-grs.com]
152 * ...text of the reply...
153 * [whois.corporatedomains.com]
154 * ...text of the reply...
155 *
156 * With -a, no "DOMAIN" -> "domain DOMAIN" transformation is attempted.
157
158 * With -n, the first reply is shown, redirects are not followed:
159 * [Querying whois.verisign-grs.com]
160 * [whois.verisign-grs.com]
161 * ...text of the reply...
162 */
163
47int whois_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 164int whois_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
48int whois_main(int argc UNUSED_PARAM, char **argv) 165int whois_main(int argc UNUSED_PARAM, char **argv)
49{ 166{
50 int port = 43; 167 int port = 43;
51 const char *host = "whois-servers.net"; 168 const char *host = "whois.iana.org";
52
53 opt_complementary = "-1:p+";
54 getopt32(argv, "h:p:", &host, &port);
55 169
170 opt_complementary = "-1";
171 getopt32(argv, "ih:p:+", &host, &port);
56 argv += optind; 172 argv += optind;
173
57 do { 174 do {
58 int fd = create_and_connect_stream_or_die(host, port); 175 recursive_query(host, port, *argv);
59 fdprintf(fd, "%s\r\n", *argv);
60 pipe_out(fd);
61 } 176 }
62 while (*++argv); 177 while (*++argv);
63 178