Imported Debian version 5.0.0

This commit is contained in:
Marco d'Itri 2009-12-20 03:01:40 +01:00
parent e8806bc509
commit 15c8d523f7
16 changed files with 624 additions and 312 deletions

View File

@ -5,10 +5,15 @@ CFLAGS = -g -O2
PERL = perl
INSTALL = install
whois_OBJECTS := whois.o utils.o
mkpasswd_OBJECTS := mkpasswd.o utils.o
##############################################################################
# Solaris
#whois_LDADD += -lnsl -lsocket
#whois_LDADD += -lnsl -lsocket -liconv
# FreeBSD
#whois_LDADD += -liconv
#LIBS += -L/usr/local/lib -lintl
#INCLUDES += -I/usr/local/include
@ -16,6 +21,9 @@ INSTALL = install
#whois_LDADD += -lsocket
#LDFLAGS += -Zexe -Dstrncasecmp=strnicmp
# OS X
#whois_LDADD += -liconv
ifdef CONFIG_FILE
DEFS += -DCONFIG_FILE=\"$(CONFIG_FILE)\"
endif
@ -29,6 +37,11 @@ whois_LDADD += -lidn
DEFS += -DHAVE_LIBIDN
endif
ifdef HAVE_ICONV
whois_OBJECTS += simple_recode.o
DEFS += -DHAVE_ICONV
endif
ifdef HAVE_XCRYPT
mkpasswd_LDADD += -lxcrypt
DEFS += -DHAVE_XCRYPT
@ -36,11 +49,9 @@ else
mkpasswd_LDADD += -lcrypt
endif
##############################################################################
all: Makefile.depend whois mkpasswd #pos
whois_OBJECTS := whois.o utils.o
mkpasswd_OBJECTS := mkpasswd.o utils.o
##############################################################################
%.o: %.c
$(CC) $(DEFS) $(INCLUDES) $(CFLAGS) -c $<
@ -53,19 +64,22 @@ mkpasswd: $(mkpasswd_OBJECTS)
##############################################################################
as_del.h: as_del_list make_as_del.pl
$(PERL) -w make_as_del.pl < as_del_list > $@
$(PERL) -w make_as_del.pl < $< > $@
as32_del.h: as32_del_list make_as32_del.pl
$(PERL) -w make_as32_del.pl < as32_del_list > $@
$(PERL) -w make_as32_del.pl < $< > $@
ip_del.h: ip_del_list make_ip_del.pl
$(PERL) -w make_ip_del.pl < ip_del_list > $@
$(PERL) -w make_ip_del.pl < $< > $@
ip6_del.h: ip6_del_list make_ip6_del.pl
$(PERL) -w make_ip6_del.pl < ip6_del_list > $@
$(PERL) -w make_ip6_del.pl < $< > $@
tld_serv.h: tld_serv_list make_tld_serv.pl
$(PERL) -w make_tld_serv.pl < tld_serv_list > $@
$(PERL) -w make_tld_serv.pl < $< > $@
servers_charset.h: servers_charset_list make_servers_charset.pl
$(PERL) -w make_servers_charset.pl < $< > $@
##############################################################################
install: install-whois install-mkpasswd #install-pos

View File

@ -1,5 +1,5 @@
/* Program version */
#define VERSION "4.7.37"
#define VERSION "5.0.0"
/* Configurable features */

21
data.h
View File

