Home | History | Annotate | Line # | Download | only in whois
whois.c revision 1.15
      1 /*	$NetBSD: whois.c,v 1.15 2000/10/04 20:09:05 mjl Exp $	*/
      2 
      3 /*
      4  * RIPE version marten (at) ripe.net
      5  * many changes & networkupdate by david (at) ripe.net
      6  * cosmetics by steven (at) dante.org.uk --	gcc stopped complaining mostly,
      7  *					code is still messy, though.
      8  *
      9  * 1.15 94/09/07
     10  *
     11  * 1.2  9705/02
     12  * "-v" option added; ambrose (at) ripe.net
     13  * "whois.ripe.net" replaced by "bsdbase.ripe.net";  ambrose (at) ripe.net
     14  * "bsdbase.ripe.net" replaced by "joshua.ripe.net"; marek (at) ripe.net
     15  * "joshua.ripe.net" replaced by "whois.ripe.net"; roman (at) ripe.net 981105
     16  *
     17  * Copyright (c) 1980 Regents of the University of California.
     18  * All rights reserved.
     19  *
     20  * Redistribution and use in source and binary forms, with or without
     21  * modification, are permitted provided that the following conditions
     22  * are met:
     23  * 1. Redistributions of source code must retain the above copyright
     24  *    notice, this list of conditions and the following disclaimer.
     25  * 2. Redistributions in binary form must reproduce the above copyright
     26  *    notice, this list of conditions and the following disclaimer in the
     27  *    documentation and/or other materials provided with the distribution.
     28  * 3. All advertising materials mentioning features or use of this software
     29  *    must display the following acknowledgement:
     30  *	This product includes software developed by the University of
     31  *	California, Berkeley and its contributors.
     32  * 4. Neither the name of the University nor the names of its contributors
     33  *    may be used to endorse or promote products derived from this software
     34  *    without specific prior written permission.
     35  *
     36  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     37  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     39  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     40  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     41  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     42  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     44  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     45  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     46  * SUCH DAMAGE.
     47  */
     48 
     49 #include <sys/cdefs.h>
     50 #if defined(sun) && defined(solaris)
     51 #define SYSV
     52 #endif
     53 
     54 #ifndef lint
     55 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
     56 	The Regents of the University of California.  All rights reserved.\n");
     57 #endif /* not lint */
     58 
     59 #ifndef RIPE
     60 #ifndef lint
     61 #if 0
     62 static char sccsid[] = "@(#)whois.c	8.1 (Berkeley) 6/6/93";
     63 #else
     64 __RCSID("$NetBSD: whois.c,v 1.15 2000/10/04 20:09:05 mjl Exp $");
     65 #endif
     66 #endif /* not lint */
     67 #endif /* not RIPE */
     68 
     69 #ifdef RIPE
     70 #ifndef lint
     71 char sccsid[] =
     72     "@(#)whois.c 5.11 (Berkeley) 3/2/91 - RIPE 1.15 94/09/07 marten (at) ripe.net";
     73 #endif /* not lint */
     74 #endif /* RIPE */
     75 
     76 #include <sys/types.h>
     77 #include <sys/socket.h>
     78 #include <sys/param.h>
     79 #include <netinet/in.h>
     80 #include <err.h>
     81 #include <netdb.h>
     82 #include <stdio.h>
     83 #include <stdlib.h>
     84 #include <ctype.h>
     85 #include <string.h>
     86 #include <errno.h>
     87 #include <unistd.h>
     88 #include <pwd.h>
     89 #include <signal.h>
     90 
     91 #if defined(SYSV)
     92 #include	<crypt.h>
     93 #endif /* SYSV */
     94 
     95 #ifndef __NetBSD__
     96 #ifdef __STDC__
     97 extern int	getopt(int argc, char * const *argv, const char *optstring);
     98 extern int	kill(pid_t pid, int sig);
     99 extern FILE	*fdopen(int fildes, const char *type);
    100 extern int	gethostname(char *name, int namelen);
    101 #else /* !__STDC__ */
    102 extern int	gethostname();
    103 #endif /* __STDC__ */
    104 #endif /* __NetBSD__ */
    105 
    106 #if defined(SYSV) || defined(__STDC__)
    107 
    108 #define		index(s,c)		strchr((const char*)(s),(int)(c))
    109 #define		rindex(s,c)		strrchr((const char*)(s),(int)(c))
    110 #define		bzero(s,n)		memset((void*)s,0,(size_t)n)
    111 
    112 #ifdef HASMEMMOVE
    113 # define	bcopy(s,d,n)	memmove((void*)(d),(void*)(s),(size_t)(n))
    114 #else
    115 # define	bcopy(s,d,n)	memcpy((void*)(d),(void*)(s),(size_t)(n))
    116 #endif /* HASMEMMOVE */
    117 
    118 #endif /* SYSV || __STDC__ */
    119 
    120 #ifdef GLIBC
    121 typedef __u_short u_short;
    122 typedef __caddr_t caddr_t;
    123 #endif /* GLIBC */
    124 
    125 /*
    126 
    127 # the following defines can be used but are not fully functional anymore...
    128 #
    129 # CLEVER- Use a educated guess of the whereabouts of the nearest server
    130 #	  This is done by taking the top-level domain of the current
    131 #	  machine, and looking for a CNAME record for a server with name
    132 #	  <top-level-domain>-whois.ripe.net
    133 #	  If this machine does not exsist or the current machine's top-level
    134 #	  domain could not be found,it will fall back to whois.ripe.net
    135 #	  the default for this RIPE version of whois
    136 #	  The CLEVER option implies the RIPE option.
    137 
    138 # TOPDOMAIN=\"<top-level-domain>\"
    139 #	- This option will fix the default host to be
    140 #	  <top-level-domain>-whois.ripe.net, which may point to a secondary
    141 #	  server inside your top-level domain. If there is no such secondary
    142 #	  server, it will point to whois.ripe.net, the default. This option
    143 #	  overrules the CLEVER option.
    144 #	  The TOPDOMAIN option implies the RIPE option.
    145 
    146 */
    147 
    148 #if defined(TOPDOMAIN) || defined(CLEVER)
    149 #ifndef RIPE
    150 #define RIPE
    151 #endif /* !RIPE */
    152 #endif /* TOPDOMAIN || CLEVER */
    153 
    154 #if defined(RIPE) && !defined(__NetBSD__)
    155 #include <sys/param.h>
    156 #define NICHOST "whois.ripe.net"
    157 #else
    158 #define NICHOST "whois.internic.net"
    159 #endif
    160 
    161 int main __P((int, char **));
    162 static void usage __P((void));
    163 static void closesocket __P((int, int));
    164 static void termhandler __P((int));
    165 
    166 void usage()
    167 {
    168 #ifdef RIPE
    169 #ifdef NETWORKUPDATE
    170   (void)fprintf(stderr, "\nUsage: networkupdate [-46] [-h hostname] [-p port]");
    171 #else
    172   (void)fprintf(stderr, "\nUsage: whois [-46aFLmMrSvR] [-h hostname] [-s sources] [-T types] [-i attr] keys\n");
    173   (void)fprintf(stderr, "       whois -t type");
    174   (void)fprintf(stderr, "       whois -v type");
    175 #endif
    176 #else
    177   (void)fprintf(stderr, "\nUsage: whois [-46] [-h hostname] [-p port] name ...");
    178 #endif
    179   (void)fprintf(stderr, "\n\nWhere:\n\n");
    180   (void)fprintf(stderr, "-4                         Use IPv4 Only\n");
    181   (void)fprintf(stderr, "-6                         Use IPv6 Only\n");
    182 #ifdef RIPE
    183 #ifndef NETWORKUPDATE
    184   (void)fprintf(stderr, "-a                         search all databases\n");
    185   (void)fprintf(stderr, "-F                         fast raw output\n");
    186 #endif
    187 #endif
    188   (void)fprintf(stderr, "-h hostname                search alternate server\n");
    189 #ifdef RIPE
    190 #ifndef NETWORKUPDATE
    191   (void)fprintf(stderr, "-i [attr][[,attr] ... ]    do an inverse lookup for specified attributes\n");
    192   (void)fprintf(stderr, "-L                         find all Less specific matches\n");
    193   (void)fprintf(stderr, "-m                         find first level more specific matches\n");
    194   (void)fprintf(stderr, "-M                         find all More specific matches\n");
    195 #endif
    196 #endif
    197   (void)fprintf(stderr, "-p port                    port to connect to\n");
    198 #ifdef RIPE
    199 #ifndef NETWORKUPDATE
    200   (void)fprintf(stderr, "-r                         turn off recursive lookups\n");
    201   (void)fprintf(stderr, "-s source[[,source] ... ]  search databases with source 'source'\n");
    202   (void)fprintf(stderr, "-S                         tell server to leave out 'syntactic sugar'\n");
    203   (void)fprintf(stderr, "-t type                    requests template for object of type 'type'\n");
    204   (void)fprintf(stderr, "-v type                    requests verbose template for object of type 'type'\n");
    205   (void)fprintf(stderr, "-R                         force to show local copy of the domain object even if it contains referral\n");
    206   (void)fprintf(stderr, "-T type[[,type] ... ]      only look for objects of type 'type'\n\n");
    207   (void)fprintf(stderr, "Please note that most of these flags are NOT understood by\n");
    208   (void)fprintf(stderr, "non RIPE whois servers\n");
    209 #endif
    210 #endif
    211   (void)fprintf(stderr, "\n");
    212 
    213   exit(1);
    214 }
    215 
    216 int s;
    217 
    218 void closesocket(s, child)
    219 int s, child;
    220 {
    221   /* printf("close connection child=%i\n", child);  */
    222 
    223   close(s);
    224 
    225 #ifdef NETWORKUPDATE
    226   if (child==0) {
    227      kill(getppid(), SIGTERM);
    228   }
    229 #endif
    230 
    231   exit(0);
    232 
    233 }
    234 
    235 void termhandler(sig)
    236 int sig;
    237 {
    238   closesocket(s,1);
    239 }
    240 
    241 
    242 #ifdef RIPE
    243 #if defined(__STDC__) || defined(SYSV)
    244 #define occurs(str,pat)		((int) strstr((str),(pat)))
    245 #else /* !__STDC__ && !SYSV */
    246 int occurs(str, pat)
    247      char *str, *pat;
    248 {
    249   register char *point = str;
    250 
    251   while ((point=index(point, *pat)))
    252     {
    253       if (strncmp(point, pat, strlen(pat)) == 0)
    254 	return(1);
    255       point++;
    256     }
    257   return(0);
    258 }
    259 #endif
    260 #endif
    261 
    262 int main(argc, argv)
    263      int argc;
    264      char **argv;
    265 {
    266   extern char *optarg;
    267   extern int optind;
    268   FILE *sfi;
    269   FILE *sfo;
    270   int ch;
    271   struct addrinfo *dst, hints;
    272   int af=PF_UNSPEC;
    273   int error;
    274   char *host, *whoishost;
    275   int optp=0;
    276   char *optport="whois";
    277 #ifdef DEBUG
    278   int verb=1;
    279 #else /*DEBUG */
    280   int verb=0;
    281 #endif
    282 #ifdef RIPE
    283   int opthost=0;
    284 #ifndef NETWORKUPDATE
    285   /* normal whois client */
    286   char *string;
    287   int alldatabases=0;
    288   int optsource=0, optrecur=0, optfast=0, opttempl=0, optverbose=0;
    289   int optobjtype=0, optsugar=0, optinverselookup=0, optgetupdates=0;
    290   int optL=0, optm=0, optM=0, optchanged=0, optnonreferral=0;
    291   char	*source=NULL, *templ=NULL, *verbose=NULL, *objtype=NULL,
    292 	*inverselookup=NULL, *getupdates=NULL;
    293 #else /* NETWORKUPDATE */
    294   /* networkupdate client */
    295   int prev;
    296   char domainname[64]; /* that's what sys/param.h says */
    297   struct passwd *passwdentry;
    298   int child;
    299 #endif
    300 #ifdef CLEVER
    301   int  myerror;
    302   char *mytoplevel;
    303   char *myhost;
    304 #endif
    305 #endif
    306 
    307 #ifdef TOPDOMAIN
    308   host = strcat(TOPDOMAIN, "-whois.ripe.net");
    309 #else
    310   host = NICHOST;
    311 #endif
    312 
    313 #ifdef RIPE
    314 #ifdef NETWORKUPDATE
    315     while ((ch = getopt(argc, argv, "46h:p:")) != -1)
    316 #else
    317   while ((ch = getopt(argc, argv, "46acFg:h:i:LmMp:rs:SRt:T:v:")) != -1)
    318 #endif
    319 #else
    320     while ((ch = getopt(argc, argv, "46h:p:")) != -1)
    321 #endif
    322       switch((char)ch) {
    323       case '4':
    324 	af = PF_INET;
    325 	break;
    326       case '6':
    327 	af = PF_INET6;
    328 	break;
    329       case 'h':
    330 	host = optarg;
    331 	opthost = 1;
    332 	break;
    333       case 'p':
    334 	optport=optarg;
    335         optp =1;
    336         break;
    337 #ifdef RIPE
    338 #ifndef NETWORKUPDATE
    339       case 'a':
    340 	alldatabases=1;
    341 	break;
    342       case 'c':
    343         optchanged=1;
    344         break;
    345       case 'F':
    346 	optfast = 1;
    347 	break;
    348       case 'g':
    349         getupdates=optarg;
    350 	optgetupdates=1;
    351 	break;
    352       case 'i':
    353         inverselookup=optarg;
    354 	optinverselookup = 1;
    355 	break;
    356       case 'L':
    357 	if (optM || optm) {
    358           fprintf(stderr, "Only one of -L, -m or -M allowed\n\n");
    359           usage();
    360         }
    361 	optL=1;
    362 	break;
    363       case 'm':
    364 	if (optM || optL) {
    365 	  fprintf(stderr, "Only one of -L, -m or -M allowed\n\n");
    366           usage();
    367 	}
    368 	optm=1;
    369 	break;
    370       case 'M':
    371 	if (optL || optm) {
    372 	  fprintf(stderr, "Only one of -L, -m or -M allowed\n\n");
    373 	  usage();
    374 	}
    375 	optM=1;
    376 	break;
    377 
    378       case 's':
    379 	source = optarg;
    380 	optsource=1;
    381 	break;
    382       case 'S':
    383 	optsugar=1;
    384 	break;
    385       case 'R':
    386 	optnonreferral=1;
    387 	break;
    388       case 'r':
    389 	optrecur=1;
    390 	break;
    391       case 't':
    392 	 templ=optarg;
    393 	 opttempl=1;
    394 	 break;
    395       case 'v':
    396 	 verbose=optarg;
    397 	 optverbose=1;
    398 	 break;
    399       case 'T':
    400 	objtype=optarg;
    401 	optobjtype=1;
    402 	break;
    403 
    404 #endif
    405 #endif
    406       case '?':
    407       default:
    408 	usage();
    409       }
    410   argc -= optind;
    411   argv += optind;
    412 
    413 #ifdef RIPE
    414 #ifdef NETWORKUPDATE
    415   if (argc>0)
    416     usage();
    417 #else
    418   if ((argc<=0) && !opttempl && !optverbose && !optgetupdates && (!(opttempl && optgetupdates)))
    419     usage();
    420 #endif
    421 #else
    422   if (argc<=0)
    423     usage();
    424 #endif
    425 
    426   if (!opthost) {
    427 
    428 #ifdef CLEVER
    429     whoishost=(char *)calloc(MAXHOSTNAMELEN, sizeof(char));
    430     myhost =(char *)calloc(MAXHOSTNAMELEN, sizeof(char));
    431     myerror = gethostname(myhost, MAXHOSTNAMELEN);
    432     if (myerror >= 0) {
    433       if (occurs(myhost, ".")) {
    434 	mytoplevel = rindex(myhost,'.');
    435 	mytoplevel++;
    436 	(void) sprintf(whoishost, "%s-whois.ripe.net", mytoplevel);
    437 	if (verb) fprintf(stderr, "Clever guess: %s\n", whoishost);
    438       }
    439     }
    440 
    441     memset(&hints, 0, sizeof(hints));
    442     hints.ai_flags = AI_CANONNAME;
    443     hints.ai_family = af;
    444     hints.ai_socktype = SOCK_STREAM;
    445     hints.ai_protocol = 0;
    446     error = getaddrinfo(host, optport, &hints, &dst);
    447     if ((error) && (verb))
    448       fprintf(stderr,"No such host: %s\n", whoishost);
    449     if (error) {
    450 #endif
    451 
    452       whoishost=NICHOST;
    453 
    454       if (verb)
    455 	fprintf(stderr, "Default host: %s\n\n", whoishost);
    456       memset(&hints, 0, sizeof(hints));
    457       hints.ai_flags = AI_CANONNAME;
    458       hints.ai_family = af;
    459       hints.ai_socktype = SOCK_STREAM;
    460       hints.ai_protocol = 0;
    461       error = getaddrinfo(host, optport , &hints, &dst);
    462       if (error) {
    463 	fprintf(stderr,"No such host: %s\n", whoishost);
    464 	if (verb) fprintf(stderr, "Now I give up ...\n");
    465 	perror("Unknown host");
    466 	exit(1);
    467       }
    468 
    469 #ifdef CLEVER
    470     }
    471 #endif
    472   }
    473   else {
    474     if (verb)
    475       fprintf(stderr, "Trying: %s\n\n", host);
    476     memset(&hints, 0, sizeof(hints));
    477     hints.ai_flags = AI_CANONNAME;
    478     hints.ai_family = af;
    479     hints.ai_socktype = SOCK_STREAM;
    480     hints.ai_protocol = 0;
    481     error = getaddrinfo(host, optport, &hints, &dst);
    482     if (error) {
    483       (void)fprintf(stderr, "whois: %s: ", host);
    484       perror("Unknown host");
    485       exit(1);
    486     }
    487   }
    488 
    489   for (/*nothing*/; dst; dst = dst->ai_next) {
    490     s = socket(dst->ai_family, dst->ai_socktype, dst->ai_protocol);
    491     if (s < 0)
    492       continue;
    493     if (connect(s, dst->ai_addr, dst->ai_addrlen) < 0) {
    494       close(s);
    495       if (verb) (void)fprintf(stderr, "whois: connect miss\n");
    496       continue;
    497     }
    498     /*okay*/
    499     break;
    500   }
    501   if (dst == NULL) {
    502     perror("whois: connect");
    503     exit(1);
    504   }
    505   if (verb) (void)fprintf(stderr, "whois: connect success\n");
    506 
    507 #ifndef NETWORKUPDATE
    508   sfi = fdopen(s, "r");
    509   sfo = fdopen(s, "w");
    510   if (sfi == NULL || sfo == NULL) {
    511     perror("whois: fdopen");
    512     (void)close(s);
    513     exit(1);
    514   }
    515 #endif
    516 
    517   signal(SIGTERM, termhandler);
    518 
    519 #ifdef RIPE
    520 #ifdef NETWORKUPDATE
    521 
    522   if ((child=fork())==0) {
    523 
    524      sfo = fdopen(s, "w");
    525      if (sfo == NULL) {
    526        perror("whois: fdopen");
    527        (void)close(s);
    528        exit(1);
    529      }
    530 
    531      if (gethostname(domainname, sizeof(domainname))) {
    532         fprintf(stderr, "error when doing gethostname()");
    533         exit(-1);
    534      }
    535 
    536      passwdentry=getpwuid(getuid());
    537 
    538      fprintf(sfo, "-Vnc2.0 -U %s %s\n", passwdentry->pw_name, domainname);
    539      fflush(sfo);
    540 
    541      prev='\0';
    542 
    543      while ((ch=getchar()) != EOF) {
    544 
    545         fputc(ch, sfo);
    546 
    547         if (ch=='\n') fflush(sfo);
    548         if (feof(sfo)) closesocket(s, child);
    549         if ((ch=='.') && (prev=='\n')) closesocket(s, child);
    550         if (!isspace(ch) || ((!isspace(prev)) && (ch=='\n'))) prev=ch;
    551      }
    552 
    553      closesocket(s, child);
    554 
    555   }
    556 
    557   sfi = fdopen(s, "r");
    558   if (sfi == NULL) {
    559        perror("whois: fdopen");
    560        (void)close(s);
    561        exit(1);
    562   }
    563 
    564 #else
    565 
    566   if (alldatabases)
    567     (void)fprintf(sfo, "-a ");
    568   if (optchanged)
    569     (void)fprintf(sfo, "-c ");
    570   if (optfast)
    571     (void)fprintf(sfo, "-F ");
    572   if (optgetupdates)
    573     (void)fprintf(sfo, "-g %s ", getupdates);
    574   if (optinverselookup)
    575     (void)fprintf(sfo, "-i %s ", inverselookup);
    576   if (optL)
    577     (void)fprintf(sfo, "-L ");
    578   if (optm)
    579     (void)fprintf(sfo, "-m ");
    580   if (optM)
    581     (void)fprintf(sfo, "-M ");
    582   if (optrecur)
    583     (void)fprintf(sfo, "-r ");
    584   if (optsource)
    585     (void)fprintf(sfo, "-s %s ", source);
    586   if (optsugar)
    587     (void)fprintf(sfo, "-S ");
    588   if (optnonreferral)
    589     (void)fprintf(sfo, "-R ");
    590   if (opttempl)
    591     (void)fprintf(sfo, "-t %s ", templ);
    592   if (optverbose)
    593     (void)fprintf(sfo, "-v %s ", verbose);
    594   if (optobjtype)
    595     (void)fprintf(sfo, "-T %s ", objtype);
    596 
    597   /* we can only send the -V when we are sure that we are dealing with
    598      a RIPE whois server :-( */
    599 
    600   whoishost=(char *)calloc(strlen(host)+1, sizeof(char));
    601   strcpy(whoishost, host);
    602   for (string=whoishost;(*string=(char)tolower(*string));string++);
    603 
    604   if (strstr(whoishost, "ripe.net") ||
    605       strstr(whoishost, "ra.net") ||
    606       strstr(whoishost, "apnic.net") ||
    607       strstr(whoishost, "mci.net") ||
    608       strstr(whoishost, "isi.edu") ||
    609       strstr(whoishost, "garr.it") ||
    610       strstr(whoishost, "ans.net") ||
    611       alldatabases || optfast || optgetupdates || optinverselookup ||
    612       optL || optm || optM || optrecur || optsugar || optsource ||
    613       opttempl || optverbose || optobjtype)
    614     (void)fprintf(sfo, "-VwC2.0 ");
    615 #endif
    616 #endif
    617 
    618 #ifndef NETWORKUPDATE
    619   while (argc-- > 1)
    620     (void)fprintf(sfo, "%s ", *argv++);
    621    if (*argv) (void)fputs(*argv, sfo);
    622    (void)fputs("\r\n", sfo);
    623   (void)fflush(sfo);
    624 #endif
    625 
    626   while ((ch = getc(sfi)) != EOF)
    627     putchar(ch);
    628 
    629   closesocket(s, 1);
    630 
    631   exit(0);
    632 
    633 }
    634