1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
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, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software Foundation,
21    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 
24 /**
25   @file
26 
27   @brief
28   Get hostname for an IP address.
29 
30   Hostnames are checked with reverse name lookup and checked that they
31   doesn't resemble an IP address.
32 */
33 
34 #include "my_global.h"
35 #include "hostname.h"
36 #include "hash_filo.h"
37 #include <m_ctype.h>
38 #include "log.h"                                // sql_print_warning,
39                                                 // sql_print_information
40 #include "violite.h"                            // vio_getnameinfo,
41                                                 // vio_get_normalized_ip_string
42 
43 #ifdef HAVE_ARPA_INET_H
44 #include <arpa/inet.h>
45 #endif
46 #ifdef HAVE_SYS_UN_H
47 #include <sys/un.h>
48 #endif
49 #if !defined(_WIN32)
50 #include <sys/utsname.h>
51 #endif
52 
Host_errors()53 Host_errors::Host_errors()
54 : m_connect(0),
55   m_host_blocked(0),
56   m_nameinfo_transient(0),
57   m_nameinfo_permanent(0),
58   m_format(0),
59   m_addrinfo_transient(0),
60   m_addrinfo_permanent(0),
61   m_FCrDNS(0),
62   m_host_acl(0),
63   m_no_auth_plugin(0),
64   m_auth_plugin(0),
65   m_handshake(0),
66   m_proxy_user(0),
67   m_proxy_user_acl(0),
68   m_authentication(0),
69   m_ssl(0),
70   m_max_user_connection(0),
71   m_max_user_connection_per_hour(0),
72   m_default_database(0),
73   m_init_connect(0),
74   m_local(0)
75 {}
76 
~Host_errors()77 Host_errors::~Host_errors()
78 {}
79 
reset()80 void Host_errors::reset()
81 {
82   m_connect= 0;
83   m_host_blocked= 0;
84   m_nameinfo_transient= 0;
85   m_nameinfo_permanent= 0;
86   m_format= 0;
87   m_addrinfo_transient= 0;
88   m_addrinfo_permanent= 0;
89   m_FCrDNS= 0;
90   m_host_acl= 0;
91   m_no_auth_plugin= 0;
92   m_auth_plugin= 0;
93   m_handshake= 0;
94   m_proxy_user= 0;
95   m_proxy_user_acl= 0;
96   m_authentication= 0;
97   m_ssl= 0;
98   m_max_user_connection= 0;
99   m_max_user_connection_per_hour= 0;
100   m_default_database= 0;
101   m_init_connect= 0;
102   m_local= 0;
103 }
104 
aggregate(const Host_errors * errors)105 void Host_errors::aggregate(const Host_errors *errors)
106 {
107   m_connect+= errors->m_connect;
108   m_host_blocked+= errors->m_host_blocked;
109   m_nameinfo_transient+= errors->m_nameinfo_transient;
110   m_nameinfo_permanent+= errors->m_nameinfo_permanent;
111   m_format+= errors->m_format;
112   m_addrinfo_transient+= errors->m_addrinfo_transient;
113   m_addrinfo_permanent+= errors->m_addrinfo_permanent;
114   m_FCrDNS+= errors->m_FCrDNS;
115   m_host_acl+= errors->m_host_acl;
116   m_no_auth_plugin+= errors->m_no_auth_plugin;
117   m_auth_plugin+= errors->m_auth_plugin;
118   m_handshake+= errors->m_handshake;
119   m_proxy_user+= errors->m_proxy_user;
120   m_proxy_user_acl+= errors->m_proxy_user_acl;
121   m_authentication+= errors->m_authentication;
122   m_ssl+= errors->m_ssl;
123   m_max_user_connection+= errors->m_max_user_connection;
124   m_max_user_connection_per_hour+= errors->m_max_user_connection_per_hour;
125   m_default_database+= errors->m_default_database;
126   m_init_connect+= errors->m_init_connect;
127   m_local+= errors->m_local;
128 }
129 
130 static hash_filo *hostname_cache;
131 
hostname_cache_refresh()132 void hostname_cache_refresh()
133 {
134   hostname_cache->clear();
135 }
136 
hostname_cache_size()137 uint hostname_cache_size()
138 {
139   return hostname_cache->size();
140 }
141 
hostname_cache_resize(uint size)142 void hostname_cache_resize(uint size)
143 {
144   hostname_cache->resize(size);
145 }
146 
hostname_cache_init(uint size)147 bool hostname_cache_init(uint size)
148 {
149   Host_entry tmp;
150   uint key_offset= (uint) ((char*) (&tmp.ip_key) - (char*) &tmp);
151 
152   if (!(hostname_cache= new hash_filo(key_memory_host_cache_hostname,
153                                       size,
154                                       key_offset, HOST_ENTRY_KEY_SIZE,
155                                       NULL, (my_hash_free_key) free,
156                                       &my_charset_bin)))
157     return 1;
158 
159   hostname_cache->clear();
160 
161   return 0;
162 }
163 
hostname_cache_free()164 void hostname_cache_free()
165 {
166   delete hostname_cache;
167   hostname_cache= NULL;
168 }
169 
hostname_cache_lock()170 void hostname_cache_lock()
171 {
172   mysql_mutex_lock(&hostname_cache->lock);
173 }
174 
hostname_cache_unlock()175 void hostname_cache_unlock()
176 {
177   mysql_mutex_unlock(&hostname_cache->lock);
178 }
179 
prepare_hostname_cache_key(const char * ip_string,char * ip_key)180 static void prepare_hostname_cache_key(const char *ip_string,
181                                        char *ip_key)
182 {
183   size_t ip_string_length= strlen(ip_string);
184   assert(ip_string_length < HOST_ENTRY_KEY_SIZE);
185 
186   memset(ip_key, 0, HOST_ENTRY_KEY_SIZE);
187   memcpy(ip_key, ip_string, ip_string_length);
188 }
189 
hostname_cache_first()190 Host_entry *hostname_cache_first()
191 { return (Host_entry *) hostname_cache->first(); }
192 
hostname_cache_search(const char * ip_key)193 static inline Host_entry *hostname_cache_search(const char *ip_key)
194 {
195   return (Host_entry *) hostname_cache->search((uchar *) ip_key, 0);
196 }
197 
add_hostname_impl(const char * ip_key,const char * hostname,bool validated,Host_errors * errors,ulonglong now)198 static void add_hostname_impl(const char *ip_key, const char *hostname,
199                               bool validated, Host_errors *errors,
200                               ulonglong now)
201 {
202   Host_entry *entry;
203   bool need_add= false;
204 
205   entry= hostname_cache_search(ip_key);
206 
207   if (likely(entry == NULL))
208   {
209     entry= (Host_entry *) malloc(sizeof (Host_entry));
210     if (entry == NULL)
211       return;
212 
213     need_add= true;
214     memcpy(&entry->ip_key, ip_key, HOST_ENTRY_KEY_SIZE);
215     entry->m_errors.reset();
216     entry->m_hostname_length= 0;
217     entry->m_host_validated= false;
218     entry->m_first_seen= now;
219     entry->m_last_seen= now;
220     entry->m_first_error_seen= 0;
221     entry->m_last_error_seen= 0;
222   }
223   else
224   {
225     entry->m_last_seen= now;
226   }
227 
228   if (validated)
229   {
230     if (hostname != NULL)
231     {
232       size_t len= strlen(hostname);
233       if (len > sizeof(entry->m_hostname) - 1)
234         len= sizeof(entry->m_hostname) - 1;
235       memcpy(entry->m_hostname, hostname, len);
236       entry->m_hostname[len]= '\0';
237       entry->m_hostname_length= static_cast<uint>(len);
238 
239       DBUG_PRINT("info",
240                  ("Adding/Updating '%s' -> '%s' (validated) to the hostname cache...'",
241                  ip_key,
242                  entry->m_hostname));
243     }
244     else
245     {
246       entry->m_hostname_length= 0;
247       DBUG_PRINT("info",
248                  ("Adding/Updating '%s' -> NULL (validated) to the hostname cache...'",
249                  ip_key));
250     }
251     entry->m_host_validated= true;
252     /*
253       New errors that are considered 'blocking',
254       that will eventually cause the IP to be black listed and blocked.
255     */
256     errors->sum_connect_errors();
257   }
258   else
259   {
260     entry->m_hostname_length= 0;
261     entry->m_host_validated= false;
262     /* Do not count new blocking errors during DNS failures. */
263     errors->clear_connect_errors();
264     DBUG_PRINT("info",
265                ("Adding/Updating '%s' -> NULL (not validated) to the hostname cache...'",
266                ip_key));
267   }
268 
269   if (errors->has_error())
270     entry->set_error_timestamps(now);
271 
272   entry->m_errors.aggregate(errors);
273 
274   if (need_add)
275     hostname_cache->add(entry);
276 
277   return;
278 }
279 
add_hostname(const char * ip_key,const char * hostname,bool validated,Host_errors * errors)280 static void add_hostname(const char *ip_key, const char *hostname,
281                          bool validated, Host_errors *errors)
282 {
283   if (specialflag & SPECIAL_NO_HOST_CACHE)
284     return;
285 
286   ulonglong now= my_micro_time();
287 
288   mysql_mutex_lock(&hostname_cache->lock);
289 
290   add_hostname_impl(ip_key, hostname, validated, errors, now);
291 
292   mysql_mutex_unlock(&hostname_cache->lock);
293 
294   return;
295 }
296 
inc_host_errors(const char * ip_string,Host_errors * errors)297 void inc_host_errors(const char *ip_string, Host_errors *errors)
298 {
299   if (!ip_string)
300     return;
301 
302   ulonglong now= my_micro_time();
303   char ip_key[HOST_ENTRY_KEY_SIZE];
304   prepare_hostname_cache_key(ip_string, ip_key);
305 
306   mysql_mutex_lock(&hostname_cache->lock);
307 
308   Host_entry *entry= hostname_cache_search(ip_key);
309 
310   if (entry)
311   {
312     if (entry->m_host_validated)
313       errors->sum_connect_errors();
314     else
315       errors->clear_connect_errors();
316 
317     entry->m_errors.aggregate(errors);
318     entry->set_error_timestamps(now);
319   }
320 
321   mysql_mutex_unlock(&hostname_cache->lock);
322 }
323 
324 
reset_host_connect_errors(const char * ip_string)325 void reset_host_connect_errors(const char *ip_string)
326 {
327   if (!ip_string)
328     return;
329 
330   char ip_key[HOST_ENTRY_KEY_SIZE];
331   prepare_hostname_cache_key(ip_string, ip_key);
332 
333   mysql_mutex_lock(&hostname_cache->lock);
334 
335   Host_entry *entry= hostname_cache_search(ip_key);
336 
337   if (entry)
338     entry->m_errors.clear_connect_errors();
339 
340   mysql_mutex_unlock(&hostname_cache->lock);
341 }
342 
343 
is_ip_loopback(const struct sockaddr * ip)344 static inline bool is_ip_loopback(const struct sockaddr *ip)
345 {
346   switch (ip->sa_family) {
347   case AF_INET:
348     {
349       /* Check for IPv4 127.0.0.1. */
350       struct in_addr *ip4= &((struct sockaddr_in *) ip)->sin_addr;
351       return ntohl(ip4->s_addr) == INADDR_LOOPBACK;
352     }
353 
354 #ifdef HAVE_IPV6
355   case AF_INET6:
356     {
357       /* Check for IPv6 ::1. */
358       struct in6_addr *ip6= &((struct sockaddr_in6 *) ip)->sin6_addr;
359       return IN6_IS_ADDR_LOOPBACK(ip6);
360     }
361 #endif /* HAVE_IPV6 */
362 
363   default:
364     return FALSE;
365   }
366 }
367 
is_hostname_valid(const char * hostname)368 static inline bool is_hostname_valid(const char *hostname)
369 {
370   /*
371     A hostname is invalid if it starts with a number followed by a dot
372     (IPv4 address).
373   */
374 
375   if (!my_isdigit(&my_charset_latin1, hostname[0]))
376     return TRUE;
377 
378   const char *p= hostname + 1;
379 
380   while (my_isdigit(&my_charset_latin1, *p))
381     ++p;
382 
383   return *p != '.';
384 }
385 
386 /**
387   Resolve IP-address to host name.
388 
389   This function does the following things:
390     - resolves IP-address;
391     - employs Forward Confirmed Reverse DNS technique to validate IP-address;
392     - returns host name if IP-address is validated;
393     - set value to out-variable connect_errors -- this variable represents the
394       number of connection errors from the specified IP-address.
395     - update the host_cache statistics
396 
397   NOTE: connect_errors are counted (are supported) only for the clients
398   where IP-address can be resolved and FCrDNS check is passed.
399 
400   @param [in]  ip_storage IP address (sockaddr). Must be set.
401   @param [in]  ip_string  IP address (string). Must be set.
402   @param [out] hostname
403   @param [out] connect_errors
404 
405   @return Error status
406   @retval 0 Success
407   @retval RC_BLOCKED_HOST The host is blocked.
408 
409   The function does not set/report MySQL server error in case of failure.
410   It's caller's responsibility to handle failures of this function
411   properly.
412 */
413 
ip_to_hostname(struct sockaddr_storage * ip_storage,const char * ip_string,char ** hostname,uint * connect_errors)414 int ip_to_hostname(struct sockaddr_storage *ip_storage,
415                    const char *ip_string,
416                    char **hostname,
417                    uint *connect_errors)
418 {
419   const struct sockaddr *ip= (const sockaddr *) ip_storage;
420   int err_code;
421   Host_errors errors;
422 
423   DBUG_ENTER("ip_to_hostname");
424   DBUG_PRINT("info", ("IP address: '%s'; family: %d.",
425                       ip_string,
426                       (int) ip->sa_family));
427 
428   /* Default output values, for most cases. */
429   *hostname= NULL;
430   *connect_errors= 0;
431 
432   /* Check if we have loopback address (127.0.0.1 or ::1). */
433 
434   if (is_ip_loopback(ip))
435   {
436     DBUG_PRINT("info", ("Loopback address detected."));
437 
438     /* Do not count connect errors from localhost. */
439     *hostname= (char *) my_localhost;
440 
441     DBUG_RETURN(0);
442   }
443 
444   /* Prepare host name cache key. */
445 
446   char ip_key[HOST_ENTRY_KEY_SIZE];
447   prepare_hostname_cache_key(ip_string, ip_key);
448 
449   /* Check first if we have host name in the cache. */
450 
451   if (!(specialflag & SPECIAL_NO_HOST_CACHE))
452   {
453     ulonglong now= my_micro_time();
454 
455     mysql_mutex_lock(&hostname_cache->lock);
456 
457     Host_entry *entry= hostname_cache_search(ip_key);
458 
459     if (entry)
460     {
461       entry->m_last_seen= now;
462       *connect_errors= entry->m_errors.m_connect;
463 
464       if (entry->m_errors.m_connect >= max_connect_errors)
465       {
466         entry->m_errors.m_host_blocked++;
467         entry->set_error_timestamps(now);
468         mysql_mutex_unlock(&hostname_cache->lock);
469         DBUG_RETURN(RC_BLOCKED_HOST);
470       }
471 
472       /*
473         If there is an IP -> HOSTNAME association in the cache,
474         but for a hostname that was not validated,
475         do not return that hostname: perform the network validation again.
476       */
477       if (entry->m_host_validated)
478       {
479         if (entry->m_hostname_length)
480           *hostname= my_strdup(key_memory_host_cache_hostname,
481                                entry->m_hostname, MYF(0));
482 
483         DBUG_PRINT("info",("IP (%s) has been found in the cache. "
484                            "Hostname: '%s'",
485                            ip_key,
486                            (*hostname? *hostname : "null")
487                           ));
488 
489         mysql_mutex_unlock(&hostname_cache->lock);
490 
491         DBUG_RETURN(0);
492       }
493     }
494 
495     mysql_mutex_unlock(&hostname_cache->lock);
496   }
497 
498   /*
499     Resolve host name. Return an error if a host name can not be resolved
500     (instead of returning the numeric form of the host name).
501   */
502 
503   char hostname_buffer[NI_MAXHOST];
504 
505   DBUG_PRINT("info", ("Resolving '%s'...", (const char *) ip_key));
506 
507   err_code= vio_getnameinfo(ip, hostname_buffer, NI_MAXHOST, NULL, 0,
508                             NI_NAMEREQD);
509 
510   /*
511   ===========================================================================
512   DEBUG code only (begin)
513   Simulate various output from vio_getnameinfo().
514   ===========================================================================
515   */
516 
517   DBUG_EXECUTE_IF("getnameinfo_error_noname",
518                   {
519                     strcpy(hostname_buffer, "<garbage>");
520                     err_code= EAI_NONAME;
521                   }
522                   );
523 
524   DBUG_EXECUTE_IF("getnameinfo_error_again",
525                   {
526                     strcpy(hostname_buffer, "<garbage>");
527                     err_code= EAI_AGAIN;
528                   }
529                   );
530 
531   DBUG_EXECUTE_IF("getnameinfo_fake_ipv4",
532                   {
533                     strcpy(hostname_buffer, "santa.claus.ipv4.example.com");
534                     err_code= 0;
535                   }
536                   );
537 
538   DBUG_EXECUTE_IF("getnameinfo_fake_ipv6",
539                   {
540                     strcpy(hostname_buffer, "santa.claus.ipv6.example.com");
541                     err_code= 0;
542                   }
543                   );
544 
545   DBUG_EXECUTE_IF("getnameinfo_format_ipv4",
546                   {
547                     strcpy(hostname_buffer, "12.12.12.12");
548                     err_code= 0;
549                   }
550                   );
551 
552   DBUG_EXECUTE_IF("getnameinfo_format_ipv6",
553                   {
554                     strcpy(hostname_buffer, "12:DEAD:BEEF:0");
555                     err_code= 0;
556                   }
557                   );
558 
559 
560   DBUG_EXECUTE_IF ("getnameinfo_fake_max_length",
561                   {
562                     std::string s(NI_MAXHOST-1, 'a');
563                     strcpy(hostname_buffer, s.c_str());
564                     err_code= 0;
565                   }
566                   );
567 
568   /*
569   ===========================================================================
570   DEBUG code only (end)
571   ===========================================================================
572   */
573 
574   if (err_code)
575   {
576     // NOTE: gai_strerror() returns a string ending by a dot.
577 
578     DBUG_PRINT("error", ("IP address '%s' could not be resolved: %s",
579                          ip_key,
580                          gai_strerror(err_code)));
581 
582     sql_print_warning("IP address '%s' could not be resolved: %s",
583                       ip_key,
584                       gai_strerror(err_code));
585 
586     bool validated;
587     if (vio_is_no_name_error(err_code))
588     {
589       /*
590         The no-name error means that there is no reverse address mapping
591         for the IP address. A host name can not be resolved.
592       */
593       errors.m_nameinfo_permanent= 1;
594       validated= true;
595     }
596     else
597     {
598       /*
599         If it is not the no-name error, we should not cache the hostname
600         (or rather its absence), because the failure might be transient.
601         Only the ip error statistics are cached.
602       */
603       errors.m_nameinfo_transient= 1;
604       validated= false;
605     }
606     add_hostname(ip_key, NULL, validated, &errors);
607 
608     DBUG_RETURN(0);
609   }
610 
611   DBUG_PRINT("info", ("IP '%s' resolved to '%s'.",
612                       (const char *) ip_key,
613                       (const char *) hostname_buffer));
614 
615   /*
616     Validate hostname: the server does not accept host names, which
617     resemble IP addresses.
618 
619     The thing is that theoretically, a host name can be in a form of IPv4
620     address (123.example.org, or 1.2 or even 1.2.3.4). We have to deny such
621     host names because ACL-systems is not designed to work with them.
622 
623     For example, it is possible to specify a host name mask (like
624     192.168.1.%) for an ACL rule. Then, if IPv4-like hostnames are allowed,
625     there is a security hole: instead of allowing access for
626     192.168.1.0/255 network (which was assumed by the user), the access
627     will be allowed for host names like 192.168.1.example.org.
628   */
629 
630   if (!is_hostname_valid(hostname_buffer))
631   {
632     DBUG_PRINT("error", ("IP address '%s' has been resolved "
633                          "to the host name '%s', which resembles "
634                          "IPv4-address itself.",
635                          ip_key,
636                          hostname_buffer));
637 
638     sql_print_warning("IP address '%s' has been resolved "
639                       "to the host name '%s', which resembles "
640                       "IPv4-address itself.",
641                       ip_key,
642                       hostname_buffer);
643 
644     errors.m_format= 1;
645     add_hostname(ip_key, hostname_buffer, false, &errors);
646 
647     DBUG_RETURN(false);
648   }
649 
650   /* Get IP-addresses for the resolved host name (FCrDNS technique). */
651 
652   struct addrinfo hints;
653   struct addrinfo *addr_info_list;
654   /*
655     Makes fault injection with DBUG_EXECUTE_IF easier.
656     Invoking free_addr_info(NULL) crashes on some platforms.
657   */
658   bool free_addr_info_list= false;
659 
660   memset(&hints, 0, sizeof (struct addrinfo));
661   hints.ai_flags= AI_PASSIVE;
662   hints.ai_socktype= SOCK_STREAM;
663   hints.ai_family= AF_UNSPEC;
664 
665   DBUG_PRINT("info", ("Getting IP addresses for hostname '%s'...",
666                       hostname_buffer));
667 
668   err_code= getaddrinfo(hostname_buffer, NULL, &hints, &addr_info_list);
669   if (err_code == 0)
670     free_addr_info_list= true;
671 
672   /*
673   ===========================================================================
674   DEBUG code only (begin)
675   Simulate various output from getaddrinfo().
676   ===========================================================================
677   */
678   DBUG_EXECUTE_IF("getaddrinfo_error_noname",
679                   {
680                     if (free_addr_info_list)
681                       freeaddrinfo(addr_info_list);
682 
683                     addr_info_list= NULL;
684                     err_code= EAI_NONAME;
685                     free_addr_info_list= false;
686                   }
687                   );
688 
689   DBUG_EXECUTE_IF("getaddrinfo_error_again",
690                   {
691                     if (free_addr_info_list)
692                       freeaddrinfo(addr_info_list);
693 
694                     addr_info_list= NULL;
695                     err_code= EAI_AGAIN;
696                     free_addr_info_list= false;
697                   }
698                   );
699 
700   DBUG_EXECUTE_IF("getaddrinfo_fake_bad_ipv4",
701                   {
702                     if (free_addr_info_list)
703                       freeaddrinfo(addr_info_list);
704 
705                     struct sockaddr_in *debug_addr;
706                     /*
707                       Not thread safe, which is ok.
708                       Only one connection at a time is tested with
709                       fault injection.
710                     */
711                     static struct sockaddr_in debug_sock_addr[2];
712                     static struct addrinfo debug_addr_info[2];
713                     /* Simulating ipv4 192.0.2.126 */
714                     debug_addr= & debug_sock_addr[0];
715                     debug_addr->sin_family= AF_INET;
716                     debug_addr->sin_addr.s_addr= inet_addr("192.0.2.126");
717 
718                     /* Simulating ipv4 192.0.2.127 */
719                     debug_addr= & debug_sock_addr[1];
720                     debug_addr->sin_family= AF_INET;
721                     debug_addr->sin_addr.s_addr= inet_addr("192.0.2.127");
722 
723                     debug_addr_info[0].ai_addr= (struct sockaddr*) & debug_sock_addr[0];
724                     debug_addr_info[0].ai_addrlen= sizeof (struct sockaddr_in);
725                     debug_addr_info[0].ai_next= & debug_addr_info[1];
726 
727                     debug_addr_info[1].ai_addr= (struct sockaddr*) & debug_sock_addr[1];
728                     debug_addr_info[1].ai_addrlen= sizeof (struct sockaddr_in);
729                     debug_addr_info[1].ai_next= NULL;
730 
731                     addr_info_list= & debug_addr_info[0];
732                     err_code= 0;
733                     free_addr_info_list= false;
734                   }
735                   );
736 
737   DBUG_EXECUTE_IF("getaddrinfo_fake_good_ipv4",
738                   {
739                     if (free_addr_info_list)
740                       freeaddrinfo(addr_info_list);
741 
742                     struct sockaddr_in *debug_addr;
743                     static struct sockaddr_in debug_sock_addr[2];
744                     static struct addrinfo debug_addr_info[2];
745                     /* Simulating ipv4 192.0.2.5 */
746                     debug_addr= & debug_sock_addr[0];
747                     debug_addr->sin_family= AF_INET;
748                     debug_addr->sin_addr.s_addr= inet_addr("192.0.2.5");
749 
750                     /* Simulating ipv4 192.0.2.4 */
751                     debug_addr= & debug_sock_addr[1];
752                     debug_addr->sin_family= AF_INET;
753                     debug_addr->sin_addr.s_addr= inet_addr("192.0.2.4");
754 
755                     debug_addr_info[0].ai_addr= (struct sockaddr*) & debug_sock_addr[0];
756                     debug_addr_info[0].ai_addrlen= sizeof (struct sockaddr_in);
757                     debug_addr_info[0].ai_next= & debug_addr_info[1];
758 
759                     debug_addr_info[1].ai_addr= (struct sockaddr*) & debug_sock_addr[1];
760                     debug_addr_info[1].ai_addrlen= sizeof (struct sockaddr_in);
761                     debug_addr_info[1].ai_next= NULL;
762 
763                     addr_info_list= & debug_addr_info[0];
764                     err_code= 0;
765                     free_addr_info_list= false;
766                   }
767                   );
768 
769 #ifdef HAVE_IPV6
770   DBUG_EXECUTE_IF("getaddrinfo_fake_bad_ipv6",
771                   {
772                     if (free_addr_info_list)
773                       freeaddrinfo(addr_info_list);
774 
775                     struct sockaddr_in6 *debug_addr;
776                     struct in6_addr *ip6;
777                     /*
778                       Not thread safe, which is ok.
779                       Only one connection at a time is tested with
780                       fault injection.
781                     */
782                     static struct sockaddr_in6 debug_sock_addr[2];
783                     static struct addrinfo debug_addr_info[2];
784                     /* Simulating ipv6 2001:DB8::6:7E */
785                     debug_addr= & debug_sock_addr[0];
786                     debug_addr->sin6_family= AF_INET6;
787                     ip6= & debug_addr->sin6_addr;
788                     /* inet_pton not available on Windows XP. */
789                     ip6->s6_addr[ 0] = 0x20;
790                     ip6->s6_addr[ 1] = 0x01;
791                     ip6->s6_addr[ 2] = 0x0d;
792                     ip6->s6_addr[ 3] = 0xb8;
793                     ip6->s6_addr[ 4] = 0x00;
794                     ip6->s6_addr[ 5] = 0x00;
795                     ip6->s6_addr[ 6] = 0x00;
796                     ip6->s6_addr[ 7] = 0x00;
797                     ip6->s6_addr[ 8] = 0x00;
798                     ip6->s6_addr[ 9] = 0x00;
799                     ip6->s6_addr[10] = 0x00;
800                     ip6->s6_addr[11] = 0x00;
801                     ip6->s6_addr[12] = 0x00;
802                     ip6->s6_addr[13] = 0x06;
803                     ip6->s6_addr[14] = 0x00;
804                     ip6->s6_addr[15] = 0x7e;
805 
806                     /* Simulating ipv6 2001:DB8::6:7F */
807                     debug_addr= & debug_sock_addr[1];
808                     debug_addr->sin6_family= AF_INET6;
809                     ip6= & debug_addr->sin6_addr;
810                     ip6->s6_addr[ 0] = 0x20;
811                     ip6->s6_addr[ 1] = 0x01;
812                     ip6->s6_addr[ 2] = 0x0d;
813                     ip6->s6_addr[ 3] = 0xb8;
814                     ip6->s6_addr[ 4] = 0x00;
815                     ip6->s6_addr[ 5] = 0x00;
816                     ip6->s6_addr[ 6] = 0x00;
817                     ip6->s6_addr[ 7] = 0x00;
818                     ip6->s6_addr[ 8] = 0x00;
819                     ip6->s6_addr[ 9] = 0x00;
820                     ip6->s6_addr[10] = 0x00;
821                     ip6->s6_addr[11] = 0x00;
822                     ip6->s6_addr[12] = 0x00;
823                     ip6->s6_addr[13] = 0x06;
824                     ip6->s6_addr[14] = 0x00;
825                     ip6->s6_addr[15] = 0x7f;
826 
827                     debug_addr_info[0].ai_addr= (struct sockaddr*) & debug_sock_addr[0];
828                     debug_addr_info[0].ai_addrlen= sizeof (struct sockaddr_in6);
829                     debug_addr_info[0].ai_next= & debug_addr_info[1];
830 
831                     debug_addr_info[1].ai_addr= (struct sockaddr*) & debug_sock_addr[1];
832                     debug_addr_info[1].ai_addrlen= sizeof (struct sockaddr_in6);
833                     debug_addr_info[1].ai_next= NULL;
834 
835                     addr_info_list= & debug_addr_info[0];
836                     err_code= 0;
837                     free_addr_info_list= false;
838                   }
839                   );
840 
841   DBUG_EXECUTE_IF("getaddrinfo_fake_good_ipv6",
842                   {
843                     if (free_addr_info_list)
844                       freeaddrinfo(addr_info_list);
845 
846                     struct sockaddr_in6 *debug_addr;
847                     struct in6_addr *ip6;
848                     /*
849                       Not thread safe, which is ok.
850                       Only one connection at a time is tested with
851                       fault injection.
852                     */
853                     static struct sockaddr_in6 debug_sock_addr[2];
854                     static struct addrinfo debug_addr_info[2];
855                     /* Simulating ipv6 2001:DB8::6:7 */
856                     debug_addr= & debug_sock_addr[0];
857                     debug_addr->sin6_family= AF_INET6;
858                     ip6= & debug_addr->sin6_addr;
859                     ip6->s6_addr[ 0] = 0x20;
860                     ip6->s6_addr[ 1] = 0x01;
861                     ip6->s6_addr[ 2] = 0x0d;
862                     ip6->s6_addr[ 3] = 0xb8;
863                     ip6->s6_addr[ 4] = 0x00;
864                     ip6->s6_addr[ 5] = 0x00;
865                     ip6->s6_addr[ 6] = 0x00;
866                     ip6->s6_addr[ 7] = 0x00;
867                     ip6->s6_addr[ 8] = 0x00;
868                     ip6->s6_addr[ 9] = 0x00;
869                     ip6->s6_addr[10] = 0x00;
870                     ip6->s6_addr[11] = 0x00;
871                     ip6->s6_addr[12] = 0x00;
872                     ip6->s6_addr[13] = 0x06;
873                     ip6->s6_addr[14] = 0x00;
874                     ip6->s6_addr[15] = 0x07;
875 
876                     /* Simulating ipv6 2001:DB8::6:6 */
877                     debug_addr= & debug_sock_addr[1];
878                     debug_addr->sin6_family= AF_INET6;
879                     ip6= & debug_addr->sin6_addr;
880                     ip6->s6_addr[ 0] = 0x20;
881                     ip6->s6_addr[ 1] = 0x01;
882                     ip6->s6_addr[ 2] = 0x0d;
883                     ip6->s6_addr[ 3] = 0xb8;
884                     ip6->s6_addr[ 4] = 0x00;
885                     ip6->s6_addr[ 5] = 0x00;
886                     ip6->s6_addr[ 6] = 0x00;
887                     ip6->s6_addr[ 7] = 0x00;
888                     ip6->s6_addr[ 8] = 0x00;
889                     ip6->s6_addr[ 9] = 0x00;
890                     ip6->s6_addr[10] = 0x00;
891                     ip6->s6_addr[11] = 0x00;
892                     ip6->s6_addr[12] = 0x00;
893                     ip6->s6_addr[13] = 0x06;
894                     ip6->s6_addr[14] = 0x00;
895                     ip6->s6_addr[15] = 0x06;
896 
897                     debug_addr_info[0].ai_addr= (struct sockaddr*) & debug_sock_addr[0];
898                     debug_addr_info[0].ai_addrlen= sizeof (struct sockaddr_in6);
899                     debug_addr_info[0].ai_next= & debug_addr_info[1];
900 
901                     debug_addr_info[1].ai_addr= (struct sockaddr*) & debug_sock_addr[1];
902                     debug_addr_info[1].ai_addrlen= sizeof (struct sockaddr_in6);
903                     debug_addr_info[1].ai_next= NULL;
904 
905                     addr_info_list= & debug_addr_info[0];
906                     err_code= 0;
907                     free_addr_info_list= false;
908                   }
909                   );
910 #endif /* HAVE_IPV6 */
911 
912   /*
913   ===========================================================================
914   DEBUG code only (end)
915   ===========================================================================
916   */
917 
918   if (err_code != 0)
919   {
920     sql_print_warning("Host name '%s' could not be resolved: %s",
921                       hostname_buffer,
922                       gai_strerror(err_code));
923 
924     bool validated;
925 
926     if (err_code == EAI_NONAME)
927     {
928       errors.m_addrinfo_permanent= 1;
929       validated= true;
930     }
931     else
932     {
933       /*
934         Don't cache responses when the DNS server is down, as otherwise
935         transient DNS failure may leave any number of clients (those
936         that attempted to connect during the outage) unable to connect
937         indefinitely.
938         Only cache error statistics.
939       */
940       errors.m_addrinfo_transient= 1;
941       validated= false;
942     }
943     add_hostname(ip_key, NULL, validated, &errors);
944 
945     DBUG_RETURN(false);
946   }
947 
948   /* Check that getaddrinfo() returned the used IP (FCrDNS technique). */
949 
950   DBUG_PRINT("info", ("The following IP addresses found for '%s':",
951                       hostname_buffer));
952 
953   for (struct addrinfo *addr_info= addr_info_list;
954        addr_info; addr_info= addr_info->ai_next)
955   {
956     char ip_buffer[HOST_ENTRY_KEY_SIZE];
957 
958     {
959       bool err_status MY_ATTRIBUTE((unused));
960       err_status=
961         vio_get_normalized_ip_string(addr_info->ai_addr, addr_info->ai_addrlen,
962                                      ip_buffer, sizeof (ip_buffer));
963       assert(!err_status);
964     }
965 
966     DBUG_PRINT("info", ("  - '%s'", ip_buffer));
967 
968     if (native_strcasecmp(ip_key, ip_buffer) == 0)
969     {
970       /* Copy host name string to be stored in the cache. */
971 
972       *hostname= my_strdup(key_memory_host_cache_hostname,
973                            hostname_buffer, MYF(0));
974 
975       if (!*hostname)
976       {
977         DBUG_PRINT("error", ("Out of memory."));
978 
979         if (free_addr_info_list)
980           freeaddrinfo(addr_info_list);
981         DBUG_RETURN(true);
982       }
983 
984       break;
985     }
986   }
987 
988   /* Log resolved IP-addresses if no match was found. */
989 
990   if (!*hostname)
991   {
992     errors.m_FCrDNS= 1;
993 
994     sql_print_warning("Hostname '%s' does not resolve to '%s'.",
995                       hostname_buffer,
996                       ip_key);
997     sql_print_information("Hostname '%s' has the following IP addresses:",
998                           hostname_buffer);
999 
1000     for (struct addrinfo *addr_info= addr_info_list;
1001          addr_info; addr_info= addr_info->ai_next)
1002     {
1003       char ip_buffer[HOST_ENTRY_KEY_SIZE];
1004 
1005 #ifndef NDEBUG
1006       bool err_status=
1007 #endif
1008         vio_get_normalized_ip_string(addr_info->ai_addr, addr_info->ai_addrlen,
1009                                      ip_buffer, sizeof (ip_buffer));
1010       assert(!err_status);
1011 
1012       sql_print_information(" - %s", ip_buffer);
1013     }
1014   }
1015 
1016   /* Add an entry for the IP to the cache. */
1017   add_hostname(ip_key, *hostname, true, &errors);
1018 
1019   /* Free the result of getaddrinfo(). */
1020   if (free_addr_info_list)
1021     freeaddrinfo(addr_info_list);
1022 
1023   DBUG_RETURN(false);
1024 }
1025