@ -21,8 +21,10 @@ const char *ripe_servers[] = {
"whois.arnes.si",
"www.registry.co.ug",
"whois.nic.ir",
"whois.pandi.or.id",
"whois.nic.ck",
"whois.ra.net",
"whois.bgpmon.net",
NULL
};
@ -74,12 +76,6 @@ const char *nic_handles[] = {
"poem-", "whois.ripe.net",
"form-", "whois.ripe.net",
"pgpkey-", "whois.ripe.net",
#if 0
// commented until somebody will explain the query format for these
"coco-", "whois.corenic.net",
"coho-", "whois.corenic.net",
"core-", "whois.corenic.net",
#endif
"denic-", "whois.denic.de",
/* RPSL objects */
"as-", "whois.ripe.net",
@ -139,3 +135,16 @@ const char *tld_serv[] = {
NULL, NULL
};
#ifdef HAVE_ICONV
struct server_charset {
const char *name;
const char *charset;
const char *options;
};
const struct server_charset servers_charset[] = {
#include "servers_charset.h"
{ NULL, NULL, NULL }
};
#endif

13
debian/changelog vendored
View File

@ -1,3 +1,16 @@
whois (5.0.0) unstable; urgency=low
* Added optional support for automatically transcoding the output of
servers. (Closes: #363366, #402356)
* Automatically add --show-handles to queries for .dk domains.
* Normalize the querystring and convert it to punycode even if a server
is specified on the command line.
* Updated the .id, .is, .my, .sb and .tj TLD servers.
* Removed the .mm, .pw, .sr and .tp TLD servers.
* Cleaned up the horrible strings manipulation code. (Closes: #131924)
-- Marco d'Itri <md@linux.it> Sun, 20 Dec 2009 03:01:40 +0100
whois (4.7.37) unstable; urgency=medium
* Added new ASN allocations.

2
debian/rules vendored
View File

@ -9,7 +9,7 @@ VERSION := $(shell dpkg-parsechangelog | sed -n 's/\+.*$$//; /^Version/s/.* //p'
build:
dh_testdir
$(MAKE) CONFIG_FILE="/etc/whois.conf" HAVE_LIBIDN=1
$(MAKE) CONFIG_FILE="/etc/whois.conf" HAVE_LIBIDN=1 HAVE_ICONV=1
cd po && $(MAKE) whois.pot
touch $@

21
make_servers_charset.pl Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/perl
use warnings;
use strict;
while (<>) {
chomp;
s/#.*$//;
s/^\s+//; s/\s+$//;
next if /^$/;
die "format error: $_" unless
(my ($a, $b, $c) = /^([a-z0-9.-]+)\s+([a-z0-9-]+)(?:\s+(.+))?$/);
if ($c) {
print qq( { "$a",\t"$b",\t"$c" },\n);
} else {
print qq( { "$a",\t"$b",\tNULL },\n);
}
}

34
servers_charset.h Normal file
View File

@ -0,0 +1,34 @@
{ "whois.corenic.net", "utf-8", "-C UTF-8" },
{ "whois.cat", "utf-8", "-C UTF-8" },
{ "whois.museum", "utf-8", "-C UTF-8" },
{ "whois.nic.br", "iso-8859-1", NULL },
{ "whois.cira.ca", "iso-8859-1", NULL },
{ "whois.nic.ch", "utf-8", NULL },
{ "whois.nic.cl", "iso-8859-1", NULL },
{ "whois.cnnic.net.cn", "utf-8", NULL },
{ "whois.nic.cz", "utf-8", NULL },
{ "whois.denic.de", "utf-8", NULL },
{ "whois.enum.denic.de", "utf-8", NULL },
{ "whois.dk-hostmaster.dk", "utf-8", "--charset=utf-8" },
{ "whois.eenet.ee", "iso-8859-1", NULL },
{ "whois.eu", "utf-8", NULL },
{ "whois.ficora.fi", "iso-8859-1", NULL },
{ "whois.nic.fr", "iso-8859-1", NULL },
{ "whois.hkdnr.net.hk", "utf-8", NULL },
{ "whois.nic.hu", "iso-8859-1", NULL },
{ "whois.isnic.is", "iso-8859-1", NULL },
{ "whois.jprs.jp", "iso-2022-jp", NULL },
{ "whois.nic.ad.jp", "iso-2022-jp", NULL },
{ "whois.nic.or.kr", "euc-kr", NULL },
{ "whois.nic.li", "utf-8", NULL },
{ "whois.domreg.lt", "utf-8", NULL },
{ "whois.dns.lu", "iso-8859-1", NULL },
{ "whois.nic.mu", "utf-8", NULL },
{ "whois.norid.no", "iso-8859-1", NULL },
{ "whois.nic.nu", "utf-8", NULL },
{ "whois.dns.pt", "iso-8859-1", NULL },
{ "whois.nic-se.se", "utf-8", NULL },
{ "whois.nic.tr", "utf-8", NULL },
{ "whois.twnic.net", "utf-8", NULL },
{ "whois.net.ua", "koi8-u", NULL },
{ "whois.nic.org.uy", "utf-8", NULL },

37
servers_charset_list Normal file
View File

@ -0,0 +1,37 @@
# server name charset optional parameters
whois.corenic.net utf-8 -C UTF-8
whois.cat utf-8 -C UTF-8
whois.museum utf-8 -C UTF-8
whois.nic.br iso-8859-1
whois.cira.ca iso-8859-1
whois.nic.ch utf-8
whois.nic.cl iso-8859-1
whois.cnnic.net.cn utf-8
whois.nic.cz utf-8
whois.denic.de utf-8
whois.enum.denic.de utf-8
whois.dk-hostmaster.dk utf-8 --charset=utf-8
whois.eenet.ee iso-8859-1
whois.eu utf-8
whois.ficora.fi iso-8859-1
whois.nic.fr iso-8859-1
whois.hkdnr.net.hk utf-8
whois.nic.hu iso-8859-1
whois.isnic.is iso-8859-1
whois.jprs.jp iso-2022-jp
whois.nic.ad.jp iso-2022-jp
whois.nic.or.kr euc-kr
whois.nic.li utf-8
whois.domreg.lt utf-8
whois.dns.lu iso-8859-1
whois.nic.mu utf-8
whois.norid.no iso-8859-1
whois.nic.nu utf-8
whois.dns.pt iso-8859-1
whois.nic-se.se utf-8
whois.nic.tr utf-8
whois.twnic.net utf-8
whois.net.ua koi8-u
whois.nic.org.uy utf-8

176
simple_recode.c Normal file
View File

@ -0,0 +1,176 @@
/*
* Copyright 2009 by Marco d'Itri <md@linux.it>.
*
* simple_recode was inspired by a similar function found in Simon
* Josefsson's libidn.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <iconv.h>
#include <langinfo.h>
#include "utils.h"
#include "simple_recode.h"
/* Global variables */
iconv_t simple_recode_iconv_handle;
const char *simple_recode_input_charset;
/*
* These value should be tuned to an acceptable compromise between memory
* usage and calling iconv(3) as few times as possible.
*/
#define SIMPLE_RECODE_BUFFER_SIZE_1 256
#define SIMPLE_RECODE_BUFFER_SIZE_2 1024
#define SIMPLE_RECODE_BUFFER_INCREMENT 1
/*
* Convert a NULL-terminated string accordingly to the provided iconv(3)
* handle. The returned string is allocated using malloc(3) and needs to be
* deallocated by the caller.
* Incomplete, invalid and impossible to recode sequences are copied as-is.
* On failure, NULL is returned and errno is set.
*/
char *simple_recode(const iconv_t handle, const char *str)
{
char *inp = (char *) str;
char *outp, *result;
size_t inbytes_remaining, outbytes_remaining, outbuf_size;
inbytes_remaining = strlen(inp);
if (inbytes_remaining + 1 <= SIMPLE_RECODE_BUFFER_SIZE_1
- (SIMPLE_RECODE_BUFFER_SIZE_1 >> SIMPLE_RECODE_BUFFER_INCREMENT))
outbuf_size = SIMPLE_RECODE_BUFFER_SIZE_1;
else
outbuf_size = inbytes_remaining + 1
+ (inbytes_remaining >> SIMPLE_RECODE_BUFFER_INCREMENT);
outp = result = malloc(outbuf_size);
if (!result)
return NULL;
outbytes_remaining = outbuf_size - 1;
do {
size_t err = iconv(handle, &inp, &inbytes_remaining, &outp,
&outbytes_remaining);
if (err != -1)
break; /* success */
switch (errno) {
case EINVAL: /* incomplete multibyte sequence */
case EILSEQ: /* invalid multibyte sequence */
#ifdef SIMPLE_RECODE_SKIP_INVALID_SEQUENCES
/* recover from invalid input by replacing it with a '?' */
inp++;
*outp++ = '?'; /* use U+FFFD for unicode output? how? */
#else
/* garbage in, garbage out */
*outp++ = *inp++;
#endif
inbytes_remaining--;
outbytes_remaining--;
continue;
case E2BIG:
{
size_t used = outp - result;
size_t newsize;
if (outbuf_size < SIMPLE_RECODE_BUFFER_SIZE_2)
newsize = SIMPLE_RECODE_BUFFER_SIZE_2;
else
newsize = outbuf_size
+ (outbuf_size >> SIMPLE_RECODE_BUFFER_INCREMENT);
/* check if the newsize variable has overflowed */
if (newsize <= outbuf_size) {
errno = ENOMEM;
return NULL;
}
outbuf_size = newsize;
result = realloc(result, outbuf_size);
if (!result)
return NULL;
/* update the position in the new output stream */
outp = result + used;
outbytes_remaining = outbuf_size - used - 1;
continue;
}
default:
return NULL;
}
} while (inbytes_remaining > 0);
*outp = '\0';
return result;
}
/*
* Like fputs(3), but transparently recodes s using the global variable
* simple_recode_input_charset as the input charset and the current locale
* as the output charset.
* If simple_recode_input_charset is NULL it just calls fputs(3).
* Exits with an error if iconv(3) or iconv_open(3) fail.
*
* Assumes that setlocale(3) has already been called.
*
* If appropriate, the iconv object referenced by the global variable
* simple_recode_iconv_handle should be deallocated with iconv_close(3).
*/
int recode_fputs(const char *s, FILE *stream)
{
char *out;
int result;
if (simple_recode_input_charset == NULL) /* no conversion is needed */
return fputs(s, stream);
if (simple_recode_iconv_handle == NULL) {
simple_recode_iconv_handle = iconv_open(nl_langinfo(CODESET),
simple_recode_input_charset);
if (simple_recode_iconv_handle == (iconv_t) - 1)
err_sys("iconv_open");
}
out = simple_recode(simple_recode_iconv_handle, s);
if (!out)
err_sys("iconv");
result = fputs(out, stream);
free(out);
return result;
}
void simple_recode_iconv_close(void)
{
if (simple_recode_iconv_handle == NULL)
return;
iconv_close(simple_recode_iconv_handle);
simple_recode_iconv_handle = NULL;
simple_recode_input_charset = NULL;
}

14
simple_recode.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef SIMPLE_RECODE_H
#define SIMPLE_RECODE_H
#include <iconv.h>
#include <stdio.h>
extern iconv_t simple_recode_iconv_handle;
extern const char *simple_recode_input_charset;
char *simple_recode(const iconv_t handle, const char *str);
int recode_fputs(const char *s, FILE* stream);
void simple_recode_iconv_close(void);
#endif

View File

@ -80,6 +80,7 @@
.bh NONE # www.inet.com.bh
.bi WEB http://whois.nic.bi/register/whois.hei # whois.nic.bi wrong referral?
.bj whois.nic.bj
#.bl
.bm WEB http://207.228.133.14/cgi-bin/lansaweb?procfun+BMWHO+BMWHO2+WHO
.bn NONE # www.brunet.bn
.bo WEB http://www.nic.bo/
@ -156,7 +157,7 @@
.hr WEB http://www.dns.hr/pretrazivanje.html
.ht whois.nic.ht
.hu whois.nic.hu
.id whois.idnic.net.id
.id whois.pandi.or.id
.ie whois.domainregistry.ie
.il whois.isoc.org.il
.im whois.nic.im
@ -164,7 +165,7 @@
.io whois.nic.io
.iq NONE # http://www.cmc.iq/english/iq/iqregister1.htm
.ir whois.nic.ir
.is whois.isnet.is
.is whois.isnic.is
.it whois.nic.it
.je whois.je
.jm NONE # NIC? uwimona.edu.jm http://nic.jm
@ -196,11 +197,12 @@
.mc whois.ripe.net
.md WEB http://www.dns.md/wh1.php # whois.nic.md is restricted
.me whois.meregistry.net # afilias
#.mf
.mg whois.nic.mg
.mh NONE # www.nic.net.mh
.mk WEB http://dns.marnet.net.mk/registar.php
.ml NONE # NIC? www.sotelma.ml
.mm whois.nic.mm
.mm NONE # NO NIC
.mn AFILIAS
.mo WEB http://www.monic.net.mo/
.mp NONE # get.mp
@ -212,7 +214,7 @@
.mv NONE # NIC? www.dhiraagu.com.mv
.mw WEB http://www.registrar.mw/
.mx whois.nic.mx
.my whois.mynic.net.my
.my whois.domainregistry.my
.mz NONE # NIC? www.uem.mz
.na whois.na-nic.com.na
.nc whois.cctld.nc
@ -240,7 +242,7 @@
.pr whois.nic.pr
.ps WEB http://www.nic.ps/whois/whois.html
.pt whois.dns.pt
.pw whois.nic.pw
.pw NONE # NO NIC
.py WEB http://www.nic.py/consultas.html
.qa NONE # http://www.qtel.com.qa/InternetFeatures.do
.re whois.nic.fr
@ -250,7 +252,7 @@
.ru whois.ripn.net
.rw WEB http://www.nic.rw/cgi-bin/whoisrw.pl
.sa saudinic.net.sa
.sb whois.nic.net.sb
.sb whois.coccaregistry.net
.sc AFILIAS # www.nic.sc
.sd NONE # http://isoc.sd/ (CHECK LATER)
.se whois.nic-se.se
@ -263,7 +265,7 @@
.sm whois.ripe.net
.sn whois.nic.sn
.so NONE # www.nic.so (CHECK LATER, recently delegated)
.sr whois.register.sr
.sr NONE # www.register.sr
.st whois.nic.st
.su whois.ripn.net
.sv WEB http://www.uca.edu.sv/dns/ # http://www.svnet.org.sv/
@ -274,13 +276,13 @@
.tf whois.nic.tf
.tg WEB http://www.nic.tg/
.th whois.thnic.net
.tj whois.nic.tj
.tj WEB http://www.nic.tj/whois.html
.tk whois.dot.tk
.tl whois.nic.tl
.tm whois.nic.tm
.tn WEB http://whois.ati.tn/
.to whois.tonic.to
.tp whois.nic.tp
.tp NONE # phase out in progress
.tr whois.nic.tr
.tt WEB http://www.nic.tt/cgi-bin/search.pl
.tv VERISIGN whois.nic.tv
@ -300,6 +302,7 @@
.parliament.uk NONE
.police.uk NONE
.uk whois.nic.uk
#.um
.fed.us whois.nic.gov
.us whois.nic.us
.com.uy WEB https://nic.anteldata.com.uy/dns/
@ -312,10 +315,10 @@
.vi WEB http://www.nic.vi/whoisform.htm
.vn WEB http://www.vnnic.vn/english/
.vu WEB http://www.vunic.vu/whois.html
.wf whois.nic.wf
.wf whois.nic.fr
.ws whois.samoanic.ws
.ye NONE # NIC? www.nominet.org.ye http://www.y.net.ye/services/domain_name.htm
.yt whois.nic.yt
.yt whois.nic.fr
.yu NONE # www.nic.yu - phase out date: 30 March 2009
.ac.za whois.ac.za
.co.za whois.coza.net.za
@ -340,7 +343,7 @@
-cz whois.nic.cz
-dk whois.dk-hostmaster.dk
-il whois.isoc.org.il
-is whois.isnet.is
-is whois.isnic.is
-kg whois.domain.kg
-ti whois.telstra.net
-tw whois.twnic.net

View File

@ -1,90 +0,0 @@
The gentoo people submitted this patch. I'm not applying it as it makes
the code harder to understand with no major gain and without being a
fully correct fix.
diff -Nru whois-4.6.6.orig/whois.c whois-4.6.6/whois.c
--- whois-4.6.6.orig/whois.c 2003-06-15 12:36:52.000000000 -0400
+++ whois-4.6.6/whois.c 2003-08-11 02:15:30.000000000 -0400
@@ -73,12 +73,12 @@
/* RIPE flags */
if (strchr(ripeflags, ch)) {
for (p = fstring; *p; p++);
- sprintf(p--, "-%c ", ch);
+ snprintf(p--, sizeof(fstring), "-%c ", ch);
continue;
}
if (strchr(ripeflagsp, ch)) {
for (p = fstring; *p; p++);
- sprintf(p--, "-%c %s ", ch, optarg);
+ snprintf(p--, sizeof(fstring), "-%c %s ", ch, optarg);
if (ch == 't' || ch == 'v' || ch == 'q')
nopar = 1;
continue;
@@ -132,10 +132,10 @@
while (1) {
qslen += strlen(*argv) + 1 + 1;
qstring = realloc(qstring, qslen);
- strcat(qstring, *argv++);
+ strncat(qstring, *argv++, qslen-1);
if (argc == 1)
break;
- strcat(qstring, " ");
+ strncat(qstring, " ", qslen);
argc--;
}
}
@@ -401,10 +401,13 @@
{
char *buf;
int i, isripe = 0;
+ int buflen = 0;
/* +10 for CORE; +2 for \r\n; +1 for NULL */
- buf = malloc(strlen(flags) + strlen(query) + strlen(client_tag) + 4
- + 10 + 2 + 1);
+ buflen = (strlen(flags) + strlen(query) + strlen(client_tag) + 4 + 10 + 2 + 1);
+
+ buf = malloc(buflen);
+
*buf = '\0';
for (i = 0; ripe_servers[i]; i++)
if (strcmp(server, ripe_servers[i]) == 0) {
@@ -426,23 +429,23 @@
if (*flags) {
if (!isripe && strcmp(server, "whois.corenic.net") != 0)
puts(_("Warning: RIPE flags used with a traditional server."));
- strcat(buf, flags);
+ strncat(buf, flags, buflen);
}
/* FIXME: /e is not applied to .JP ASN */
if (!isripe && (strcmp(server, "whois.nic.mil") == 0 ||
strcmp(server, "whois.nic.ad.jp") == 0) &&
strncasecmp(query, "AS", 2) == 0 && isasciidigit(query[2]))
- sprintf(buf, "AS %s", query + 2); /* fix query for DDN */
+ snprintf(buf, buflen, "AS %s", query + 2); /* fix query for DDN */
else if (!isripe && strcmp(server, "whois.corenic.net") == 0)
- sprintf(buf, "--machine %s", query); /* machine readable output */
+ snprintf(buf, buflen, "--machine %s", query); /* machine readable output */
else if (!isripe && strcmp(server, "whois.nic.ad.jp") == 0) {
char *lang = getenv("LANG"); /* not a perfect check, but... */
if (!lang || (strncmp(lang, "ja", 2) != 0))
- sprintf(buf, "%s/e", query); /* ask for english text */
+ snprintf(buf, buflen, "%s/e", query); /* ask for english text */
else
- strcat(buf, query);
+ strncat(buf, query, buflen);
} else
- strcat(buf, query);
+ strncat(buf, query, buflen);
return buf;
}
@@ -485,7 +488,7 @@
if (verb)
printf(_("Detected referral to %s on %s.\n"), nq, nh);
- strcat(nq, "\r\n");
+ strncat(nq, "\r\n", sizeof(nq));
fd = openconn(nh, np);
do_query(fd, nq);
continue;

35
whois.1
View File

@ -1,4 +1,4 @@
.TH "WHOIS" "1" "4 March 2005" "Marco d'Itri" "Debian GNU/Linux"
.TH "WHOIS" "1" "20 December 2009" "Marco d'Itri" "Debian GNU/Linux"
.SH "NAME"
whois \- client for the whois directory service
.SH "SYNOPSIS"
@ -52,17 +52,20 @@ only search in the domains database. If you want to search for NIC handles
you have to prepend a \fI!\fP character. When you do this, the default
server becomes \fIwhois.networksolutions.com\fP.
.P
When querying \fIwhois.nic.mil\fP for AS numbers, the program will
When querying \fIwhois.arin.net\fP for IPv4 or IPv6 networks, the CIDR
netmask length will be automatically removed from the query string.
.P
When querying \fIwhois.nic.ad.jp\fP for AS numbers, the program will
automatically convert the request in the appropriate format, inserting
a space after the string \fIAS\fP.
.P
If the program is compiled with IDN support, when querying
\fIwhois.denic.de\fP for domain names it will automatically add the flags
\fI\-T dn,ace \-C US\-ASCII\fP if no flags have been specified by the user.
The domain name will \fBalways\fP be IDN-encoded.
When querying \fIwhois.denic.de\fP for domain names and no other
flags have been specified, the program will automatically add the flag
\fI\-T dn\fP.
.P
When querying \fIwhois.corenic.net\fP, the program will automatically
request machine-readable output.
When querying \fIwhois.dk-hostmaster.dk\fP for domain names and no other
flags have been specified, the program will automatically add the flag
\fI\-\-show\-handles\fP.
.P
RIPE-specific command line options are ignored when querying non-RIPE
servers. This may or may not be the behaviour intended by the user.
@ -75,6 +78,12 @@ to find a server before applying the normal rules. Each line of the
file should contain a regular expression to be matched against the query
text and the whois server to use, separated by white space.
.P
The whois protocol does not specify an encoding for characters which
cannot be represented by ASCII and implementations vary wildly.
If the program knows that a specific server uses a certain encoding,
if needed it will transcode the server output to the encoding specified
by the current system locale.
.P
Command line arguments will always be interpreted accordingly to the
current system locale and converted to the IDN ASCII Compatible Encoding.
.SH "Files"
@ -82,8 +91,8 @@ current system locale and converted to the IDN ASCII Compatible Encoding.
.SH "ENVIRONMENT"
.IP LANG
When querying \fIwhois.nic.ad.jp\fP and \fIwhois.jprs.jp\fP english text
is requested unless the
\fILANG\fP environment variable specifies a Japanese locale.
is requested unless the \fILANG\fP or \fILC_MESSAGES\fP environment
variables specify a Japanese locale.
.IP "WHOIS_OPTIONS"
A list of options which will be evalued before the ones specified on the
command line.
@ -101,9 +110,9 @@ the help file which can be obtained with the command:
.IP
.B whois \-h whois.ripe.net HELP
.SH "BUGS"
The program has many buffer overflows when parsing the command line
parameters: be sure to not pass untrusted data to it.
It will be rewritten to use a dynamic strings library.
The program may have buffer overflows in the command line parser:
be sure to not pass untrusted data to it.
It should be rewritten to use a dynamics strings library.
.SH "HISTORY"
This program closely tracks the user interface of the whois client
developed at RIPE by Ambrose Magee and others on the base of the

419
whois.c
View File

@ -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_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
#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
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_LIBIDN
# define DENIC_PARAM_ACE ",ace"
#else
# define DENIC_PARAM_ACE ""
#endif
#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;
}

View File

@ -3,13 +3,13 @@
/* String sent to RIPE servers - MUST NOT BE LONGER THAN FIVE CHARACTERS! */
/* Do *NOT* change it if you don't know what you are doing! */
#define IDSTRING "Md4.7"
#define IDSTRING "Md5.0"
#define HIDE_DISABLED -2
#define HIDE_UNSTARTED -1
#define HIDE_NOT_STARTED -1
/* prototypes */
const char *whichwhois(const char *);
const char *guess_server(const char *);
const char *match_config_file(const char *);
const char *whereas(const unsigned long);
const char *whereas32(const unsigned long);
@ -24,6 +24,7 @@ int connect_with_timeout(int, const struct sockaddr *, socklen_t, int);
void usage(void);
void alarm_handler(int);
void sighandler(int);
int japanese_locale(void);
unsigned long myinet_aton(const char *);
unsigned long asn32_to_long(const char *);
int isasciidigit(const char);
@ -33,7 +34,7 @@ char *normalize_domain(const char *);
char *convert_6to4(const char *);
char *convert_teredo(const char *);
char *convert_inaddr(const char *);
const char *handle_query(const char *server, const char *port,
void handle_query(const char *server, const char *port,
const char *qstring, const char *fstring);
void split_server_port(const char *const input, const char **server,
const char **port);

View File

@ -1,6 +1,6 @@
Summary: Enhanced WHOIS client
Name: whois
Version: 4.7.37
Version: 5.0.0
Release: 1
License: GPL
Vendor: Marco d'Itri <md@linux.it>
@ -20,7 +20,7 @@ server for most queries.
%setup
%build
make OPTS="$RPM_OPT_FLAGS"
make CFLAGS="$RPM_OPT_FLAGS" HAVE_LIBIDN=1 HAVE_ICONV=1
%install
rm -rf ${RPM_BUILD_ROOT}