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