dnsserver.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:8k
- /*
- * $Id: dnsserver.c,v 1.56 1999/01/13 23:24:12 wessels Exp $
- *
- * DEBUG: section 0 DNS Resolver
- * AUTHOR: Harvest Derived
- *
- * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from the
- * Internet community. Development is led by Duane Wessels of the
- * National Laboratory for Applied Network Research and funded by the
- * National Science Foundation. Squid is Copyrighted (C) 1998 by
- * Duane Wessels and the University of California San Diego. Please
- * see the COPYRIGHT file for full details. Squid incorporates
- * software developed and/or copyrighted by other sources. Please see
- * the CREDITS file for full details.
- *
- * 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, USA.
- *
- */
- #include "config.h"
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #if HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #if HAVE_STDIO_H
- #include <stdio.h>
- #endif
- #if HAVE_SYS_TYPES_H
- #include <sys/types.h>
- #endif
- #if HAVE_CTYPE_H
- #include <ctype.h>
- #endif
- #if HAVE_ERRNO_H
- #include <errno.h>
- #endif
- #if HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #if HAVE_GRP_H
- #include <grp.h>
- #endif
- #if HAVE_GNUMALLOC_H
- #include <gnumalloc.h>
- #elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)
- #include <malloc.h>
- #endif
- #if HAVE_MEMORY_H
- #include <memory.h>
- #endif
- #if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_) /* protect NEXTSTEP */
- #define _SQUID_NETDB_H_
- #include <netdb.h>
- #endif
- #if HAVE_PWD_H
- #include <pwd.h>
- #endif
- #if HAVE_SIGNAL_H
- #include <signal.h>
- #endif
- #if HAVE_TIME_H
- #include <time.h>
- #endif
- #if HAVE_SYS_PARAM_H
- #include <sys/param.h>
- #endif
- #if HAVE_SYS_TIME_H
- #include <sys/time.h>
- #endif
- #if HAVE_SYS_RESOURCE_H
- #include <sys/resource.h> /* needs sys/time.h above it */
- #endif
- #if HAVE_SYS_SOCKET_H
- #include <sys/socket.h>
- #endif
- #if HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #endif
- #if HAVE_ARPA_INET_H
- #include <arpa/inet.h>
- #endif
- #if HAVE_SYS_STAT_H
- #include <sys/stat.h>
- #endif
- #if HAVE_SYS_UN_H
- #include <sys/un.h>
- #endif
- #if HAVE_SYS_WAIT_H
- #include <sys/wait.h>
- #endif
- #if HAVE_LIBC_H
- #include <libc.h>
- #endif
- #ifdef HAVE_SYS_SYSCALL_H
- #include <sys/syscall.h>
- #endif
- #ifdef HAVE_STRING_H
- #include <string.h>
- #endif
- #ifdef HAVE_STRINGS_H
- #include <strings.h>
- #endif
- #if HAVE_BSTRING_H
- #include <bstring.h>
- #endif
- #ifdef HAVE_CRYPT_H
- #include <crypt.h>
- #endif
- #if HAVE_SYS_SELECT_H
- #include <sys/select.h>
- #endif
- #if HAVE_ARPA_NAMESER_H
- #include <arpa/nameser.h>
- #endif
- #if HAVE_RESOLV_H
- #include <resolv.h>
- #endif
- #include "util.h"
- #include "snprintf.h"
- #if !defined(_SQUID_AIX_)
- extern int h_errno;
- #endif
- #if LIBRESOLV_DNS_TTL_HACK
- extern int _dns_ttl_; /* this is a really *dirty* hack - bne */
- #endif
- #ifdef _SQUID_NEXT_
- /* This is a really bloody hack. frank@langen.bull.de
- * Workaround bug in gethostbyname which sets h_errno wrong
- * WARNING: This hack queries only the resolver and not NetInfo or YP
- */
- struct hostent *_res_gethostbyname(char *name);
- #define gethostbyname _res_gethostbyname
- #endif /* _SQUID_NEXT_ */
- static struct in_addr no_addr;
- #ifdef _SQUID_OS2_
- struct state _res =
- {0}; /* it's not in any of the libraries */
- #endif
- /* error messages from gethostbyname() */
- static char *
- my_h_msgs(int x)
- {
- if (x == HOST_NOT_FOUND)
- return "Host not found (authoritative)";
- else if (x == TRY_AGAIN)
- return "Host not found (non-authoritative)";
- else if (x == NO_RECOVERY)
- return "Non recoverable errors";
- else if (x == NO_DATA || x == NO_ADDRESS)
- return "Valid name, no data record of requested type";
- else
- return "Unknown DNS problem";
- }
- #define REQ_SZ 512
- static void
- lookup(const char *buf)
- {
- const struct hostent *result = NULL;
- int reverse = 0;
- int ttl = 0;
- int retry = 0;
- int i;
- struct in_addr addr;
- if (0 == strcmp(buf, "$shutdown"))
- exit(0);
- if (0 == strcmp(buf, "$hello")) {
- printf("$aliven");
- return;
- }
- /* check if it's already an IP address in text form. */
- for (;;) {
- if (safe_inet_addr(buf, &addr)) {
- reverse = 1;
- result = gethostbyaddr((char *) &addr.s_addr, 4, AF_INET);
- } else {
- result = gethostbyname(buf);
- }
- if (NULL != result)
- break;
- if (h_errno != TRY_AGAIN)
- break;
- if (++retry == 3)
- break;
- sleep(1);
- }
- if (NULL == result) {
- if (h_errno == TRY_AGAIN) {
- printf("$fail Name Server for domain '%s' is unavailable.n", buf);
- } else {
- printf("$fail DNS Domain '%s' is invalid: %s.n",
- buf, my_h_msgs(h_errno));
- }
- return;
- }
- #if LIBRESOLV_DNS_TTL_HACK
- /* DNS TTL handling - bne@CareNet.hu
- * for first try it's a dirty hack, by hacking getanswer
- * to place the ttl in a global variable */
- if (_dns_ttl_ > -1)
- ttl = _dns_ttl_;
- #endif
- if (reverse) {
- printf("$name %d %sn", ttl, result->h_name);
- return;
- }
- printf("$addr %d", ttl);
- for (i = 0; NULL != result->h_addr_list[i]; i++) {
- if (32 == i)
- break;
- xmemcpy(&addr, result->h_addr_list[i], sizeof(addr));
- printf(" %s", inet_ntoa(addr));
- }
- printf("n");
- }
- static void
- usage(void)
- {
- fprintf(stderr, "usage: dnsserver -Dhv -s nameservern"
- "t-D Enable resolver RES_DEFNAMES and RES_DNSRCH optionsn"
- "t-h Helpn"
- "t-v Versionn"
- "t-s nameserver Specify alternate name server(s). 'nameserver'n"
- "t must be an IP address, -s option may be repeatedn");
- }
- int
- main(int argc, char *argv[])
- {
- char request[512];
- char *t = NULL;
- int c;
- int opt_s = 0;
- extern char *optarg;
- safe_inet_addr("255.255.255.255", &no_addr);
- #if HAVE_RES_INIT
- res_init();
- #ifdef RES_DEFAULT
- _res.options = RES_DEFAULT;
- #endif
- #ifdef RES_DEFNAMES
- _res.options &= ~RES_DEFNAMES;
- #endif
- #ifdef RES_DNSRCH
- _res.options &= ~RES_DNSRCH;
- #endif
- #endif
- while ((c = getopt(argc, argv, "Dhs:v")) != -1) {
- switch (c) {
- case 'D':
- #ifdef RES_DEFNAMES
- _res.options |= RES_DEFNAMES;
- #endif
- #ifdef RES_DNSRCH
- _res.options |= RES_DNSRCH;
- #endif
- break;
- case 's':
- #if HAVE_RES_INIT
- if (opt_s == 0) {
- _res.nscount = 0;
- /*
- * Setting RES_INIT here causes coredumps when -s is
- * used with -D option. It looks to me like setting
- * RES_INIT is wrong. The resolver code sets RES_INIT
- * after calling res_init(). When we change the _res
- * structure and set RES_INIT, some internal resolver
- * structures get confused. -DW 2.1.p1
- */
- #if SEEMS_WRONG
- _res.options |= RES_INIT;
- #endif
- opt_s = 1;
- } else if (_res.nscount == MAXNS) {
- fprintf(stderr, "Too many -s options, only %d are allowedn",
- MAXNS);
- break;
- }
- #if HAVE_RES_NSADDR_LIST
- _res.nsaddr_list[_res.nscount] = _res.nsaddr_list[0];
- safe_inet_addr(optarg, &_res.nsaddr_list[_res.nscount++].sin_addr);
- #elif HAVE_RES_NS_LIST
- _res.ns_list[_res.nscount] = _res.ns_list[0];
- safe_inet_addr(optarg, &_res.ns_list[_res.nscount++].addr.sin_addr);
- #else /* Unknown NS list format */
- fprintf(stderr, "-s is not supported on this resolvern");
- #endif
- #else /* !HAVE_RES_INIT */
- fprintf(stderr, "-s is not supported on this resolvern");
- #endif /* HAVE_RES_INIT */
- break;
- case 'v':
- printf("dnsserver version %sn", SQUID_VERSION);
- exit(0);
- break;
- case 'h':
- default:
- usage();
- exit(1);
- break;
- }
- }
- for (;;) {
- memset(request, ' ', REQ_SZ);
- if (fgets(request, REQ_SZ, stdin) == NULL)
- exit(1);
- t = strrchr(request, 'n');
- if (t == NULL) /* Ignore if no newline */
- continue;
- *t = ' '; /* strip NL */
- if ((t = strrchr(request, 'r')) != NULL)
- *t = ' '; /* strip CR */
- lookup(request);
- fflush(stdout);
- }
- /* NOTREACHED */
- return 0;
- }