summaryrefslogtreecommitdiff
path: root/whois.c
diff options
context:
space:
mode:
Diffstat (limited to 'whois.c')
-rw-r--r--whois.c417
1 files changed, 244 insertions, 173 deletions
diff --git a/whois.c b/whois.c
index c6f36a5..0be8d30 100644
--- a/whois.c
+++ b/whois.c
@@ -40,6 +40,12 @@
#include "whois.h"
#include "utils.h"
+#ifdef HAVE_ICONV
+#include "simple_recode.h"
+#else
+#define recode_fputs(a, b) fputs(a, b)
+#endif
+
/* hack */
#define malloc(s) NOFAIL(malloc(s))
#define realloc(p, s) NOFAIL(realloc(p, s))
@@ -48,12 +54,12 @@
int sockfd, verb = 0;
#ifdef ALWAYS_HIDE_DISCL
-int hide_discl = HIDE_UNSTARTED;
+int hide_discl = HIDE_NOT_STARTED;
#else
int hide_discl = HIDE_DISABLED;
#endif
-const char *client_tag = (char *)IDSTRING;
+const char *client_tag = IDSTRING;
#ifdef HAVE_GETOPT_LONG
static const struct option longopts[] = {
@@ -72,9 +78,9 @@ extern int optind;
int main(int argc, char *argv[])
{
- int ch, nopar = 0;
+ int ch, nopar = 0, fstringlen = 64;
const char *server = NULL, *port = NULL;
- char *p, *qstring, fstring[64] = "\0";
+ char *qstring, *fstring;
#ifdef ENABLE_NLS
setlocale(LC_ALL, "");
@@ -82,6 +88,9 @@ int main(int argc, char *argv[])
textdomain(NLS_CAT_NAME);
#endif
+ fstring = malloc(fstringlen + 1);
+ *fstring = '\0';
+
/* prepend options from environment */
argv = merge_args(getenv("WHOIS_OPTIONS"), argv, &argc);
@@ -89,13 +98,20 @@ int main(int argc, char *argv[])
"abBcdFg:Gh:Hi:KlLmMp:q:rRs:St:T:v:V:x", longopts, 0)) > 0) {
/* RIPE flags */
if (strchr(ripeflags, ch)) {
- for (p = fstring; *p; p++);
- sprintf(p--, "-%c ", ch);
+ if (strlen(fstring) + 3 > fstringlen) {
+ fstringlen += 3;
+ fstring = realloc(fstring, fstringlen + 1);
+ }
+ sprintf(fstring + strlen(fstring), "-%c ", ch);
continue;
}
if (strchr(ripeflagsp, ch)) {
- for (p = fstring; *p; p++);
- snprintf(p--, sizeof(fstring), "-%c %s ", ch, optarg);
+ int flaglen = 3 + strlen(optarg) + 1;
+ if (strlen(fstring) + flaglen > fstringlen) {
+ fstringlen += flaglen;
+ fstring = realloc(fstring, fstringlen + 1);
+ }
+ sprintf(fstring + strlen(fstring), "-%c %s ", ch, optarg);
if (ch == 't' || ch == 'v' || ch == 'q')
nopar = 1;
continue;
@@ -108,7 +124,7 @@ int main(int argc, char *argv[])
case 'V':
client_tag = optarg;
case 'H':
- hide_discl = HIDE_UNSTARTED; /* enable disclaimers hiding */
+ hide_discl = HIDE_NOT_STARTED; /* enable disclaimers hiding */
break;
case 'p':
port = strdup(optarg);
@@ -131,16 +147,17 @@ int main(int argc, char *argv[])
usage();
/* On some systems realloc only works on non-NULL buffers */
+ /* I wish I could remember which ones they are... */
qstring = malloc(64);
*qstring = '\0';
/* parse other parameters, if any */
if (!nopar) {
- int qslen = 0;
+ int qstringlen = 0;
while (1) {
- qslen += strlen(*argv) + 1 + 1;
- qstring = realloc(qstring, qslen);
+ qstringlen += strlen(*argv) + 1;
+ qstring = realloc(qstring, qstringlen + 1);
strcat(qstring, *argv++);
if (argc == 1)
break;
@@ -154,12 +171,18 @@ int main(int argc, char *argv[])
signal(SIGALRM, alarm_handler);
if (getenv("WHOIS_HIDE"))
- hide_discl = HIDE_UNSTARTED;
+ hide_discl = HIDE_NOT_STARTED;
/* -v or -t has been used */
if (!server && !*qstring)
server = strdup("whois.ripe.net");
+ if (*qstring) {
+ char *tmp = normalize_domain(qstring);
+ free(qstring);
+ qstring = tmp;
+ }
+
#ifdef CONFIG_FILE
if (!server) {
server = match_config_file(qstring);
@@ -168,29 +191,24 @@ int main(int argc, char *argv[])
}
#endif
- if (!server) {
- char *tmp;
-
- tmp = normalize_domain(qstring);
- free(qstring);
- qstring = tmp;
- server = whichwhois(qstring);
- }
+ if (!server)
+ server = guess_server(qstring);
handle_query(server, port, qstring, fstring);
exit(0);
}
-/* server may be a server name from the command line, a server name got
- * from whichwhois or an encoded command/message from whichwhois.
- * server and port are allocated with malloc.
+/*
+ * Server may be a server name from the command line, a server name got
+ * from guess_server or an encoded command/message from guess_server.
+ * This function has multiple memory leaks.
*/
-const char *handle_query(const char *hserver, const char *hport,
- const char *qstring, const char *fstring)
+void handle_query(const char *hserver, const char *hport,
+ const char *query, const char *flags)
{
const char *server = NULL, *port = NULL;
- char *p;
+ char *p, *query_string;
if (hport) {
server = strdup(hserver);
@@ -200,6 +218,7 @@ const char *handle_query(const char *hserver, const char *hport,
else
split_server_port(hserver, &server, &port);
+ retry:
switch (server[0]) {
case 0:
if (!(server = getenv("WHOIS_SERVER")))
@@ -209,78 +228,77 @@ const char *handle_query(const char *hserver, const char *hport,
puts(_("This TLD has no whois server, but you can access the "
"whois database at"));
puts(server + 1);
- return NULL;
+ return;
case 3:
puts(_("This TLD has no whois server."));
- return NULL;
+ return;
case 5:
puts(_("No whois server is known for this kind of object."));
- return NULL;
+ return;
case 6:
puts(_("Unknown AS number or IP network. Please upgrade this program."));
- return NULL;
+ return;
case 4:
if (verb)
printf(_("Using server %s.\n"), server + 1);
sockfd = openconn(server + 1, NULL);
- server = query_crsnic(sockfd, qstring);
+ server = query_crsnic(sockfd, query);
break;
case 7:
if (verb)
printf(_("Using server %s.\n"),
"whois.publicinterestregistry.net");
sockfd = openconn("whois.publicinterestregistry.net", NULL);
- server = query_pir(sockfd, qstring);
+ server = query_pir(sockfd, query);
break;
case 8:
if (verb)
printf(_("Using server %s.\n"), "whois.afilias-grs.info");
sockfd = openconn("whois.afilias-grs.info", NULL);
- server = query_afilias(sockfd, qstring);
+ server = query_afilias(sockfd, query);
break;
case 0x0A:
- p = convert_6to4(qstring);
- /* XXX should fail if p = 0.0.0.0 */
+ p = convert_6to4(query);
printf(_("\nQuerying for the IPv4 endpoint %s of a 6to4 IPv6 address.\n\n"), p);
- server = whichwhois(p);
- /* XXX should fail if server[0] < ' ' */
- qstring = p; /* XXX leak */
- break;
+ server = guess_server(p);
+ query = p;
+ goto retry;
case 0x0B:
- p = convert_teredo(qstring);
+ p = convert_teredo(query);
printf(_("\nQuerying for the IPv4 endpoint %s of a Teredo IPv6 address.\n\n"), p);
- server = whichwhois(p);
- qstring = p ;
- break;
+ server = guess_server(p);
+ query = p;
+ goto retry;
case 0x0C:
- p = convert_inaddr(qstring);
- server = whichwhois(p);
- break;
+ p = convert_inaddr(query);
+ server = guess_server(p);
+ free(p);
+ goto retry;
default:
break;
}
if (!server)
- return NULL;
+ return;
- p = queryformat(server, fstring, qstring);
+ query_string = queryformat(server, flags, query);
if (verb) {
printf(_("Using server %s.\n"), server);
- printf(_("Query string: \"%s\"\n\n"), p);
+ printf(_("Query string: \"%s\"\n\n"), query_string);
}
sockfd = openconn(server, port);
- strcat(p, "\r\n");
- server = do_query(sockfd, p);
+ server = do_query(sockfd, query_string);
+ free(query_string);
/* recursion is fun */
if (server) {
printf(_("\n\nFound a referral to %s.\n\n"), server);
- handle_query(server, NULL, qstring, fstring);
+ handle_query(server, NULL, query, flags);
}
- return NULL;
+ return;
}
#ifdef CONFIG_FILE
@@ -304,9 +322,8 @@ const char *match_config_file(const char *s)
regex_t re;
#endif
- for (p = buf; *p; p++)
- if (*p == '\n')
- *p = '\0';
+ if ((p = strpbrk(buf, "\r\n")))
+ *p = '\0';
p = buf;
while (*p == ' ' || *p == '\t') /* eat leading blanks */
@@ -359,7 +376,7 @@ const char *match_config_file(const char *s)
/* Parses an user-supplied string and tries to guess the right whois server.
* Returns a statically allocated buffer.
*/
-const char *whichwhois(const char *s)
+const char *guess_server(const char *s)
{
unsigned long ip, as32;
unsigned int i;
@@ -463,6 +480,11 @@ const char *whereas(const unsigned long asn)
return "\x06";
}
+/*
+ * Construct the query string.
+ * Determines the server character set as a side effect.
+ * Returns a malloc'ed string which needs to be freed by the caller.
+ */
char *queryformat(const char *server, const char *flags, const char *query)
{
char *buf, *p;
@@ -471,59 +493,75 @@ char *queryformat(const char *server, const char *flags, const char *query)
/* 64 bytes reserved for server-specific flags added later */
buf = malloc(strlen(flags) + strlen(query) + strlen(client_tag) + 64);
*buf = '\0';
+
for (i = 0; ripe_servers[i]; i++)
if (streq(server, ripe_servers[i])) {
- strcat(buf, "-V ");
- strcat(buf, client_tag);
- strcat(buf, " ");
+ sprintf(buf + strlen(buf), "-V %s ", client_tag);
isripe = 1;
break;
}
+
if (*flags) {
- if (!isripe && !streq(server, "whois.corenic.net"))
+ if (!isripe)
puts(_("Warning: RIPE flags used with a traditional server."));
strcat(buf, flags);
}
+#ifdef HAVE_ICONV
+ simple_recode_iconv_close();
+ for (i = 0; servers_charset[i].name; i++)
+ if (streq(server, servers_charset[i].name)) {
+ simple_recode_input_charset = servers_charset[i].charset;
+ if (servers_charset[i].options) {
+ strcat(buf, servers_charset[i].options);
+ strcat(buf, " ");
+ }
+ break;
+ }
+#endif
+
#ifdef HAVE_LIBIDN
- /* why, oh why DENIC had to make whois "user friendly"?
- * Do this only if the user did not use any flag.
- */
- if (streq(server, "whois.denic.de") && domcmp(query, ".de")
- && !strchr(query, ' ') && !*flags)
- sprintf(buf, "-T dn,ace -C US-ASCII %s", query);
- else
- /* here we have another registrar who could not make things simple
- * -C sets the language for both input and output
- */
- if (!isripe && streq(server, "whois.cat") && domcmp(query, ".cat")
- && !strchr(query, ' '))
- sprintf(buf, "-C US-ASCII ace %s", query);
- else
+# define DENIC_PARAM_ACE ",ace"
+#else
+# define DENIC_PARAM_ACE ""
#endif
- if (!isripe && (streq(server, "whois.nic.mil") ||
- streq(server, "whois.nic.ad.jp")) &&
- strncaseeq(query, "AS", 2) && isasciidigit(query[2]))
- /* FIXME: /e is not applied to .JP ASN */
- sprintf(buf, "AS %s", query + 2); /* fix query for DDN */
- else if (!isripe && (streq(server, "whois.nic.ad.jp") ||
- streq(server, "whois.jprs.jp"))) {
- char *lang = getenv("LANG"); /* not a perfect check, but... */
- if (!lang || !strneq(lang, "ja", 2))
- sprintf(buf, "%s/e", query); /* ask for english text */
- else
- strcat(buf, query);
- } else if (!isripe && streq(server, "whois.arin.net") &&
- (p = strrchr(query, '/'))) {
- strncat(buf, query, p - query); /* strip CIDR */
- } else
+#ifdef HAVE_ICONV
+# define DENIC_PARAM_CHARSET ""
+#else
+# define DENIC_PARAM_CHARSET " -C US-ASCII"
+#endif
+
+ /* add useful default flags if there are no flags or multiple arguments */
+ if (isripe) { }
+ else if (strchr(query, ' ') || *flags) { }
+ else if (streq(server, "whois.denic.de") && domcmp(query, ".de"))
+ strcat(buf, "-T dn" DENIC_PARAM_ACE DENIC_PARAM_CHARSET " ");
+ else if (streq(server, "whois.dk-hostmaster.dk") && domcmp(query, ".dk"))
+ strcat(buf, "--show-handles ");
+
+ /* mangle and add the query string */
+ if (!isripe && streq(server, "whois.nic.ad.jp") &&
+ strncaseeq(query, "AS", 2) && isasciidigit(query[2])) {
+ strcat(buf, "AS ");
+ strcat(buf, query + 2);
+ }
+ else if (!isripe && streq(server, "whois.arin.net") &&
+ (p = strrchr(query, '/')))
+ strncat(buf, query, p - query); /* strip the mask length */
+ else
strcat(buf, query);
+
+ /* ask for english text */
+ if (!isripe && (streq(server, "whois.nic.ad.jp") ||
+ streq(server, "whois.jprs.jp")) && japanese_locale())
+ strcat(buf, "/e");
+
return buf;
}
/* the first parameter contains the state of this simple state machine:
* HIDE_DISABLED: hidden text finished
- * HIDE_UNSTARTED: hidden text not seen yet
+ * HIDE_NOT_STARTED: hidden text not seen yet
* >= 0: currently hiding message hide_strings[*hiding]
*/
int hide_line(int *hiding, const char *const line)
@@ -532,7 +570,7 @@ int hide_line(int *hiding, const char *const line)
if (*hiding == HIDE_DISABLED) {
return 0;
- } else if (*hiding == HIDE_UNSTARTED) { /* looking for smtng to hide */
+ } else if (*hiding == HIDE_NOT_STARTED) { /* looking for smtng to hide */
for (i = 0; hide_strings[i] != NULL; i += 2) {
if (strneq(line, hide_strings[i], strlen(hide_strings[i]))) {
*hiding = i; /* start hiding */
@@ -540,7 +578,7 @@ int hide_line(int *hiding, const char *const line)
}
}
return 0; /* don't hide this line */
- } else if (*hiding > HIDE_UNSTARTED) { /* hiding something */
+ } else if (*hiding > HIDE_NOT_STARTED) { /* hiding something */
if (*hide_strings[*hiding + 1] == '\0') { /*look for a blank line?*/
if (*line == '\n' || *line == '\r' || *line == '\0') {
*hiding = HIDE_DISABLED; /* stop hiding */
@@ -561,18 +599,19 @@ int hide_line(int *hiding, const char *const line)
/* returns a string which should be freed by the caller, or NULL */
const char *do_query(const int sock, const char *query)
{
- char buf[2000], *p;
+ char *temp, *p, buf[2000];
FILE *fi;
int hide = hide_discl;
char *referral_server = NULL;
+ temp = malloc(strlen(query) + 2 + 1);
+ strcpy(temp, query);
+ strcat(temp, "\r\n");
+
fi = fdopen(sock, "r");
- if (write(sock, query, strlen(query)) < 0)
+ if (write(sock, temp, strlen(temp)) < 0)
err_sys("write");
-/* Using shutdown used to break the buggy RIPE server. Would this work now?
- if (shutdown(sock, 1) < 0)
- err_sys("shutdown");
-*/
+ free(temp);
while (fgets(buf, sizeof(buf), fi)) {
/* 6bone-style referral:
@@ -583,7 +622,7 @@ const char *do_query(const int sock, const char *query)
if (sscanf(buf, REFERTO_FORMAT, nh, np, nq) == 3) {
/* XXX we are ignoring the new query string */
- referral_server = malloc(300);
+ referral_server = malloc(strlen(nh) + 1 + strlen(np) + 1);
sprintf(referral_server, "%s:%s", nh, np);
}
}
@@ -593,32 +632,28 @@ const char *do_query(const int sock, const char *query)
* ReferralServer: whois://whois.ripe.net
*/
if (!referral_server && strneq(buf, "ReferralServer:", 15)) {
- char *q;
-
- q = strstr(buf, "rwhois://");
- if ((q = strstr(buf, "rwhois://")))
- referral_server = strdup(q + 9);
- else if ((q = strstr(buf, "whois://")))
- referral_server = strdup(q + 8);
- if (referral_server) {
- if ((q = strchr(referral_server, '/'))
- || (q = strchr(referral_server, '\n')))
- *q = '\0';
- }
+ if ((p = strstr(buf, "rwhois://")))
+ referral_server = strdup(p + 9);
+ else if ((p = strstr(buf, "whois://")))
+ referral_server = strdup(p + 8);
+ if (referral_server && (p = strpbrk(referral_server, "/\r\n")))
+ *p = '\0';
}
if (hide_line(&hide, buf))
continue;
- for (p = buf; *p && *p != '\r' && *p != '\n'; p++);
- *p = '\0';
- fprintf(stdout, "%s\n", buf);
+ if ((p = strpbrk(buf, "\r\n")))
+ *p = '\0';
+ recode_fputs(buf, stdout);
+ fputc('\n', stdout);
}
+
if (ferror(fi))
err_sys("fgets");
fclose(fi);
- if (hide > HIDE_UNSTARTED)
+ if (hide > HIDE_NOT_STARTED)
err_quit(_("Catastrophic error: disclaimer text has been changed.\n"
"Please upgrade this program.\n"));
@@ -627,9 +662,10 @@ const char *do_query(const int sock, const char *query)
const char *query_crsnic(const int sock, const char *query)
{
- char *temp, buf[2000], *ret = NULL;
+ char *temp, *p, buf[2000];
FILE *fi;
int hide = hide_discl;
+ char *referral_server = NULL;
int state = 0;
temp = malloc(strlen(query) + 1 + 2 + 1);
@@ -640,39 +676,46 @@ const char *query_crsnic(const int sock, const char *query)
fi = fdopen(sock, "r");
if (write(sock, temp, strlen(temp)) < 0)
err_sys("write");
+ free(temp);
+
while (fgets(buf, sizeof(buf), fi)) {
/* If there are multiple matches only the server of the first record
is queried */
if (state == 0 && strneq(buf, " Domain Name:", 15))
state = 1;
if (state == 1 && strneq(buf, " Whois Server:", 16)) {
- char *p, *q;
-
for (p = buf; *p != ':'; p++); /* skip until colon */
for (p++; *p == ' '; p++); /* skip colon and spaces */
- ret = malloc(strlen(p) + 1);
- for (q = ret; *p != '\n' && *p != '\r' && *p != ' '; *q++ = *p++)
- ; /*copy data*/
- *q = '\0';
+ referral_server = strdup(p);
+ if ((p = strpbrk(referral_server, "\r\n ")))
+ *p = '\0';
state = 2;
}
+
/* the output must not be hidden or no data will be shown for
host records and not-existing domains */
- if (!hide_line(&hide, buf))
- fputs(buf, stdout);
+ if (hide_line(&hide, buf))
+ continue;
+
+ if ((p = strpbrk(buf, "\r\n")))
+ *p = '\0';
+ recode_fputs(buf, stdout);
+ fputc('\n', stdout);
}
+
if (ferror(fi))
err_sys("fgets");
+ fclose(fi);
- free(temp);
- return ret;
+ return referral_server;
}
const char *query_pir(const int sock, const char *query)
{
- char *temp, buf[2000], *ret = NULL;
+ char *temp, *p, buf[2000];
FILE *fi;
int hide = hide_discl;
+ char *referral_server = NULL;
int state = 0;
temp = malloc(strlen(query) + 5 + 2 + 1);
@@ -683,6 +726,8 @@ const char *query_pir(const int sock, const char *query)
fi = fdopen(sock, "r");
if (write(sock, temp, strlen(temp)) < 0)
err_sys("write");
+ free(temp);
+
while (fgets(buf, sizeof(buf), fi)) {
/* If there are multiple matches only the server of the first record
is queried */
@@ -691,31 +736,37 @@ const char *query_pir(const int sock, const char *query)
state = 1;
if (state == 1 &&
strneq(buf, "Registrant Street1:Whois Server:", 32)) {
- char *p, *q;
-
for (p = buf; *p != ':'; p++); /* skip until colon */
for (p++; *p != ':'; p++); /* skip until 2nd colon */
for (p++; *p == ' '; p++); /* skip colon and spaces */
- ret = malloc(strlen(p) + 1);
- for (q = ret; *p != '\n' && *p != '\r'; *q++ = *p++); /*copy data*/
- *q = '\0';
+ referral_server = strdup(p);
+ if ((p = strpbrk(referral_server, "\r\n")))
+ *p = '\0';
state = 2;
}
- if (!hide_line(&hide, buf))
- fputs(buf, stdout);
+
+ if (hide_line(&hide, buf))
+ continue;
+
+ if ((p = strpbrk(buf, "\r\n")))
+ *p = '\0';
+ recode_fputs(buf, stdout);
+ fputc('\n', stdout);
}
+
if (ferror(fi))
err_sys("fgets");
+ fclose(fi);
- free(temp);
- return ret;
+ return referral_server;
}
const char *query_afilias(const int sock, const char *query)
{
- char *temp, buf[2000], *ret = NULL;
+ char *temp, *p, buf[2000];
FILE *fi;
int hide = hide_discl;
+ char *referral_server = NULL;
int state = 0;
temp = malloc(strlen(query) + 2 + 1);
@@ -725,39 +776,37 @@ const char *query_afilias(const int sock, const char *query)
fi = fdopen(sock, "r");
if (write(sock, temp, strlen(temp)) < 0)
err_sys("write");
+ free(temp);
while (fgets(buf, sizeof(buf), fi)) {
if (state == 0 && strneq(buf, "Domain Name:", 12))
state = 1;
if (state == 1 && strneq(buf, "Whois Server:", 13)) {
- char *p, *q;
-
for (p = buf; *p != ':'; p++); /* skip until colon */
for (p++; *p == ' '; p++); /* skip colon and spaces */
- ret = malloc(strlen(p) + 1);
- for (q = ret; *p != '\n' && *p != '\r' && *p != ' '; *q++ = *p++)
- ; /*copy data*/
- *q = '\0';
+ referral_server = strdup(p);
+ if ((p = strpbrk(referral_server, "\r\n ")))
+ *p = '\0';
}
- if (!hide_line(&hide, buf)) {
- char *p;
+ if (hide_line(&hide, buf))
+ continue;
- for (p = buf; *p && *p != '\r' && *p != '\n'; p++)
- ;
+ if ((p = strpbrk(buf, "\r\n")))
*p = '\0';
- fprintf(stdout, "%s\n", buf);
- }
+ recode_fputs(buf, stdout);
+ fputc('\n', stdout);
}
+
if (ferror(fi))
err_sys("fgets");
fclose(fi);
- if (hide > HIDE_UNSTARTED)
+ if (hide > HIDE_NOT_STARTED)
err_quit(_("Catastrophic error: disclaimer text has been changed.\n"
"Please upgrade this program.\n"));
- return ret;
+ return referral_server;
}
int openconn(const char *server, const char *port)
@@ -831,9 +880,9 @@ int connect_with_timeout(int fd, const struct sockaddr *addr,
socklen_t addrlen, int timeout)
{
int savedflags, rc, connect_errno, opt;
+ unsigned int len;
fd_set fd_w;
struct timeval tv;
- size_t len;
if (timeout <= 0)
return (connect(fd, addr, addrlen));
@@ -881,7 +930,7 @@ int connect_with_timeout(int fd, const struct sockaddr *addr,
/* and report them */
if (opt != 0) {
- errno = (int) &opt;
+ errno = opt;
return -1;
}
@@ -900,6 +949,22 @@ void sighandler(int signum)
err_quit(_("Interrupted by signal %d..."), signum);
}
+int japanese_locale(void) {
+ char *lang;
+
+ lang = getenv("LC_MESSAGE");
+ if (lang) {
+ if (strneq(lang, "ja", 2))
+ return 0;
+ return 1;
+ }
+
+ lang = getenv("LANG");
+ if (lang && strneq(lang, "ja", 2))
+ return 0;
+ return 1;
+}
+
/* check if dom ends with tld */
int domcmp(const char *dom, const char *tld)
{
@@ -915,14 +980,20 @@ int domcmp(const char *dom, const char *tld)
return 0;
}
+/*
+ * Attempt to normalize a query by removing trailing dots and whitespace,
+ * then convert the domain to punycode.
+ * The function assumes that the domain is the last token of they query.
+ * Returns a malloc'ed string which needs to be freed by the caller.
+ */
char *normalize_domain(const char *dom)
{
char *p, *ret;
char *domain_start = NULL;
ret = strdup(dom);
- for (p = ret; *p; p++); p--; /* move to the last char */
/* eat trailing dots and blanks */
+ p = ret + strlen(ret);
for (; *p == '.' || *p == ' ' || *p == '\t' || p == ret; p--)
*p = '\0';
@@ -1004,61 +1075,61 @@ void split_server_port(const char *const input,
char *convert_6to4(const char *s)
{
- char *new = malloc(sizeof("255.255.255.255"));
+ char *new;
unsigned int a, b;
if (sscanf(s, "2002:%x:%x:", &a, &b) != 2)
- return (char *) "0.0.0.0";
+ return strdup("0.0.0.0");
+ new = malloc(sizeof("255.255.255.255"));
sprintf(new, "%d.%d.%d.%d", a >> 8, a & 0xff, b >> 8, b & 0xff);
return new;
}
char *convert_teredo(const char *s)
{
- char *new = malloc(sizeof("255.255.255.255"));
+ char *new;
unsigned int a, b;
if (sscanf(s, "2001:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%x:%x", &a, &b) != 2)
- return (char *) "0.0.0.0";
+ return strdup("0.0.0.0");
a ^= 0xffff;
b ^= 0xffff;
+ new = malloc(sizeof("255.255.255.255"));
sprintf(new, "%d.%d.%d.%d", a >> 8, a & 0xff, b >> 8, b & 0xff);
return new;
}
char *convert_inaddr(const char *s)
{
- char *new = malloc(sizeof("255.255.255.255"));
+ char *new;
char *endptr;
- unsigned int a, b, c;
+ unsigned int a, b = 0, c = 0;
errno = 0;
a = strtol(s, &endptr, 10);
if (errno || a < 0 || a > 255 || *endptr != '.')
- return (char *) "0.0.0.0";
+ return strdup("0.0.0.0");
if (domcmp(endptr + 1, ".in-addr.arpa")) {
b = strtol(endptr + 1, &endptr, 10); /* 1.2. */
if (errno || b < 0 || b > 255 || *endptr != '.')
- return (char *) "0.0.0.0";
+ return strdup("0.0.0.0");
if (domcmp(endptr + 1, ".in-addr.arpa")) {
c = strtol(endptr + 1, &endptr, 10); /* 1.2.3. */
if (errno || c < 0 || c > 255 || *endptr != '.')
- return (char *) "0.0.0.0";
+ return strdup("0.0.0.0");
if (domcmp(endptr + 1, ".in-addr.arpa"))
- return (char *) "0.0.0.0";
-
- sprintf(new, "%d.%d.%d.0", c, b, a);
- } else
- sprintf(new, "%d.%d.0.0", b, a);
- } else
- sprintf(new, "%d.0.0.0", a);
+ return strdup("0.0.0.0");
+ }
+ }
+ new = malloc(sizeof("255.255.255.255"));
+ sprintf(new, "%d.%d.%d.0", c, b, a);
return new;
}