A
download hostname.cc
Language: C++
Copyright: (C) 1998 TcX AB & Monty Program KB & Detron HB
LOC: 190
Project Info
MySQL
Server: SourceForge
Type: cvs
...mysql\mysql\mysql‑3.22\sql\
   convert.cc
   crebas.cc
   derror.cc
   dfunc.cc
   field.cc
   field.h
   field_conv.cc
   filesort.cc
   gen_lex_hash.cc
   handler.cc
   handler.h
   hash_filo.cc
   hash_filo.h
   hostname.cc
   init.cc
   item.cc
   item.h
   item_buff.cc
   item_cmpfunc.cc
   item_cmpfunc.h
   item_func.cc
   item_func.h
   item_strfunc.cc
   item_strfunc.h
   item_sum.cc
   item_sum.h
   item_timefunc.cc
   item_timefunc.h
   item_uniq.cc
   item_uniq.h
   key.cc
   lex.h
   lex_hash.h
   lock.cc
   log.cc
   Makefile.am
   Makefile.in
   mf_iocache.cc
   my_lock.c
   mysql_priv.h
   mysqld.cc
   net_pkg.cc
   net_serv.c
   opt_range.cc
   opt_range.h
   opt_sum.cc
   password.c
   procedure.cc
   procedure.h
   records.cc
   sql_acl.cc
   sql_acl.h
   sql_base.cc
   sql_class.cc
   sql_class.h
   sql_crypt.cc
   sql_crypt.h
   sql_db.cc
   sql_delete.cc
   sql_insert.cc
   sql_lex.cc
   sql_lex.h
   sql_list.cc
   sql_list.h
   sql_load.cc
   sql_map.cc
   sql_map.h
   sql_parse.cc
   sql_select.cc
   sql_select.h
   sql_show.cc
   sql_string.cc
   sql_string.h
   sql_table.cc
   sql_test.cc
   sql_udf.cc
   sql_udf.h
   sql_update.cc
   sql_yacc.cc
   sql_yacc.h
   sql_yacc.yy
   structs.h
   table.h
   thr_malloc.cc
   time.cc
   udf_example.cc
   unireg.cc
   unireg.h

/* Copyright (C) 1998 TcX AB & Monty Program KB & Detron HB

   This software is distributed with NO WARRANTY OF ANY KIND.  No author or
   distributor accepts any responsibility for the consequences of using it, or
   for whether it serves any particular purpose or works at all, unless he or
   she says so in writing.  Refer to the Free Public License (the "License")
   for full details.

   Every copy of this file must include a copy of the License, normally in a
   plain ASCII text file named PUBLIC.	The License grants you the right to
   copy, modify and redistribute this file, but only under certain conditions
   described in the License.  Among other things, the License requires that
   the copyright notice and this notice be preserved on all copies. */

/*
  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 __WIN32__
#include <sys/resource.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#include <netdb.h>
#include <sys/utsname.h>
#endif // __WIN32__
#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 ? strlen(name) : 0;

      if ((entry=(host_entry*) malloc(sizeof(host_entry)+length+1)))
      {
	char *new_name= (char *) (entry+1);
	memcpy(&entry->ip, &in->s_addr, sizeof(in->s_addr));
	memcpy(new_name, name, length);	// Should work even if name == NULL
	new_name[length]=0;		// End of string
	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)
{
  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)))
  {
    DBUG_PRINT("error",("gethostbyaddr returned %d",errno));
    VOID(pthread_mutex_unlock(&hostname_cache->lock));
    add_wrong_ip(in);
    DBUG_RETURN(0);
  }
  if (!hp->h_name[0])
  {
    VOID(pthread_mutex_unlock(&hostname_cache->lock));
    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
  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));
      add_wrong_ip(in);
      DBUG_RETURN(0);
    }
  }

  /* Check that 'gethostbyname' returned the used ip */
  for (uint 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(in);
  DBUG_RETURN(0);
}

About Koders | Resources | Downloads | Support | Black Duck | Terms of Service | DMCA | Privacy Policy | Contact Us