1 /* $NetBSD: whois.c,v 1.12 1999/12/03 08:22:09 fair Exp $ */ 2 3 /* 4 * RIPE version marten@ripe.net 5 * many changes & networkupdate by david@ripe.net 6 * cosmetics by steven@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@ripe.net 13 * "whois.ripe.net" replaced by "bsdbase.ripe.net"; ambrose@ripe.net 14 * "bsdbase.ripe.net" replaced by "joshua.ripe.net"; marek@ripe.net 15 * "joshua.ripe.net" replaced by "whois.ripe.net"; roman@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.12 1999/12/03 08:22:09 fair 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@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.networksolutions.com" 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:")) != EOF) 316 #else 317 while ((ch = getopt(argc, argv, "46acFg:h:i:LmMp:rs:SRt:T:v:")) != EOF) 318 #endif 319 #else 320 while ((ch = getopt(argc, argv, "46h:p:")) != EOF) 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