mariadb/sql/hostname.cc
unknown b125770aaa We are now using Valgrind rather than purify, and have for quite some time.
Consequently, rename HAVE_purify to HAVE_valgrind, and related changes.
Leave some comments about purify when not clear that they apply also to Valgrind.
Fix redundant IF_VALGRIND declaration.

Misc. small fixes:
 - Fixes for pool-of-threads patch.
 - Fixes for push of PBXT storage engine.
 - mysql-test-run.pl fix.
 - Fix build problem in compile-pentium64-max.


BUILD/SETUP.sh:
  Rename purify -> valgrind.
BUILD/build_mccge.sh:
  Rename purify -> valgrind.
BUILD/compile-dist:
  Fix that PBXT was missing in source tarball after `BUILD/compile-dist && make dist`
BUILD/compile-pentium64-max:
  Fix a build problem with BUILD/compile-pentium64-max on CentOS/Fedora Core 10 amd64.
        
  On these systems, there is libz.so but no libz.a. Finding libz.so, ./configure decides
  to use system zlib. But since BUILD/compile-pentium64-max builds a fully static binary
  with -all-static, the link of mysqld fails due to missing libz.a.
        
  Fix by using bundled zlib in the build script.
BUILD/compile-solaris-sparc-purify:
  Rename purify -> valgrind.
include/m_string.h:
  Rename purify -> valgrind.
include/my_global.h:
  Rename purify -> valgrind.
mysql-test/Makefile.am:
  Fix that PBXT test suite was missing from `make dist` source tarball.
mysql-test/lib/mtr_unique.pm:
  Better fix to avoid races when chmod'ing the semaphore file.
  (Though using chmod 666 shared files in /tmp/ is still not a very good solution).
mysql-test/t/pool_of_threads.cnf:
  Fix that test case pool_of_threads fails if run on mysqld with no --with-libevent support.
mysys/mf_qsort.c:
  Rename purify -> valgrind.
mysys/my_alloc.c:
  Rename purify -> valgrind.
mysys/my_init.c:
  Rename purify -> valgrind.
mysys/my_rnd.c:
  Rename purify -> valgrind.
mysys/safemalloc.c:
  Rename purify -> valgrind.
scripts/mysql_config.pl.in:
  Rename purify -> valgrind.
scripts/mysql_config.sh:
  Rename purify -> valgrind.
sql/field_conv.cc:
  Rename purify -> valgrind.
sql/filesort.cc:
  Rename purify -> valgrind.
sql/ha_partition.cc:
  Rename purify -> valgrind.
sql/hostname.cc:
  Rename purify -> valgrind.
sql/item_timefunc.cc:
  Rename purify -> valgrind.
sql/log_event.cc:
  Rename purify -> valgrind.
sql/log_event_old.cc:
  Rename purify -> valgrind.
sql/my_decimal.h:
  Rename purify -> valgrind.
sql/mysqld.cc:
  Rename purify -> valgrind.
  Fix redundant IF_VALGRIND declaration.
sql/opt_range.cc:
  Rename purify -> valgrind.
sql/opt_range.h:
  Rename purify -> valgrind.
sql/records.cc:
  Rename purify -> valgrind.
sql/rpl_rli.cc:
  Rename purify -> valgrind.
sql/rpl_rli.h:
  Rename purify -> valgrind.
sql/set_var.cc:
  Fix missing static declaration on pool_of_threads.
sql/slave.cc:
  Rename purify -> valgrind.
sql/sql_base.cc:
  Rename purify -> valgrind.
sql/sql_binlog.cc:
  Rename purify -> valgrind.
sql/sql_class.cc:
  Rename purify -> valgrind.
sql/sql_list.h:
  Rename purify -> valgrind.
sql/sql_load.cc:
  Rename purify -> valgrind.
sql/sql_select.cc:
  Rename purify -> valgrind.
sql/table.cc:
  Rename purify -> valgrind.
storage/archive/azio.c:
  Rename purify -> valgrind.
storage/innobase/buf/buf0buf.c:
  Rename purify -> valgrind.
storage/innobase/include/univ.i:
  Rename purify -> valgrind.
storage/innobase/srv/srv0start.c:
  Rename purify -> valgrind.
storage/maria/ha_maria.cc:
  Rename purify -> valgrind.
storage/maria/ma_blockrec.c:
  Rename purify -> valgrind.
