aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-07-06 15:45:41 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-07-06 15:45:41 +0200
commit1035c92e2d1c017eab7cb10badb7e3b407aeba2d (patch)
treee4e3dc6b3c136196aad1d27db28b846b977b5037
parentf4f8fe841cf2df761eaade204a13e6fde6639666 (diff)
downloadbusybox-w32-1035c92e2d1c017eab7cb10badb7e3b407aeba2d.tar.gz
busybox-w32-1035c92e2d1c017eab7cb10badb7e3b407aeba2d.tar.bz2
busybox-w32-1035c92e2d1c017eab7cb10badb7e3b407aeba2d.zip
whois: make it actually work
It was doing way too simplistic work of just querying the server, no redirects, no query massaging. This required user to know a lot about whois, and enter at least three queries for each host to get meaningful information. function old new delta whois_main 209 646 +437 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/whois.c137
1 files changed, 124 insertions, 13 deletions
diff --git a/networking/whois.c b/networking/whois.c
index bf330334a..5ef83672d 100644
--- a/networking/whois.c
+++ b/networking/whois.c
@@ -28,36 +28,147 @@
28 28
29#include "libbb.h" 29#include "libbb.h"
30 30
31static void pipe_out(int fd) 31static char *query(const char *host, int port, const char *domain)
32{ 32{
33 int fd;
33 FILE *fp; 34 FILE *fp;
34 char buf[1024]; 35 bool success;
36 char *redir = NULL;
37 const char *pfx = "";
38 char linebuf[1024];
39 char *buf = NULL;
40 unsigned bufpos = 0;
35 41
42 again:
43 printf("[Querying %s:%d '%s%s']\n", host, port, pfx, domain);
44 fd = create_and_connect_stream_or_die(host, port);
45 success = 0;
46 fdprintf(fd, "%s%s\r\n", pfx, domain);
36 fp = xfdopen_for_read(fd); 47 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 48
49 while (fgets(linebuf, sizeof(linebuf), fp)) {
50 unsigned len = strcspn(linebuf, "\r\n");
51 linebuf[len++] = '\n';
52
53 buf = xrealloc(buf, bufpos + len + 1);
54 memcpy(buf + bufpos, linebuf, len);
55 bufpos += len;
56
57 if (!redir || !success) {
58 trim(linebuf);
59 str_tolower(linebuf);
60 if (!success) {
61 success = is_prefixed_with(linebuf, "domain:")
62 || is_prefixed_with(linebuf, "domain name:");
63 }
64 else if (!redir) {
65 char *p = is_prefixed_with(linebuf, "whois server:");
66 if (!p)
67 p = is_prefixed_with(linebuf, "whois:");
68 if (p)
69 redir = xstrdup(skip_whitespace(p));
70 }
71 }
72 }
44 fclose(fp); /* closes fd too */ 73 fclose(fp); /* closes fd too */
74 if (!success && !pfx[0]) {
75 /*
76 * Looking at jwhois.conf, some whois servers use
77 * "domain = DOMAIN", "DOMAIN ID <DOMAIN>"
78 * and "domain=DOMAIN_WITHOUT_LAST_COMPONENT"
79 * formats, but those are rare.
80 * (There are a few even more contrived ones.)
81 * We are trying only "domain DOMAIN", the typical one.
82 */
83 pfx = "domain ";
84 bufpos = 0;
85 goto again;
86 }
87
88 /* Success */
89 if (redir && strcmp(redir, host) == 0) {
90 /* Redirect to self does not count */
91 free(redir);
92 redir = NULL;
93 }
94 if (!redir) {
95 /* Output saved text */
96 printf("[%s]\n", host);
97 buf[bufpos] = '\0';
98 fputs(buf, stdout);
99 }
100 free(buf);
101 return redir;
45} 102}
46 103
104static void recursive_query(const char *host, int port, const char *domain)
105{
106 char *free_me = NULL;
107 char *redir;
108 again:
109 redir = query(host, port, domain);
110 free(free_me);
111 if (redir) {
112 printf("[Redirected to %s]\n", redir);
113 host = free_me = redir;
114 port = 43;
115 goto again;
116 }
117}
118
119/* One of "big" whois implementations has these options:
120 *
121 * $ whois --help
122 * jwhois version 4.0, Copyright (C) 1999-2007 Free Software Foundation, Inc.
123 * -v, --verbose verbose debug output
124 * -c FILE, --config=FILE use FILE as configuration file
125 * -h HOST, --host=HOST explicitly query HOST
126 * -n, --no-redirect disable content redirection
127 * -s, --no-whoisservers disable whois-servers.net service support
128 * -a, --raw disable reformatting of the query
129 * -i, --display-redirections display all redirects instead of hiding them
130 * -p PORT, --port=PORT use port number PORT (in conjunction with HOST)
131 * -r, --rwhois force an rwhois query to be made
132 * --rwhois-display=DISPLAY sets the display option in rwhois queries
133 * --rwhois-limit=LIMIT sets the maximum number of matches to return
134 *
135 * Example of its output:
136 * $ whois cnn.com
137 * [Querying whois.verisign-grs.com]
138 * [Redirected to whois.corporatedomains.com]
139 * [Querying whois.corporatedomains.com]
140 * [whois.corporatedomains.com]
141 * ...text of the reply...
142 *
143 * With -i, reply from each server is printed, after all redirects are done:
144 * [Querying whois.verisign-grs.com]
145 * [Redirected to whois.corporatedomains.com]
146 * [Querying whois.corporatedomains.com]
147 * [whois.verisign-grs.com]
148 * ...text of the reply...
149 * [whois.corporatedomains.com]
150 * ...text of the reply...
151 *
152 * With -a, no "DOMAIN" -> "domain DOMAIN" transformation is attempted.
153
154 * With -n, the first reply is shown, redirects are not followed:
155 * [Querying whois.verisign-grs.com]
156 * [whois.verisign-grs.com]
157 * ...text of the reply...
158 */
159
47int whois_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 160int whois_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
48int whois_main(int argc UNUSED_PARAM, char **argv) 161int whois_main(int argc UNUSED_PARAM, char **argv)
49{ 162{
50 int port = 43; 163 int port = 43;
51 const char *host = "whois-servers.net"; 164 const char *host = "whois.iana.org";
52 165
53 opt_complementary = "-1:p+"; 166 opt_complementary = "-1:p+";
54 getopt32(argv, "h:p:", &host, &port); 167 getopt32(argv, "h:p:", &host, &port);
55
56 argv += optind; 168 argv += optind;
169
57 do { 170 do {
58 int fd = create_and_connect_stream_or_die(host, port); 171 recursive_query(host, port, *argv);
59 fdprintf(fd, "%s\r\n", *argv);
60 pipe_out(fd);
61 } 172 }
62 while (*++argv); 173 while (*++argv);
63 174