hostname.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:12k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /* Copyright (c) 1995,1996,1997 NEC Corporation.  All rights reserved.       */
  2. /*                                                                           */
  3. /* The redistribution, use and modification in source or binary forms of     */
  4. /* this software is subject to the conditions set forth in the copyright     */
  5. /* document ("Copyright") included with this distribution.                   */
  6. /*
  7.  * $Id: hostname.c,v 1.31.4.6 1998/11/18 17:39:12 wlu Exp $
  8.  */
  9. #include "socks5p.h"
  10. #include "protocol.h"
  11. #include "addr.h"
  12. #include "wrap.h"
  13. #include "log.h"
  14. #define S5_HOSTLIST_SIZE    256
  15. #define S5_HOSTALIASES_SIZE 16
  16. #define S5_FAKEHOSTFILE     "/.s5fakehost"
  17.  
  18. int lsInWrapHostname = 0;
  19. int fd = -1;
  20. /* local array of host address list and aliases list                         */
  21. static struct in_addr host_addr[S5_HOSTLIST_SIZE];
  22. static char host_aliases[S5_HOSTALIASES_SIZE][S5_HOSTNAME_SIZE];
  23. /* The address of unresolved host will be of the format "0.0.0.i", where i   */
  24. /* ranges from 1 to 254, pretty simple...                                    */
  25. #define FAKEPREFIX "0.0.0."
  26. static int SetReadLock(int lock) {
  27.     struct flock locks;
  28.     locks.l_type = (lock?F_RDLCK:F_UNLCK);
  29.     locks.l_start = 0;
  30.     locks.l_whence = SEEK_SET;
  31.     locks.l_len = 0;
  32.     return fcntl(fd, F_SETLKW, &locks);
  33. }
  34. static int SetWriteLock(int lock) {
  35.     struct flock locks;
  36.     locks.l_type = (lock?F_WRLCK:F_UNLCK);
  37.     locks.l_start = 0;
  38.     locks.l_whence = SEEK_SET;
  39.     locks.l_len = 0;
  40.     return fcntl(fd, F_SETLKW, &locks);
  41. }
  42. #define S_ISRW(mode) (((mode)&(S_IREAD | S_IWRITE)) == (S_IREAD | S_IWRITE))
  43. static void FakeHostInit(void) {
  44.     int i, j, flags;
  45.     struct stat sbuf;
  46.     char filename[1024], hostname[S5_HOSTNAME_SIZE], *tmp;
  47.     if (fd > 0) return;
  48.     if ((tmp = getenv("HOME"))) {
  49.         i = MIN(strlen(tmp)+1, sizeof(filename));
  50.         strncpy(filename, tmp, i);
  51.         filename[i-1] = '';
  52.     } else strcpy(filename, "/tmp");
  53.     j = strlen(filename);
  54.     i = MIN(strlen(S5_FAKEHOSTFILE)+1, sizeof(filename)-j);
  55.     strncat(filename, S5_FAKEHOSTFILE, i);
  56.     filename[i+j-1] = '';
  57.     if (!lstat(filename, &sbuf)) {
  58. if (sbuf.st_size != 255*sizeof(hostname)+sizeof(int) || !S_ISRW(sbuf.st_mode)) {
  59.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "FakeHostInit: fakehost file (%s) has been changed", filename);
  60.     flags = O_RDWR | O_CREAT | O_TRUNC | O_EXCL;
  61. } else if (S_ISLNK(sbuf.st_mode) && geteuid() != sbuf.st_uid) {
  62.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "FakeHostInit: fakehost file (%s) is a link", filename);
  63.     flags = O_RDWR | O_CREAT | O_TRUNC | O_EXCL;
  64. } else flags = O_RDWR;
  65.     } else flags = O_RDWR | O_CREAT | O_TRUNC | O_EXCL;
  66.     while ((fd = open(filename, flags, 0600)) < 0) {
  67. if (errno != EINTR && errno != EAGAIN) {
  68.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "FakeHostInit: open fakehost file (%s) failed %m", filename);
  69.     return;
  70. }
  71.     }
  72.     if (!(flags & O_CREAT)) return;
  73.     SetWriteLock(1);
  74.     i = 0;
  75.     j = sizeof(int);
  76.     lseek(fd, 0, SEEK_SET);
  77.     if (REAL(write)(fd, (char *)&i, j) != j) {
  78.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "FakeHostInit: write fakehost file failed %m");
  79.         REAL(close)(fd);
  80.         fd = -1;
  81.         return;
  82.     }
  83.     memset(hostname, 0, sizeof(hostname));
  84.     for (i = 0; i < 255; i++) {
  85.         if (REAL(write)(fd, hostname, sizeof(hostname)) != sizeof(hostname)) {
  86.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "FakeHostInit: write fakehost file failed %m");
  87.             REAL(close)(fd);
  88.             fd = -1;
  89.             return;
  90.         }
  91.     }
  92.     SetWriteLock(0);
  93. }
  94. static int GetFakeHost(const char *name) {
  95.     int i, j;
  96.     char hostname[S5_HOSTNAME_SIZE];
  97.     FakeHostInit();
  98.     if (fd <= 0) return -1;
  99.     SetWriteLock(1);
  100.     lseek(fd, 0, SEEK_SET);
  101.     i = 0;
  102.     if (REAL(read)(fd, (char *)&i, sizeof(int)) != sizeof(int)) {
  103.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "GetFakeHost: read table failed %m");
  104.         SetWriteLock(0);
  105.         return -1;
  106.     }
  107.     for (j = 1; j < 256; j++) {
  108.         if (REAL(read)(fd, hostname, sizeof(hostname)) != sizeof(hostname)) {
  109.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "GetFakeHost: read table failed %m");
  110.             SetWriteLock(0);
  111.             return -1;
  112.         }
  113.         if (hostname[0] == '' || !strcasecmp(name, hostname)) break;
  114.     }
  115.     if (j == 256 || hostname[0] == '') {
  116.         i++;
  117.         if (i == 256) {
  118.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(20), 0, "GetFakeHost: FAKE table is recycled");
  119.             i = 1;
  120.             j = i;
  121.         } else j = i;
  122.         lseek(fd, 0, SEEK_SET);
  123.         if (REAL(write)(fd, (char *)&i, sizeof(int)) != sizeof(int)) {
  124.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "GetFakeHost: write table failed %m");
  125.             SetWriteLock(0);
  126.             return -1;
  127.         }
  128.         memset(hostname, 0, sizeof(hostname));
  129.         strncpy(hostname, name, MIN(strlen(name), S5_HOSTNAME_SIZE-1));
  130.         hostname[MIN(strlen(name), S5_HOSTNAME_SIZE-1)] = '';
  131.         lseek(fd, (j-1)*S5_HOSTNAME_SIZE+sizeof(int), SEEK_SET);
  132.         if (REAL(write)(fd, hostname, sizeof(hostname)) != sizeof(hostname)) {
  133.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "GetFakeHost: write table failed %m");
  134.             SetWriteLock(0);
  135.             return -1;
  136.         }
  137.     }
  138.     SetWriteLock(0);
  139.     return j;
  140. }
  141. static void HostentCopy(struct in_addr **addr_list, char **aliases, const struct hostent *h) {
  142.     int i;
  143.     for (i = 0; i < S5_HOSTALIASES_SIZE; i++) {
  144. if (h->h_aliases[i] == NULL) break;
  145. strncpy(host_aliases[i], h->h_aliases[i], MIN(strlen(h->h_aliases[i]), S5_HOSTNAME_SIZE-1));
  146. host_aliases[i][MIN(strlen(h->h_aliases[i]), S5_HOSTNAME_SIZE-1)] = '';
  147. aliases[i] = (char *)host_aliases[i];
  148.     }
  149.     aliases[i] = NULL;
  150.     for (i = 0; i < S5_HOSTLIST_SIZE; i++) {
  151. if (h->h_addr_list[i] == NULL) break;
  152. memcpy((char *)&host_addr[i], h->h_addr_list[i], sizeof(struct in_addr));
  153. addr_list[i] = &host_addr[i];
  154.     }
  155.     addr_list[i] = NULL;
  156. }
  157. /* wrapper around the gethostbyname call.                                    */
  158. /* similar to gethostbyname() except for:                                    */
  159. /* *** if gethostbyname() fails, then it returns a pointer to a hostent      */
  160. /*     structure filled with a special value, so that SOCKSxxxxxx() will     */
  161. /*     realize that this host was unresolved and fill in the protocol        */
  162. /*     accordingly...                                                        */
  163. /*                                                                           */
  164. /* returns a pointer to a gethostent structure on success; NULL on failure   */
  165. struct hostent *LIBPREFIX(gethostbyname)(const char *name) {
  166.     static struct in_addr special_addr, *my_addr_list[S5_HOSTLIST_SIZE+1];
  167.     static char my_name[MAXNAMELEN], *my_aliases[S5_HOSTALIASES_SIZE+1];
  168.     static struct hostent h;
  169.     struct hostent *hp;
  170.     char *local, *fake;
  171.     int hlen, i;
  172. #ifdef FOR_SHARED_LIBRARY
  173.     if (lsInRLDFunctions || lsInWrapFunction || lsInWrapHostname) return REAL(gethostbyname)(name);
  174. #endif
  175.     lsInWrapFunction = 1;
  176.     lsInWrapHostname = 1;
  177.     LIBPREFIX2(init)("libsocks5");
  178.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS gethostbyname: looking up %s", name);
  179.     fake  = getenv("SOCKS5_FAKEALLHOSTS");
  180.     local = getenv("SOCKS5_LOCALDNSONLY");
  181.     if (!fake && (hp = REAL(gethostbyname)(name)) != NULL) {
  182. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS gethostbyname: REAL: %s", inet_ntoa(*(struct in_addr *)hp->h_addr));
  183.         hlen = MIN(strlen(hp->h_name)+1, sizeof(my_name));
  184.         strncpy(my_name, hp->h_name, hlen);
  185.         if (hlen == sizeof(my_name)) my_name[hlen-1] = '';
  186. HostentCopy(my_addr_list, my_aliases, hp);
  187.      h.h_name      = my_name;
  188.      h.h_aliases   = my_aliases;
  189.      h.h_addrtype  = hp->h_addrtype;
  190.      h.h_length    = hp->h_length;
  191.      h.h_addr_list = (char **)my_addr_list;
  192.         lsInWrapFunction = 0;
  193.         lsInWrapHostname = 0;
  194. return &h;
  195.     }
  196.     /* If your DNS is the same as the socks server, don't fake a correct     */
  197.     /* lookup when you know it won't work...                                 */
  198.     if (local) {
  199. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS gethostbyname: REAL: Fake not configured");
  200.         lsInWrapFunction = 0;
  201.         lsInWrapHostname = 0;
  202. return NULL;
  203.     }
  204.     /* Fill in some UNRESOLVED values and let the daemon resolve it          */
  205.     if ((i = GetFakeHost(name)) <= 0) {
  206.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "SOCKS gethostbyname: Get fake host failed");
  207.         lsInWrapFunction = 0;
  208.         lsInWrapHostname = 0;
  209.         return NULL;
  210.     }
  211.     hlen = MIN(strlen(name)+1, sizeof(my_name));
  212.     strncpy(my_name, name, hlen);
  213.     if (hlen == sizeof(my_name)) my_name[hlen-1] = '';
  214.     my_aliases[0] = NULL;
  215.     special_addr.s_addr = htonl(i);
  216.     my_addr_list[0] = &special_addr;
  217.     my_addr_list[1] = NULL;
  218.     h.h_name      = my_name;
  219.     h.h_aliases   = my_aliases;
  220.     h.h_addrtype  = AF_INET;
  221.     h.h_length    = sizeof(struct in_addr);
  222.     h.h_addr_list = (char **)my_addr_list;
  223.     
  224.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS gethostbyname: FAKE: %s",  inet_ntoa(*(struct in_addr *)h.h_addr_list[0]));
  225.     lsInWrapFunction = 0;
  226.     lsInWrapHostname = 0;
  227.     return &h;
  228. }
  229. int lsGetCachedAddress(const char *name, S5NetAddr *na) {
  230.     int i;
  231.     char hostname[S5_HOSTNAME_SIZE];
  232.     if (fd > 0) {
  233.         SetReadLock(1);
  234.         lseek(fd, sizeof(int), SEEK_SET);
  235.         for (i = 1; i < 256; i++) {
  236.             if (REAL(read)(fd, hostname, sizeof(hostname)) != sizeof(hostname)) {
  237.                 S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "lsGetCachedAddress: read fake table failed %m");
  238.                 SetReadLock(0);
  239.                 return -1;
  240.             }
  241.             if (hostname[0] == '') {
  242.                 SetReadLock(0);
  243.                 return -1;
  244.             }
  245.             if (strcasecmp(name, hostname)) continue;
  246.             SetReadLock(0);
  247.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(20), 0, "lsGetCachedAddress: Faked host #%d, name is: %s", i, hostname);
  248.             memset(&na->sin, 0, sizeof(ssi));
  249.             na->sin.sin_family      = AF_INET;
  250.             na->sin.sin_port        = 0;
  251.             na->sin.sin_addr.s_addr = htonl(i);
  252.             return 0;
  253.         }
  254.     }
  255.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsGetCachedAddress: Not a fake a hostname: %s", name);
  256.     return -1;
  257. }
  258. /* checks if the address is an unresolved-address and if so, returns the     */
  259. /* unresolved hostname else returns NULL                                     */
  260. int lsGetCachedHostname(const S5NetAddr *na, char *hostname, int len) {
  261.     int i;
  262.     if (!na || !hostname) return -1;
  263.     if ((i = (int)ntohl(na->sin.sin_addr.s_addr)) > 255 || i < 1) {
  264.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(20), 0, "lsGetCachedHostname: Not a fake hostname: %s", inet_ntoa(na->sin.sin_addr));
  265.         return -1;
  266.     }
  267.     if (fd > 0) {
  268.         SetReadLock(1);
  269.         lseek(fd, (i-1)*S5_HOSTNAME_SIZE+sizeof(int), SEEK_SET);
  270.         if (REAL(read)(fd, hostname, len) != len) {
  271.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "lsGetCachedHostname: read fake table failed %m");
  272.             SetReadLock(0);
  273.             return -1;
  274.         }
  275.         SetReadLock(0);
  276.         if (!*hostname) return -1;
  277.         hostname[len - 1] = '';
  278.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(20), 0, "lsGetCachedHostname: Faked host #%d, name is: %s", i, hostname);
  279.         return 0;
  280.     }
  281.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsGetCachedHostname: Not a fake hostname: %s", inet_ntoa(na->sin.sin_addr));
  282.     return -1;
  283. }