27 #include "my_global.h"
30 #include "hash_filo.h"
39 #if !defined( __WIN__)
43 #include <sys/utsname.h>
49 Host_errors::Host_errors()
52 m_nameinfo_transient(0),
53 m_nameinfo_permanent(0),
55 m_addrinfo_transient(0),
56 m_addrinfo_permanent(0),
66 m_max_user_connection(0),
67 m_max_user_connection_per_hour(0),
68 m_default_database(0),
73 Host_errors::~Host_errors()
76 void Host_errors::reset()
129 void hostname_cache_refresh()
131 hostname_cache->clear();
134 uint hostname_cache_size()
136 return hostname_cache->size();
139 void hostname_cache_resize(uint
size)
141 hostname_cache->resize(size);
144 bool hostname_cache_init()
147 uint key_offset= (uint) ((
char*) (&tmp.
ip_key) - (
char*) &tmp);
149 if (!(hostname_cache=
new hash_filo(HOST_CACHE_SIZE,
150 key_offset, HOST_ENTRY_KEY_SIZE,
151 NULL, (my_hash_free_key) free,
155 hostname_cache->clear();
160 void hostname_cache_free()
162 delete hostname_cache;
163 hostname_cache= NULL;
166 void hostname_cache_lock()
171 void hostname_cache_unlock()
176 static void prepare_hostname_cache_key(
const char *ip_string,
179 int ip_string_length= strlen(ip_string);
180 DBUG_ASSERT(ip_string_length < HOST_ENTRY_KEY_SIZE);
182 memset(ip_key, 0, HOST_ENTRY_KEY_SIZE);
183 memcpy(ip_key, ip_string, ip_string_length);
187 {
return (
Host_entry *) hostname_cache->first(); }
189 static inline Host_entry *hostname_cache_search(
const char *ip_key)
191 return (
Host_entry *) hostname_cache->search((uchar *) ip_key, 0);
194 static void add_hostname_impl(
const char *ip_key,
const char *hostname,
199 bool need_add=
false;
201 entry= hostname_cache_search(ip_key);
203 if (likely(entry == NULL))
210 memcpy(&entry->
ip_key, ip_key, HOST_ENTRY_KEY_SIZE);
214 entry->m_first_seen= now;
215 entry->m_last_seen= now;
216 entry->m_first_error_seen= 0;
217 entry->m_last_error_seen= 0;
221 entry->m_last_seen= now;
226 if (hostname != NULL)
228 uint len= strlen(hostname);
236 (
"Adding/Updating '%s' -> '%s' (validated) to the hostname cache...'",
237 (
const char *) ip_key,
244 (
"Adding/Updating '%s' -> NULL (validated) to the hostname cache...'",
245 (
const char *) ip_key));
252 errors->sum_connect_errors();
259 errors->clear_connect_errors();
261 (
"Adding/Updating '%s' -> NULL (not validated) to the hostname cache...'",
262 (
const char *) ip_key));
265 if (errors->has_error())
266 entry->set_error_timestamps(now);
271 hostname_cache->add(entry);
276 static void add_hostname(
const char *ip_key,
const char *hostname,
279 if (specialflag & SPECIAL_NO_HOST_CACHE)
282 ulonglong now= my_micro_time();
286 add_hostname_impl(ip_key, hostname, validated, errors, now);
293 void inc_host_errors(
const char *ip_string,
Host_errors *errors)
298 ulonglong now= my_micro_time();
299 char ip_key[HOST_ENTRY_KEY_SIZE];
300 prepare_hostname_cache_key(ip_string, ip_key);
304 Host_entry *entry= hostname_cache_search(ip_key);
309 errors->sum_connect_errors();
311 errors->clear_connect_errors();
314 entry->set_error_timestamps(now);
321 void reset_host_connect_errors(
const char *ip_string)
326 char ip_key[HOST_ENTRY_KEY_SIZE];
327 prepare_hostname_cache_key(ip_string, ip_key);
331 Host_entry *entry= hostname_cache_search(ip_key);
334 entry->
m_errors.clear_connect_errors();
340 static inline bool is_ip_loopback(
const struct sockaddr *ip)
342 switch (ip->sa_family) {
346 struct in_addr *ip4= &((
struct sockaddr_in *) ip)->sin_addr;
347 return ntohl(ip4->s_addr) == INADDR_LOOPBACK;
354 struct in6_addr *ip6= &((
struct sockaddr_in6 *) ip)->sin6_addr;
355 return IN6_IS_ADDR_LOOPBACK(ip6);
364 static inline bool is_hostname_valid(
const char *hostname)
371 if (!my_isdigit(&my_charset_latin1, hostname[0]))
374 const char *p= hostname + 1;
376 while (my_isdigit(&my_charset_latin1, *p))
411 const char *ip_string,
413 uint *connect_errors)
415 const struct sockaddr *ip= (
const sockaddr *) ip_storage;
420 DBUG_ENTER(
"ip_to_hostname");
421 DBUG_PRINT(
"info", (
"IP address: '%s'; family: %d.",
422 (
const char *) ip_string,
423 (
int) ip->sa_family));
431 if (is_ip_loopback(ip))
433 DBUG_PRINT(
"info", (
"Loopback address detected."));
436 *hostname= (
char *) my_localhost;
443 char ip_key[HOST_ENTRY_KEY_SIZE];
444 prepare_hostname_cache_key(ip_string, ip_key);
448 if (!(specialflag & SPECIAL_NO_HOST_CACHE))
450 ulonglong now= my_micro_time();
454 Host_entry *entry= hostname_cache_search(ip_key);
458 entry->m_last_seen= now;
464 entry->set_error_timestamps(now);
466 DBUG_RETURN(RC_BLOCKED_HOST);
477 *hostname= my_strdup(entry->
m_hostname, MYF(0));
479 DBUG_PRINT(
"info",(
"IP (%s) has been found in the cache. "
481 (
const char *) ip_key,
482 (
const char *) (*hostname? *hostname :
"null")
499 char hostname_buffer[NI_MAXHOST];
501 DBUG_PRINT(
"info", (
"Resolving '%s'...", (
const char *) ip_key));
503 err_code= vio_getnameinfo(ip, hostname_buffer, NI_MAXHOST, NULL, 0,
513 DBUG_EXECUTE_IF(
"getnameinfo_error_noname",
515 strcpy(hostname_buffer,
"<garbage>");
516 err_code= EAI_NONAME;
520 DBUG_EXECUTE_IF(
"getnameinfo_error_again",
522 strcpy(hostname_buffer,
"<garbage>");
527 DBUG_EXECUTE_IF(
"getnameinfo_fake_ipv4",
529 strcpy(hostname_buffer,
"santa.claus.ipv4.example.com");
534 DBUG_EXECUTE_IF(
"getnameinfo_fake_ipv6",
536 strcpy(hostname_buffer,
"santa.claus.ipv6.example.com");
541 DBUG_EXECUTE_IF(
"getnameinfo_format_ipv4",
543 strcpy(hostname_buffer,
"12.12.12.12");
548 DBUG_EXECUTE_IF(
"getnameinfo_format_ipv6",
550 strcpy(hostname_buffer,
"12:DEAD:BEEF:0");
565 DBUG_PRINT(
"error", (
"IP address '%s' could not be resolved: %s",
566 (
const char *) ip_key,
567 (
const char *) gai_strerror(err_code)));
569 sql_print_warning(
"IP address '%s' could not be resolved: %s",
570 (
const char *) ip_key,
571 (
const char *) gai_strerror(err_code));
574 if (vio_is_no_name_error(err_code))
593 add_hostname(ip_key, NULL, validated, &errors);
598 DBUG_PRINT(
"info", (
"IP '%s' resolved to '%s'.",
599 (
const char *) ip_key,
600 (
const char *) hostname_buffer));
617 if (!is_hostname_valid(hostname_buffer))
619 DBUG_PRINT(
"error", (
"IP address '%s' has been resolved "
620 "to the host name '%s', which resembles "
621 "IPv4-address itself.",
622 (
const char *) ip_key,
623 (
const char *) hostname_buffer));
625 sql_print_warning(
"IP address '%s' has been resolved "
626 "to the host name '%s', which resembles "
627 "IPv4-address itself.",
628 (
const char *) ip_key,
629 (
const char *) hostname_buffer);
632 add_hostname(ip_key, hostname_buffer,
false, &errors);
645 bool free_addr_info_list=
false;
647 memset(&hints, 0,
sizeof (
struct addrinfo));
648 hints.ai_flags= AI_PASSIVE;
649 hints.ai_socktype= SOCK_STREAM;
650 hints.ai_family= AF_UNSPEC;
652 DBUG_PRINT(
"info", (
"Getting IP addresses for hostname '%s'...",
653 (
const char *) hostname_buffer));
655 err_code= getaddrinfo(hostname_buffer, NULL, &hints, &addr_info_list);
657 free_addr_info_list=
true;
665 DBUG_EXECUTE_IF(
"getaddrinfo_error_noname",
667 if (free_addr_info_list)
668 freeaddrinfo(addr_info_list);
670 addr_info_list= NULL;
671 err_code= EAI_NONAME;
672 free_addr_info_list=
false;
676 DBUG_EXECUTE_IF(
"getaddrinfo_error_again",
678 if (free_addr_info_list)
679 freeaddrinfo(addr_info_list);
681 addr_info_list= NULL;
683 free_addr_info_list=
false;
687 DBUG_EXECUTE_IF(
"getaddrinfo_fake_bad_ipv4",
689 if (free_addr_info_list)
690 freeaddrinfo(addr_info_list);
692 struct sockaddr_in *debug_addr;
698 static struct sockaddr_in debug_sock_addr[2];
699 static struct addrinfo debug_addr_info[2];
701 debug_addr= & debug_sock_addr[0];
702 debug_addr->sin_family= AF_INET;
703 debug_addr->sin_addr.s_addr= inet_addr(
"192.0.2.126");
706 debug_addr= & debug_sock_addr[1];
707 debug_addr->sin_family= AF_INET;
708 debug_addr->sin_addr.s_addr= inet_addr(
"192.0.2.127");
710 debug_addr_info[0].ai_addr= (
struct sockaddr*) & debug_sock_addr[0];
711 debug_addr_info[0].ai_addrlen=
sizeof (
struct sockaddr_in);
712 debug_addr_info[0].ai_next= & debug_addr_info[1];
714 debug_addr_info[1].ai_addr= (
struct sockaddr*) & debug_sock_addr[1];
715 debug_addr_info[1].ai_addrlen=
sizeof (
struct sockaddr_in);
716 debug_addr_info[1].ai_next= NULL;
718 addr_info_list= & debug_addr_info[0];
720 free_addr_info_list=
false;
724 DBUG_EXECUTE_IF(
"getaddrinfo_fake_good_ipv4",
726 if (free_addr_info_list)
727 freeaddrinfo(addr_info_list);
729 struct sockaddr_in *debug_addr;
730 static struct sockaddr_in debug_sock_addr[2];
731 static struct addrinfo debug_addr_info[2];
733 debug_addr= & debug_sock_addr[0];
734 debug_addr->sin_family= AF_INET;
735 debug_addr->sin_addr.s_addr= inet_addr(
"192.0.2.5");
738 debug_addr= & debug_sock_addr[1];
739 debug_addr->sin_family= AF_INET;
740 debug_addr->sin_addr.s_addr= inet_addr(
"192.0.2.4");
742 debug_addr_info[0].ai_addr= (
struct sockaddr*) & debug_sock_addr[0];
743 debug_addr_info[0].ai_addrlen=
sizeof (
struct sockaddr_in);
744 debug_addr_info[0].ai_next= & debug_addr_info[1];
746 debug_addr_info[1].ai_addr= (
struct sockaddr*) & debug_sock_addr[1];
747 debug_addr_info[1].ai_addrlen=
sizeof (
struct sockaddr_in);
748 debug_addr_info[1].ai_next= NULL;
750 addr_info_list= & debug_addr_info[0];
752 free_addr_info_list=
false;
757 DBUG_EXECUTE_IF(
"getaddrinfo_fake_bad_ipv6",
759 if (free_addr_info_list)
760 freeaddrinfo(addr_info_list);
762 struct sockaddr_in6 *debug_addr;
769 static struct sockaddr_in6 debug_sock_addr[2];
770 static struct addrinfo debug_addr_info[2];
772 debug_addr= & debug_sock_addr[0];
773 debug_addr->sin6_family= AF_INET6;
774 ip6= & debug_addr->sin6_addr;
776 ip6->s6_addr[ 0] = 0x20;
777 ip6->s6_addr[ 1] = 0x01;
778 ip6->s6_addr[ 2] = 0x0d;
779 ip6->s6_addr[ 3] = 0xb8;
780 ip6->s6_addr[ 4] = 0x00;
781 ip6->s6_addr[ 5] = 0x00;
782 ip6->s6_addr[ 6] = 0x00;
783 ip6->s6_addr[ 7] = 0x00;
784 ip6->s6_addr[ 8] = 0x00;
785 ip6->s6_addr[ 9] = 0x00;
786 ip6->s6_addr[10] = 0x00;
787 ip6->s6_addr[11] = 0x00;
788 ip6->s6_addr[12] = 0x00;
789 ip6->s6_addr[13] = 0x06;
790 ip6->s6_addr[14] = 0x00;
791 ip6->s6_addr[15] = 0x7e;
794 debug_addr= & debug_sock_addr[1];
795 debug_addr->sin6_family= AF_INET6;
796 ip6= & debug_addr->sin6_addr;
797 ip6->s6_addr[ 0] = 0x20;
798 ip6->s6_addr[ 1] = 0x01;
799 ip6->s6_addr[ 2] = 0x0d;
800 ip6->s6_addr[ 3] = 0xb8;
801 ip6->s6_addr[ 4] = 0x00;
802 ip6->s6_addr[ 5] = 0x00;
803 ip6->s6_addr[ 6] = 0x00;
804 ip6->s6_addr[ 7] = 0x00;
805 ip6->s6_addr[ 8] = 0x00;
806 ip6->s6_addr[ 9] = 0x00;
807 ip6->s6_addr[10] = 0x00;
808 ip6->s6_addr[11] = 0x00;
809 ip6->s6_addr[12] = 0x00;
810 ip6->s6_addr[13] = 0x06;
811 ip6->s6_addr[14] = 0x00;
812 ip6->s6_addr[15] = 0x7f;
814 debug_addr_info[0].ai_addr= (
struct sockaddr*) & debug_sock_addr[0];
815 debug_addr_info[0].ai_addrlen=
sizeof (
struct sockaddr_in6);
816 debug_addr_info[0].ai_next= & debug_addr_info[1];
818 debug_addr_info[1].ai_addr= (
struct sockaddr*) & debug_sock_addr[1];
819 debug_addr_info[1].ai_addrlen=
sizeof (
struct sockaddr_in6);
820 debug_addr_info[1].ai_next= NULL;
822 addr_info_list= & debug_addr_info[0];
824 free_addr_info_list=
false;
828 DBUG_EXECUTE_IF(
"getaddrinfo_fake_good_ipv6",
830 if (free_addr_info_list)
831 freeaddrinfo(addr_info_list);
833 struct sockaddr_in6 *debug_addr;
840 static struct sockaddr_in6 debug_sock_addr[2];
841 static struct addrinfo debug_addr_info[2];
843 debug_addr= & debug_sock_addr[0];
844 debug_addr->sin6_family= AF_INET6;
845 ip6= & debug_addr->sin6_addr;
846 ip6->s6_addr[ 0] = 0x20;
847 ip6->s6_addr[ 1] = 0x01;
848 ip6->s6_addr[ 2] = 0x0d;
849 ip6->s6_addr[ 3] = 0xb8;
850 ip6->s6_addr[ 4] = 0x00;
851 ip6->s6_addr[ 5] = 0x00;
852 ip6->s6_addr[ 6] = 0x00;
853 ip6->s6_addr[ 7] = 0x00;
854 ip6->s6_addr[ 8] = 0x00;
855 ip6->s6_addr[ 9] = 0x00;
856 ip6->s6_addr[10] = 0x00;
857 ip6->s6_addr[11] = 0x00;
858 ip6->s6_addr[12] = 0x00;
859 ip6->s6_addr[13] = 0x06;
860 ip6->s6_addr[14] = 0x00;
861 ip6->s6_addr[15] = 0x07;
864 debug_addr= & debug_sock_addr[1];
865 debug_addr->sin6_family= AF_INET6;
866 ip6= & debug_addr->sin6_addr;
867 ip6->s6_addr[ 0] = 0x20;
868 ip6->s6_addr[ 1] = 0x01;
869 ip6->s6_addr[ 2] = 0x0d;
870 ip6->s6_addr[ 3] = 0xb8;
871 ip6->s6_addr[ 4] = 0x00;
872 ip6->s6_addr[ 5] = 0x00;
873 ip6->s6_addr[ 6] = 0x00;
874 ip6->s6_addr[ 7] = 0x00;
875 ip6->s6_addr[ 8] = 0x00;
876 ip6->s6_addr[ 9] = 0x00;
877 ip6->s6_addr[10] = 0x00;
878 ip6->s6_addr[11] = 0x00;
879 ip6->s6_addr[12] = 0x00;
880 ip6->s6_addr[13] = 0x06;
881 ip6->s6_addr[14] = 0x00;
882 ip6->s6_addr[15] = 0x06;
884 debug_addr_info[0].ai_addr= (
struct sockaddr*) & debug_sock_addr[0];
885 debug_addr_info[0].ai_addrlen=
sizeof (
struct sockaddr_in6);
886 debug_addr_info[0].ai_next= & debug_addr_info[1];
888 debug_addr_info[1].ai_addr= (
struct sockaddr*) & debug_sock_addr[1];
889 debug_addr_info[1].ai_addrlen=
sizeof (
struct sockaddr_in6);
890 debug_addr_info[1].ai_next= NULL;
892 addr_info_list= & debug_addr_info[0];
894 free_addr_info_list=
false;
907 sql_print_warning(
"Host name '%s' could not be resolved: %s",
908 (
const char *) hostname_buffer,
909 (
const char *) gai_strerror(err_code));
913 if (err_code == EAI_NONAME)
930 add_hostname(ip_key, NULL, validated, &errors);
937 DBUG_PRINT(
"info", (
"The following IP addresses found for '%s':",
938 (
const char *) hostname_buffer));
940 for (
struct addrinfo *addr_info= addr_info_list;
941 addr_info; addr_info= addr_info->ai_next)
943 char ip_buffer[HOST_ENTRY_KEY_SIZE];
947 vio_get_normalized_ip_string(addr_info->ai_addr, addr_info->ai_addrlen,
948 ip_buffer, sizeof (ip_buffer));
949 DBUG_ASSERT(!err_status);
952 DBUG_PRINT(
"info", (
" - '%s'", (
const char *) ip_buffer));
954 if (strcasecmp(ip_key, ip_buffer) == 0)
958 *hostname= my_strdup(hostname_buffer, MYF(0));
962 DBUG_PRINT(
"error", (
"Out of memory."));
964 if (free_addr_info_list)
965 freeaddrinfo(addr_info_list);
979 sql_print_warning(
"Hostname '%s' does not resolve to '%s'.",
980 (
const char *) hostname_buffer,
981 (
const char *) ip_key);
982 sql_print_information(
"Hostname '%s' has the following IP addresses:",
983 (
const char *) hostname_buffer);
985 for (
struct addrinfo *addr_info= addr_info_list;
986 addr_info; addr_info= addr_info->ai_next)
988 char ip_buffer[HOST_ENTRY_KEY_SIZE];
991 vio_get_normalized_ip_string(addr_info->ai_addr, addr_info->ai_addrlen,
992 ip_buffer, sizeof (ip_buffer));
993 DBUG_ASSERT(!err_status);
995 sql_print_information(
" - %s", (
const char *) ip_buffer);
1000 add_hostname(ip_key, *hostname,
true, &errors);
1003 if (free_addr_info_list)
1004 freeaddrinfo(addr_info_list);