home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / hostname.cpp < prev    next >
C/C++ Source or Header  |  2000-08-31  |  6KB  |  236 lines

  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.  
  18. /*
  19.   Get hostname for an IP.  Hostnames are checked with reverse name lookup and
  20.   checked that they doesn't resemble an ip.
  21. */
  22.  
  23. #include "mysql_priv.h"
  24. #include "hash_filo.h"
  25. #include <m_ctype.h>
  26. #ifdef    __cplusplus
  27. extern "C" {                    // Because of SCO 3.2V4.2
  28. #endif
  29. #ifndef __WIN__
  30. #include <sys/resource.h>
  31. #ifdef HAVE_SYS_UN_H
  32. #include <sys/un.h>
  33. #endif
  34. #include <netdb.h>
  35. #include <sys/utsname.h>
  36. #endif // __WIN__
  37. #ifdef    __cplusplus
  38. }
  39. #endif
  40.  
  41.  
  42. class host_entry :public hash_filo_element
  43. {
  44. public:
  45.   char     ip[sizeof(((struct in_addr *) 0)->s_addr)];
  46.   uint     errors;
  47.   char     *hostname;
  48. };
  49.  
  50. static hash_filo *hostname_cache;
  51.  
  52. void hostname_cache_refresh()
  53. {
  54.   hostname_cache->clear();
  55. }
  56.  
  57. bool hostname_cache_init()
  58. {
  59.   if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE,offsetof(host_entry,ip),
  60.                      sizeof(struct in_addr),NULL,
  61.                      (void (*)(void*)) free)))
  62.     return 1;
  63.   hostname_cache->clear();
  64.   return 0;
  65. }
  66.  
  67. void hostname_cache_free()
  68. {
  69.   delete hostname_cache;
  70. }
  71.  
  72. static void add_hostname(struct in_addr *in,const char *name)
  73. {
  74.   if (!(specialflag & SPECIAL_NO_HOST_CACHE))
  75.   {
  76.     VOID(pthread_mutex_lock(&hostname_cache->lock));
  77.     host_entry *entry;
  78.     if (!(entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0)))
  79.     {
  80.       uint length=name ? (uint) strlen(name) : 0;
  81.  
  82.       if ((entry=(host_entry*) malloc(sizeof(host_entry)+length+1)))
  83.       {
  84.     char *new_name= (char *) (entry+1);
  85.     memcpy_fixed(&entry->ip, &in->s_addr, sizeof(in->s_addr));
  86.     memcpy(new_name, name, length); // Should work even if name == NULL
  87.     new_name[length]=0;        // End of string
  88.     entry->hostname=new_name;
  89.     entry->errors=0;
  90.     (void) hostname_cache->add(entry);
  91.       }
  92.     }
  93.     VOID(pthread_mutex_unlock(&hostname_cache->lock));
  94.   }
  95. }
  96.  
  97.  
  98. static inline void add_wrong_ip(struct in_addr *in)
  99. {
  100.   add_hostname(in,NullS);
  101. }
  102.  
  103. void inc_host_errors(struct in_addr *in)
  104. {
  105.   VOID(pthread_mutex_lock(&hostname_cache->lock));
  106.   host_entry *entry;
  107.   if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0)))
  108.     entry->errors++;
  109.   VOID(pthread_mutex_unlock(&hostname_cache->lock));
  110. }
  111.  
  112. void reset_host_errors(struct in_addr *in)
  113. {
  114.   VOID(pthread_mutex_lock(&hostname_cache->lock));
  115.   host_entry *entry;
  116.   if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0)))
  117.     entry->errors=0;
  118.   VOID(pthread_mutex_unlock(&hostname_cache->lock));
  119. }
  120.  
  121.  
  122. my_string ip_to_hostname(struct in_addr *in, uint *errors)
  123. {
  124.   host_entry *entry;
  125.   DBUG_ENTER("ip_to_hostname");
  126.  
  127.   /* Check first if we have name in cache */
  128.   *errors=0;
  129.   if (!(specialflag & SPECIAL_NO_HOST_CACHE))
  130.   {
  131.     VOID(pthread_mutex_lock(&hostname_cache->lock));
  132.     if ((entry=(host_entry*) hostname_cache->search((gptr) &in->s_addr,0)))
  133.     {
  134.       char *name;
  135.       if (!entry->hostname)
  136.     name=0;                    // Don't allow connection
  137.       else
  138.     name=my_strdup(entry->hostname,MYF(0));
  139.       *errors= entry->errors;
  140.       VOID(pthread_mutex_unlock(&hostname_cache->lock));
  141.       DBUG_RETURN(name);
  142.     }
  143.     VOID(pthread_mutex_unlock(&hostname_cache->lock));
  144.   }
  145.  
  146.   struct hostent *hp, *check;
  147.   char *name;
  148.   LINT_INIT(check);
  149. #if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
  150.   char buff[GETHOSTBYADDR_BUFF_SIZE],buff2[GETHOSTBYNAME_BUFF_SIZE];
  151.   int tmp_errno;
  152.   struct hostent tmp_hostent, tmp_hostent2;
  153. #ifdef HAVE_purify
  154.   bzero(buff,sizeof(buff));        // Bug in purify
  155. #endif
  156.   if (!(hp=gethostbyaddr_r((char*) in,sizeof(*in),
  157.                AF_INET,
  158.                &tmp_hostent,buff,sizeof(buff),&tmp_errno)))
  159.   {
  160.     DBUG_PRINT("error",("gethostbyaddr_r returned %d",tmp_errno));
  161.     return 0;
  162.   }
  163.   if (!(check=my_gethostbyname_r(hp->h_name,&tmp_hostent2,buff2,sizeof(buff2),
  164.                  &tmp_errno)))
  165.   {
  166.     DBUG_PRINT("error",("gethostbyname_r returned %d",tmp_errno));
  167.     add_wrong_ip(in);
  168.     DBUG_RETURN(0);
  169.   }
  170.   if (!hp->h_name[0])
  171.   {
  172.     DBUG_PRINT("error",("Got an empty hostname"));
  173.     add_wrong_ip(in);
  174.     DBUG_RETURN(0);                // Don't allow empty hostnames
  175.   }
  176.   if (!(name=my_strdup(hp->h_name,MYF(0))))
  177.     DBUG_RETURN(0);                // out of memory
  178.  
  179. #else
  180.   VOID(pthread_mutex_lock(&hostname_cache->lock));
  181.   if (!(hp=gethostbyaddr((char*) in,sizeof(*in), AF_INET)))
  182.   {
  183.     DBUG_PRINT("error",("gethostbyaddr returned %d",errno));
  184.     VOID(pthread_mutex_unlock(&hostname_cache->lock));
  185.     add_wrong_ip(in);
  186.     DBUG_RETURN(0);
  187.   }
  188.   if (!hp->h_name[0])
  189.   {
  190.     VOID(pthread_mutex_unlock(&hostname_cache->lock));
  191.     DBUG_PRINT("error",("Got an empty hostname"));
  192.     add_wrong_ip(in);
  193.     DBUG_RETURN(0);                // Don't allow empty hostnames
  194.   }
  195.   if (!(name=my_strdup(hp->h_name,MYF(0))))
  196.     DBUG_RETURN(0);                // out of memory
  197.   check=gethostbyname(name);
  198.   VOID(pthread_mutex_unlock(&hostname_cache->lock));
  199.   if (!check)
  200.   {
  201.     DBUG_PRINT("error",("gethostbyname returned %d",errno));
  202.     my_free(name,MYF(0));
  203.     DBUG_RETURN(0);
  204.   }
  205. #endif
  206.  
  207.   /* Don't accept hostnames that starts with digits because they may be
  208.      false ip:s */
  209.   if (isdigit(name[0]))
  210.   {
  211.     char *pos;
  212.     for (pos= name+1 ; isdigit(*pos); pos++) ;
  213.     if (*pos == '.')
  214.     {
  215.       DBUG_PRINT("error",("mysqld doesn't accept hostnames that starts with a number followed by a '.'"));
  216.       my_free(name,MYF(0));
  217.       add_wrong_ip(in);
  218.       DBUG_RETURN(0);
  219.     }
  220.   }
  221.  
  222.   /* Check that 'gethostbyname' returned the used ip */
  223.   for (uint i=0; check->h_addr_list[i]; i++)
  224.   {
  225.     if (*(uint32*)(check->h_addr_list)[i] == in->s_addr)
  226.     {
  227.       add_hostname(in,name);
  228.       DBUG_RETURN(name);
  229.     }
  230.   }
  231.   DBUG_PRINT("error",("Couldn't verify hostname with gethostbyname"));
  232.   my_free(name,MYF(0));
  233.   add_wrong_ip(in);
  234.   DBUG_RETURN(0);
  235. }
  236.