mariadb/sql/hostname.cc
unknown 28ad76e22c Fixed delete in tables with hidden primary key
Remove not used BDB logs on shutdown
Don't give warnings for repair on slaves
Fixed transaction log files


Docs/manual.texi:
  Updated 'known bugs'
include/my_sys.h:
  Added define for checking number of bytes left in the IO_CACHE
mysql-test/mysql-test-run:
  Small bug fixes
mysys/mf_iocache2.c:
  Use new define
sql/filesort.cc:
  Temporary fix for FULLTEXT index
sql/ha_berkeley.cc:
  Fix for delete in tables with hidden primary key
  Remove not used BDB logs on shutdown
sql/ha_myisam.cc:
  Don't give warnings for repair on slaves
sql/hostname.cc:
  Portability fix
sql/log.cc:
  Fix transaction log files
sql/log_event.h:
  portability fix
sql/slave.cc:
  Don't give warnings for repair on slaves
sql/sql_class.h:
  Cleanup
sql/sql_parse.cc:
  Fixed typo
2000-12-12 04:34:56 +02:00

240 lines
6.2 KiB
C++

/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
(at your option) any later version.
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 */
/*
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
#ifndef __WIN__
#include <sys/resource.h>
#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;
void hostname_cache_refresh()
{
hostname_cache->clear();
}
bool hostname_cache_init()
{
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE,offsetof(host_entry,ip),
sizeof(struct in_addr),NULL,
(void (*)(void*)) free)))
return 1;
hostname_cache->clear();
return 0;
}
void hostname_cache_free()
{
delete hostname_cache;
}
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((gptr) &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));
}
}
static 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((gptr) &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((gptr) &in->s_addr,0)))
entry->errors=0;
VOID(pthread_mutex_unlock(&hostname_cache->lock));
}
my_string ip_to_hostname(struct in_addr *in, uint *errors)
{
uint i;
host_entry *entry;
DBUG_ENTER("ip_to_hostname");
/* Check first if we have name in cache */
*errors=0;
if (!(specialflag & SPECIAL_NO_HOST_CACHE))
{
VOID(pthread_mutex_lock(&hostname_cache->lock));
if ((entry=(host_entry*) hostname_cache->search((gptr) &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_purify
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));
add_wrong_ip(in);
DBUG_RETURN(0);
}
if (!hp->h_name[0])
{
DBUG_PRINT("error",("Got an empty hostname"));
add_wrong_ip(in);
DBUG_RETURN(0); // Don't allow empty hostnames
}
if (!(name=my_strdup(hp->h_name,MYF(0))))
DBUG_RETURN(0); // out of memory
#else
VOID(pthread_mutex_lock(&hostname_cache->lock));
if (!(hp=gethostbyaddr((char*) in,sizeof(*in), AF_INET)))
{
VOID(pthread_mutex_unlock(&hostname_cache->lock));
DBUG_PRINT("error",("gethostbyaddr returned %d",errno));
goto err;
}
if (!hp->h_name[0]) // Don't allow empty hostnames
{
VOID(pthread_mutex_unlock(&hostname_cache->lock));
DBUG_PRINT("error",("Got an empty hostname"));
goto err;
}
if (!(name=my_strdup(hp->h_name,MYF(0))))
{
VOID(pthread_mutex_unlock(&hostname_cache->lock));
DBUG_RETURN(0); // out of memory
}
check=gethostbyname(name);
VOID(pthread_mutex_unlock(&hostname_cache->lock));
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 (isdigit(name[0]))
{
char *pos;
for (pos= name+1 ; isdigit(*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 err;
}
}
/* 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));
err:
add_wrong_ip(in);
DBUG_RETURN(0);
}