hostname.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /*
  17.   Get hostname for an IP.  Hostnames are checked with reverse name lookup and
  18.   checked that they doesn't resemble an ip.
  19. */
  20. #include "mysql_priv.h"
  21. #include "hash_filo.h"
  22. #include <m_ctype.h>
  23. #ifdef __cplusplus
  24. extern "C" { // Because of SCO 3.2V4.2
  25. #endif
  26. #ifndef __WIN__
  27. #include <sys/resource.h>
  28. #ifdef HAVE_SYS_UN_H
  29. #include <sys/un.h>
  30. #endif
  31. #include <netdb.h>
  32. #include <sys/utsname.h>
  33. #endif // __WIN__
  34. #ifdef __cplusplus
  35. }
  36. #endif
  37. class host_entry :public hash_filo_element
  38. {
  39. public:
  40.   char  ip[sizeof(((struct in_addr *) 0)->s_addr)];
  41.   uint  errors;
  42.   char  *hostname;
  43. };
  44. static hash_filo *hostname_cache;
  45. static pthread_mutex_t LOCK_hostname;
  46. void hostname_cache_refresh()
  47. {
  48.   hostname_cache->clear();
  49. }
  50. bool hostname_cache_init()
  51. {
  52.   (void) pthread_mutex_init(&LOCK_hostname,NULL);
  53.   if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE,offsetof(host_entry,ip),
  54.      sizeof(struct in_addr),NULL,
  55.      (void (*)(void*)) free)))
  56.     return 1;
  57.   hostname_cache->clear();
  58.   return 0;
  59. }
  60. void hostname_cache_free()
  61. {
  62.   (void) pthread_mutex_destroy(&LOCK_hostname);
  63.   delete hostname_cache;
  64. }
  65. static void add_hostname(struct in_addr *in,const char *name)
  66. {
  67.   if (!(specialflag & SPECIAL_NO_HOST_CACHE))
  68.   {
  69.     VOID(pthread_mutex_lock(&hostname_cache->lock));
  70.     host_entry *entry;
  71.     if (!(entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0)))
  72.     {
  73.       uint length=name ? (uint) strlen(name) : 0;
  74.       if ((entry=(host_entry*) malloc(sizeof(host_entry)+length+1)))
  75.       {
  76. char *new_name;
  77. memcpy_fixed(&entry->ip, &in->s_addr, sizeof(in->s_addr));
  78. if (length)
  79.   memcpy(new_name= (char *) (entry+1), name, length+1);
  80. else
  81.   new_name=0;
  82. entry->hostname=new_name;
  83. entry->errors=0;
  84. (void) hostname_cache->add(entry);
  85.       }
  86.     }
  87.     VOID(pthread_mutex_unlock(&hostname_cache->lock));
  88.   }
  89. }
  90. inline void add_wrong_ip(struct in_addr *in)
  91. {
  92.   add_hostname(in,NullS);
  93. }
  94. void inc_host_errors(struct in_addr *in)
  95. {
  96.   VOID(pthread_mutex_lock(&hostname_cache->lock));
  97.   host_entry *entry;
  98.   if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0)))
  99.     entry->errors++;
  100.   VOID(pthread_mutex_unlock(&hostname_cache->lock));
  101. }
  102. void reset_host_errors(struct in_addr *in)
  103. {
  104.   VOID(pthread_mutex_lock(&hostname_cache->lock));
  105.   host_entry *entry;
  106.   if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0)))
  107.     entry->errors=0;
  108.   VOID(pthread_mutex_unlock(&hostname_cache->lock));
  109. }
  110. my_string ip_to_hostname(struct in_addr *in, uint *errors)
  111. {
  112.   uint i;
  113.   host_entry *entry;
  114.   DBUG_ENTER("ip_to_hostname");
  115.   /* Check first if we have name in cache */
  116.   *errors=0;
  117.   if (!(specialflag & SPECIAL_NO_HOST_CACHE))
  118.   {
  119.     VOID(pthread_mutex_lock(&hostname_cache->lock));
  120.     if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0)))
  121.     {
  122.       char *name;
  123.       if (!entry->hostname)
  124. name=0; // Don't allow connection
  125.       else
  126. name=my_strdup(entry->hostname,MYF(0));
  127.       *errors= entry->errors;
  128.       VOID(pthread_mutex_unlock(&hostname_cache->lock));
  129.       DBUG_RETURN(name);
  130.     }
  131.     VOID(pthread_mutex_unlock(&hostname_cache->lock));
  132.   }
  133.   struct hostent *hp, *check;
  134.   char *name;
  135.   LINT_INIT(check);
  136. #if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
  137.   char buff[GETHOSTBYADDR_BUFF_SIZE],buff2[GETHOSTBYNAME_BUFF_SIZE];
  138.   int tmp_errno;
  139.   struct hostent tmp_hostent, tmp_hostent2;
  140. #ifdef HAVE_purify
  141.   bzero(buff,sizeof(buff)); // Bug in purify
  142. #endif
  143.   if (!(hp=gethostbyaddr_r((char*) in,sizeof(*in),
  144.    AF_INET,
  145.    &tmp_hostent,buff,sizeof(buff),&tmp_errno)))
  146.   {
  147.     DBUG_PRINT("error",("gethostbyaddr_r returned %d",tmp_errno));
  148.     return 0;
  149.   }
  150.   if (!(check=my_gethostbyname_r(hp->h_name,&tmp_hostent2,buff2,sizeof(buff2),
  151.  &tmp_errno)))
  152.   {
  153.     DBUG_PRINT("error",("gethostbyname_r returned %d",tmp_errno));
  154.     add_wrong_ip(in);
  155.     DBUG_RETURN(0);
  156.   }
  157.   if (!hp->h_name[0])
  158.   {
  159.     DBUG_PRINT("error",("Got an empty hostname"));
  160.     add_wrong_ip(in);
  161.     DBUG_RETURN(0); // Don't allow empty hostnames
  162.   }
  163.   if (!(name=my_strdup(hp->h_name,MYF(0))))
  164.     DBUG_RETURN(0); // out of memory
  165. #else
  166.   VOID(pthread_mutex_lock(&LOCK_hostname));
  167.   if (!(hp=gethostbyaddr((char*) in,sizeof(*in), AF_INET)))
  168.   {
  169.     VOID(pthread_mutex_unlock(&LOCK_hostname));
  170.     DBUG_PRINT("error",("gethostbyaddr returned %d",errno));
  171.     goto err;
  172.   }
  173.   if (!hp->h_name[0]) // Don't allow empty hostnames
  174.   {
  175.     VOID(pthread_mutex_unlock(&LOCK_hostname));
  176.     DBUG_PRINT("error",("Got an empty hostname"));
  177.     goto err;
  178.   }
  179.   if (!(name=my_strdup(hp->h_name,MYF(0))))
  180.   {
  181.     VOID(pthread_mutex_unlock(&LOCK_hostname));
  182.     DBUG_RETURN(0); // out of memory
  183.   }
  184.   check=gethostbyname(name);
  185.   VOID(pthread_mutex_unlock(&LOCK_hostname));
  186.   if (!check)
  187.   {
  188.     DBUG_PRINT("error",("gethostbyname returned %d",errno));
  189.     my_free(name,MYF(0));
  190.     DBUG_RETURN(0);
  191.   }
  192. #endif
  193.   /* Don't accept hostnames that starts with digits because they may be
  194.      false ip:s */
  195.   if (isdigit(name[0]))
  196.   {
  197.     char *pos;
  198.     for (pos= name+1 ; isdigit(*pos); pos++) ;
  199.     if (*pos == '.')
  200.     {
  201.       DBUG_PRINT("error",("mysqld doesn't accept hostnames that starts with a number followed by a '.'"));
  202.       my_free(name,MYF(0));
  203.       goto err;
  204.     }
  205.   }
  206.   /* Check that 'gethostbyname' returned the used ip */
  207.   for (i=0; check->h_addr_list[i]; i++)
  208.   {
  209.     if (*(uint32*)(check->h_addr_list)[i] == in->s_addr)
  210.     {
  211.       add_hostname(in,name);
  212.       DBUG_RETURN(name);
  213.     }
  214.   }
  215.   DBUG_PRINT("error",("Couldn't verify hostname with gethostbyname"));
  216.   my_free(name,MYF(0));
  217. err:
  218.   add_wrong_ip(in);
  219.   DBUG_RETURN(0);
  220. }