dnsserver.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:8k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: dnsserver.c,v 1.56 1999/01/13 23:24:12 wessels Exp $
  3.  *
  4.  * DEBUG: section 0     DNS Resolver
  5.  * AUTHOR: Harvest Derived
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "config.h"
  35. #if HAVE_UNISTD_H
  36. #include <unistd.h>
  37. #endif
  38. #if HAVE_STDLIB_H
  39. #include <stdlib.h>
  40. #endif
  41. #if HAVE_STDIO_H
  42. #include <stdio.h>
  43. #endif
  44. #if HAVE_SYS_TYPES_H
  45. #include <sys/types.h>
  46. #endif
  47. #if HAVE_CTYPE_H
  48. #include <ctype.h>
  49. #endif
  50. #if HAVE_ERRNO_H
  51. #include <errno.h>
  52. #endif
  53. #if HAVE_FCNTL_H
  54. #include <fcntl.h>
  55. #endif
  56. #if HAVE_GRP_H
  57. #include <grp.h>
  58. #endif
  59. #if HAVE_GNUMALLOC_H
  60. #include <gnumalloc.h>
  61. #elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)
  62. #include <malloc.h>
  63. #endif
  64. #if HAVE_MEMORY_H
  65. #include <memory.h>
  66. #endif
  67. #if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_) /* protect NEXTSTEP */
  68. #define _SQUID_NETDB_H_
  69. #include <netdb.h>
  70. #endif
  71. #if HAVE_PWD_H
  72. #include <pwd.h>
  73. #endif
  74. #if HAVE_SIGNAL_H
  75. #include <signal.h>
  76. #endif
  77. #if HAVE_TIME_H
  78. #include <time.h>
  79. #endif
  80. #if HAVE_SYS_PARAM_H
  81. #include <sys/param.h>
  82. #endif
  83. #if HAVE_SYS_TIME_H
  84. #include <sys/time.h>
  85. #endif
  86. #if HAVE_SYS_RESOURCE_H
  87. #include <sys/resource.h> /* needs sys/time.h above it */
  88. #endif
  89. #if HAVE_SYS_SOCKET_H
  90. #include <sys/socket.h>
  91. #endif
  92. #if HAVE_NETINET_IN_H
  93. #include <netinet/in.h>
  94. #endif
  95. #if HAVE_ARPA_INET_H
  96. #include <arpa/inet.h>
  97. #endif
  98. #if HAVE_SYS_STAT_H
  99. #include <sys/stat.h>
  100. #endif
  101. #if HAVE_SYS_UN_H
  102. #include <sys/un.h>
  103. #endif
  104. #if HAVE_SYS_WAIT_H
  105. #include <sys/wait.h>
  106. #endif
  107. #if HAVE_LIBC_H
  108. #include <libc.h>
  109. #endif
  110. #ifdef HAVE_SYS_SYSCALL_H
  111. #include <sys/syscall.h>
  112. #endif
  113. #ifdef HAVE_STRING_H
  114. #include <string.h>
  115. #endif
  116. #ifdef HAVE_STRINGS_H
  117. #include <strings.h>
  118. #endif
  119. #if HAVE_BSTRING_H
  120. #include <bstring.h>
  121. #endif
  122. #ifdef HAVE_CRYPT_H
  123. #include <crypt.h>
  124. #endif
  125. #if HAVE_SYS_SELECT_H
  126. #include <sys/select.h>
  127. #endif
  128. #if HAVE_ARPA_NAMESER_H
  129. #include <arpa/nameser.h>
  130. #endif
  131. #if HAVE_RESOLV_H
  132. #include <resolv.h>
  133. #endif
  134. #include "util.h"
  135. #include "snprintf.h"
  136. #if !defined(_SQUID_AIX_)
  137. extern int h_errno;
  138. #endif
  139. #if LIBRESOLV_DNS_TTL_HACK
  140. extern int _dns_ttl_; /* this is a really *dirty* hack - bne */
  141. #endif
  142. #ifdef _SQUID_NEXT_
  143. /* This is a really bloody hack. frank@langen.bull.de
  144.  * Workaround bug in gethostbyname which sets h_errno wrong
  145.  * WARNING: This hack queries only the resolver and not NetInfo or YP
  146.  */
  147. struct hostent *_res_gethostbyname(char *name);
  148. #define gethostbyname _res_gethostbyname
  149. #endif /* _SQUID_NEXT_ */
  150. static struct in_addr no_addr;
  151. #ifdef _SQUID_OS2_
  152. struct state _res =
  153. {0}; /* it's not in any of the libraries */
  154. #endif
  155. /* error messages from gethostbyname() */
  156. static char *
  157. my_h_msgs(int x)
  158. {
  159.     if (x == HOST_NOT_FOUND)
  160. return "Host not found (authoritative)";
  161.     else if (x == TRY_AGAIN)
  162. return "Host not found (non-authoritative)";
  163.     else if (x == NO_RECOVERY)
  164. return "Non recoverable errors";
  165.     else if (x == NO_DATA || x == NO_ADDRESS)
  166. return "Valid name, no data record of requested type";
  167.     else
  168. return "Unknown DNS problem";
  169. }
  170. #define REQ_SZ 512
  171. static void
  172. lookup(const char *buf)
  173. {
  174.     const struct hostent *result = NULL;
  175.     int reverse = 0;
  176.     int ttl = 0;
  177.     int retry = 0;
  178.     int i;
  179.     struct in_addr addr;
  180.     if (0 == strcmp(buf, "$shutdown"))
  181. exit(0);
  182.     if (0 == strcmp(buf, "$hello")) {
  183. printf("$aliven");
  184. return;
  185.     }
  186.     /* check if it's already an IP address in text form. */
  187.     for (;;) {
  188. if (safe_inet_addr(buf, &addr)) {
  189.     reverse = 1;
  190.     result = gethostbyaddr((char *) &addr.s_addr, 4, AF_INET);
  191. } else {
  192.     result = gethostbyname(buf);
  193. }
  194. if (NULL != result)
  195.     break;
  196. if (h_errno != TRY_AGAIN)
  197.     break;
  198. if (++retry == 3)
  199.     break;
  200. sleep(1);
  201.     }
  202.     if (NULL == result) {
  203. if (h_errno == TRY_AGAIN) {
  204.     printf("$fail Name Server for domain '%s' is unavailable.n", buf);
  205. } else {
  206.     printf("$fail DNS Domain '%s' is invalid: %s.n",
  207. buf, my_h_msgs(h_errno));
  208. }
  209. return;
  210.     }
  211. #if LIBRESOLV_DNS_TTL_HACK
  212.     /* DNS TTL handling - bne@CareNet.hu
  213.      * for first try it's a dirty hack, by hacking getanswer
  214.      * to place the ttl in a global variable */
  215.     if (_dns_ttl_ > -1)
  216. ttl = _dns_ttl_;
  217. #endif
  218.     if (reverse) {
  219. printf("$name %d %sn", ttl, result->h_name);
  220. return;
  221.     }
  222.     printf("$addr %d", ttl);
  223.     for (i = 0; NULL != result->h_addr_list[i]; i++) {
  224. if (32 == i)
  225.     break;
  226. xmemcpy(&addr, result->h_addr_list[i], sizeof(addr));
  227. printf(" %s", inet_ntoa(addr));
  228.     }
  229.     printf("n");
  230. }
  231. static void
  232. usage(void)
  233. {
  234.     fprintf(stderr, "usage: dnsserver -Dhv -s nameservern"
  235. "t-D             Enable resolver RES_DEFNAMES and RES_DNSRCH optionsn"
  236. "t-h             Helpn"
  237. "t-v             Versionn"
  238. "t-s nameserver  Specify alternate name server(s).  'nameserver'n"
  239. "t               must be an IP address, -s option may be repeatedn");
  240. }
  241. int
  242. main(int argc, char *argv[])
  243. {
  244.     char request[512];
  245.     char *t = NULL;
  246.     int c;
  247.     int opt_s = 0;
  248.     extern char *optarg;
  249.     safe_inet_addr("255.255.255.255", &no_addr);
  250. #if HAVE_RES_INIT
  251.     res_init();
  252. #ifdef RES_DEFAULT
  253.     _res.options = RES_DEFAULT;
  254. #endif
  255. #ifdef RES_DEFNAMES
  256.     _res.options &= ~RES_DEFNAMES;
  257. #endif
  258. #ifdef RES_DNSRCH
  259.     _res.options &= ~RES_DNSRCH;
  260. #endif
  261. #endif
  262.     while ((c = getopt(argc, argv, "Dhs:v")) != -1) {
  263. switch (c) {
  264. case 'D':
  265. #ifdef RES_DEFNAMES
  266.     _res.options |= RES_DEFNAMES;
  267. #endif
  268. #ifdef RES_DNSRCH
  269.     _res.options |= RES_DNSRCH;
  270. #endif
  271.     break;
  272. case 's':
  273. #if HAVE_RES_INIT
  274.     if (opt_s == 0) {
  275. _res.nscount = 0;
  276. /*
  277.  * Setting RES_INIT here causes coredumps when -s is
  278.  * used with -D option.  It looks to me like setting
  279.  * RES_INIT is wrong.  The resolver code sets RES_INIT
  280.  * after calling res_init().  When we change the _res
  281.  * structure and set RES_INIT, some internal resolver
  282.  * structures get confused.             -DW 2.1.p1
  283.  */
  284. #if SEEMS_WRONG
  285. _res.options |= RES_INIT;
  286. #endif
  287. opt_s = 1;
  288.     } else if (_res.nscount == MAXNS) {
  289. fprintf(stderr, "Too many -s options, only %d are allowedn",
  290.     MAXNS);
  291. break;
  292.     }
  293. #if HAVE_RES_NSADDR_LIST
  294.     _res.nsaddr_list[_res.nscount] = _res.nsaddr_list[0];
  295.     safe_inet_addr(optarg, &_res.nsaddr_list[_res.nscount++].sin_addr);
  296. #elif HAVE_RES_NS_LIST
  297.     _res.ns_list[_res.nscount] = _res.ns_list[0];
  298.     safe_inet_addr(optarg, &_res.ns_list[_res.nscount++].addr.sin_addr);
  299. #else /* Unknown NS list format */
  300.     fprintf(stderr, "-s is not supported on this resolvern");
  301. #endif
  302. #else /* !HAVE_RES_INIT */
  303.     fprintf(stderr, "-s is not supported on this resolvern");
  304. #endif /* HAVE_RES_INIT */
  305.     break;
  306. case 'v':
  307.     printf("dnsserver version %sn", SQUID_VERSION);
  308.     exit(0);
  309.     break;
  310. case 'h':
  311. default:
  312.     usage();
  313.     exit(1);
  314.     break;
  315. }
  316.     }
  317.     for (;;) {
  318. memset(request, '', REQ_SZ);
  319. if (fgets(request, REQ_SZ, stdin) == NULL)
  320.     exit(1);
  321. t = strrchr(request, 'n');
  322. if (t == NULL) /* Ignore if no newline */
  323.     continue;
  324. *t = ''; /* strip NL */
  325. if ((t = strrchr(request, 'r')) != NULL)
  326.     *t = ''; /* strip CR */
  327. lookup(request);
  328. fflush(stdout);
  329.     }
  330.     /* NOTREACHED */
  331.     return 0;
  332. }