storage/maria/ma_check.c:
  Rename purify -> valgrind.
storage/maria/ma_loghandler.c:
  Rename purify -> valgrind.
storage/maria/ma_packrec.c:
  Rename purify -> valgrind.
storage/maria/ma_page.c:
  Rename purify -> valgrind.
storage/maria/ma_pagecrc.c:
  Rename purify -> valgrind.
storage/maria/ma_search.c:
  Rename purify -> valgrind.
storage/myisam/mi_check.c:
  Rename purify -> valgrind.
storage/myisam/mi_page.c:
  Rename purify -> valgrind.
storage/myisam/mi_search.c:
  Rename purify -> valgrind.
storage/myisammrg/ha_myisammrg.cc:
  Rename purify -> valgrind.
strings/bcmp.c:
  Rename purify -> valgrind.
strings/decimal.c:
  Rename purify -> valgrind.
strings/strmake.c:
  Rename purify -> valgrind.
2009-05-06 14:03:24 +02:00

278 lines
7.3 KiB
C++

/* Copyright (C) 2000-2006 MySQL AB
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; version 2 of the License.
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-1307 USA */
/**
@file
@brief
Get hostname for an IP.
Hostnames are checked with reverse name lookup and
checked that they doesn't resemble an ip.
*/
#include "mysql_priv.h"
#include "hash_filo.h"
#include <m_ctype.h>
#ifdef __cplusplus
extern "C" { // Because of SCO 3.2V4.2
#endif
#if !defined( __WIN__)
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#include <netdb.h>
#include <sys/utsname.h>
#endif // __WIN__
#ifdef __cplusplus
}
#endif
class host_entry :public hash_filo_element
{
public:
char ip[sizeof(((struct in_addr *) 0)->s_addr)];
uint errors;
char *hostname;
};
static hash_filo *hostname_cache;
static pthread_mutex_t LOCK_hostname;
void hostname_cache_refresh()
{
hostname_cache->clear();
}
bool hostname_cache_init()
{
host_entry tmp;
uint offset= (uint) ((char*) (&tmp.ip) - (char*) &tmp);
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset,
sizeof(struct in_addr),NULL,
(hash_free_key) free,
&my_charset_bin)))
return 1;
hostname_cache->clear();
(void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW);
return 0;
}
void hostname_cache_free()
{
if (hostname_cache)
{
(void) pthread_mutex_destroy(&LOCK_hostname);
delete hostname_cache;
hostname_cache= 0;
}
}
static void add_hostname(struct in_addr *in,const char *name)
{
if (!(specialflag & SPECIAL_NO_HOST_CACHE))
{
VOID(pthread_mutex_lock(&hostname_cache->lock));
host_entry *entry;
if (!(entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0)))
{
uint length=name ? (uint) strlen(name) : 0;
if ((entry=(host_entry*) malloc(sizeof(host_entry)+length+1)))
{
char *new_name;
memcpy_fixed(&entry->ip, &in->s_addr, sizeof(in->s_addr));
if (length)
memcpy(new_name= (char *) (entry+1), name, length+1);
else
new_name=0;
entry->hostname=new_name;
entry->errors=0;
(void) hostname_cache->add(entry);
}
}
VOID(pthread_mutex_unlock(&hostname_cache->lock));
}
}
inline void add_wrong_ip(struct in_addr *in)
{
add_hostname(in,NullS);
}
void inc_host_errors(struct in_addr *in)
{
VOID(pthread_mutex_lock(&hostname_cache->lock));
host_entry *entry;
if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0)))
entry->errors++;
VOID(pthread_mutex_unlock(&hostname_cache->lock));
}
void reset_host_errors(struct in_addr *in)
{
VOID(pthread_mutex_lock(&hostname_cache->lock));
host_entry *entry;
if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0)))
entry->errors=0;
VOID(pthread_mutex_unlock(&hostname_cache->lock));
}
/* Deal with systems that don't defined INADDR_LOOPBACK */
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001UL
#endif
char * ip_to_hostname(struct in_addr *in, uint *errors)
{
uint i;
host_entry *entry;
DBUG_ENTER("ip_to_hostname");
*errors=0;
/* We always treat the loopback address as "localhost". */
if (in->s_addr == htonl(INADDR_LOOPBACK)) // is expanded inline by gcc
DBUG_RETURN((char *)my_localhost);
/* Check first if we have name in cache */
if (!(specialflag & SPECIAL_NO_HOST_CACHE))
{
VOID(pthread_mutex_lock(&hostname_cache->lock));
if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0)))
{
char *name;
if (!entry->hostname)
name=0; // Don't allow connection
else
name=my_strdup(entry->hostname,MYF(0));
*errors= entry->errors;
VOID(pthread_mutex_unlock(&hostname_cache->lock));
DBUG_RETURN(name);
}
VOID(pthread_mutex_unlock(&hostname_cache->lock));
}
struct hostent *hp, *check;
char *name;
LINT_INIT(check);
#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
char buff[GETHOSTBYADDR_BUFF_SIZE],buff2[GETHOSTBYNAME_BUFF_SIZE];
int tmp_errno;
struct hostent tmp_hostent, tmp_hostent2;
#ifdef HAVE_valgrind
bzero(buff,sizeof(buff)); // Bug in purify
#endif
if (!(hp=gethostbyaddr_r((char*) in,sizeof(*in),
AF_INET,
&tmp_hostent,buff,sizeof(buff),&tmp_errno)))
{
DBUG_PRINT("error",("gethostbyaddr_r returned %d",tmp_errno));
return 0;
}
if (!(check=my_gethostbyname_r(hp->h_name,&tmp_hostent2,buff2,sizeof(buff2),
&tmp_errno)))
{
DBUG_PRINT("error",("gethostbyname_r returned %d",tmp_errno));
/*
Don't cache responses when the DSN server is down, as otherwise
transient DNS failure may leave any number of clients (those
that attempted to connect during the outage) unable to connect
indefinitely.
*/
if (tmp_errno == HOST_NOT_FOUND || tmp_errno == NO_DATA)
add_wrong_ip(in);
my_gethostbyname_r_free();
DBUG_RETURN(0);
}
if (!hp->h_name[0])
{
DBUG_PRINT("error",("Got an empty hostname"));
add_wrong_ip(in);
my_gethostbyname_r_free();
DBUG_RETURN(0); // Don't allow empty hostnames
}
if (!(name=my_strdup(hp->h_name,MYF(0))))
{
my_gethostbyname_r_free();
DBUG_RETURN(0); // out of memory
}
my_gethostbyname_r_free();
#else
VOID(pthread_mutex_lock(&LOCK_hostname));
if (!(hp=gethostbyaddr((char*) in,sizeof(*in), AF_INET)))
{
VOID(pthread_mutex_unlock(&LOCK_hostname));
DBUG_PRINT("error",("gethostbyaddr returned %d",errno));
if (errno == HOST_NOT_FOUND || errno == NO_DATA)
goto add_wrong_ip_and_return;
/* Failure, don't cache responce */
DBUG_RETURN(0);
}
if (!hp->h_name[0]) // Don't allow empty hostnames
{
VOID(pthread_mutex_unlock(&LOCK_hostname));
DBUG_PRINT("error",("Got an empty hostname"));
goto add_wrong_ip_and_return;
}
if (!(name=my_strdup(hp->h_name,MYF(0))))
{
VOID(pthread_mutex_unlock(&LOCK_hostname));
DBUG_RETURN(0); // out of memory
}
check=gethostbyname(name);
VOID(pthread_mutex_unlock(&LOCK_hostname));
if (!check)
{
DBUG_PRINT("error",("gethostbyname returned %d",errno));
my_free(name,MYF(0));
DBUG_RETURN(0);
}
#endif
/* Don't accept hostnames that starts with digits because they may be
false ip:s */
if (my_isdigit(&my_charset_latin1,name[0]))
{
char *pos;
for (pos= name+1 ; my_isdigit(&my_charset_latin1,*pos); pos++) ;
if (*pos == '.')
{
DBUG_PRINT("error",("mysqld doesn't accept hostnames that starts with a number followed by a '.'"));
my_free(name,MYF(0));
goto add_wrong_ip_and_return;
}
}
/* Check that 'gethostbyname' returned the used ip */
for (i=0; check->h_addr_list[i]; i++)
{
if (*(uint32*)(check->h_addr_list)[i] == in->s_addr)
{
add_hostname(in,name);
DBUG_RETURN(name);
}
}
DBUG_PRINT("error",("Couldn't verify hostname with gethostbyname"));
my_free(name,MYF(0));
add_wrong_ip_and_return:
add_wrong_ip(in);
DBUG_RETURN(0);
}