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>(host_cache_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   DBUG_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 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 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= (uint)len;
238 
239       DBUG_PRINT("info",
240                  ("Adding/Updating '%s' -> '%s' (validated) to the hostname cache...'",
241                  (const char *) ip_key,
242                  (const char *) 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                  (const char *) 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                (const char *) 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_hrtime().val;
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_hrtime().val;
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 
reset_host_connect_errors(const char * ip_string)324 void reset_host_connect_errors(const char *ip_string)
325 {
326   if (!ip_string)
327     return;
328 
329   char ip_key[HOST_ENTRY_KEY_SIZE];
330   prepare_hostname_cache_key(ip_string, ip_key);
331 
332   mysql_mutex_lock(&hostname_cache->lock);
333 
334   Host_entry *entry= hostname_cache_search(ip_key);
335 
336   if (entry)
337     entry->m_errors.clear_connect_errors();
338 
339   mysql_mutex_unlock(&hostname_cache->lock);
340 }
341 
is_ip_loopback(const struct sockaddr * ip)342 static inline bool is_ip_loopback(const struct sockaddr *ip)
343 {
344   switch (ip->sa_family) {
345   case AF_INET:
346     {
347       /* Check for IPv4 127.0.0.1. */
348       struct in_addr *ip4= &((struct sockaddr_in *) ip)->sin_addr;
349       return ntohl(ip4->s_addr) == INADDR_LOOPBACK;
350     }
351 
352 #ifdef HAVE_IPV6
353   case AF_INET6:
354     {
355       /* Check for IPv6 ::1. */
356       struct in6_addr *ip6= &((struct sockaddr_in6 *) ip)->sin6_addr;
357       return IN6_IS_ADDR_LOOPBACK(ip6);
358     }
359 #endif /* HAVE_IPV6 */
360 
361   default:
362     return FALSE;
363   }
364 }
365 
is_hostname_valid(const char * hostname)366 static inline bool is_hostname_valid(const char *hostname)
367 {
368   /*
369     A hostname is invalid if it starts with a number followed by a dot
370     (IPv4 address).
371   */
372 
373   if (!my_isdigit(&my_charset_latin1, hostname[0]))
374     return TRUE;
375 
376   const char *p= hostname + 1;
377 
378   while (my_isdigit(&my_charset_latin1, *p))
379     ++p;
380 
381   return *p != '.';
382 }
383 
384 /**
385   Resolve IP-address to host name.
386 
387   This function does the following things:
388     - resolves IP-address;
389     - employs Forward Confirmed Reverse DNS technique to validate IP-address;
390     - returns host name if IP-address is validated;
391     - set value to out-variable connect_errors -- this variable represents the
392       number of connection errors from the specified IP-address.
393     - update the host_cache statistics
394 
395   NOTE: connect_errors are counted (are supported) only for the clients
396   where IP-address can be resolved and FCrDNS check is passed.
397 
398   @param [in]  ip_storage IP address (sockaddr). Must be set.
399   @param [in]  ip_string  IP address (string). Must be set.
400   @param [out] hostname
401   @param [out] connect_errors
402 
403   @return Error status
404   @retval 0 Success
405   @retval RC_BLOCKED_HOST The host is blocked.
406 
407   The function does not set/report MySQL server error in case of failure.
408   It's caller's responsibility to handle failures of this function
409   properly.
410 */
411 
ip_to_hostname(struct sockaddr_storage * ip_storage,const char * ip_string,const char ** hostname,uint * connect_errors)412 int ip_to_hostname(struct sockaddr_storage *ip_storage,
413                    const char *ip_string,
414                    const char **hostname,
415                    uint *connect_errors)
416 {
417   const struct sockaddr *ip= (const sockaddr *) ip_storage;
418   int err_code;
419   bool err_status __attribute__((unused));
420   Host_errors errors;
421 
422   DBUG_ENTER("ip_to_hostname");
423   DBUG_PRINT("info", ("IP address: '%s'; family: %d.",
424                       (const char *) ip_string,
425                       (int) ip->sa_family));
426 
427   /* Default output values, for most cases. */
428   *hostname= NULL;
429   *connect_errors= 0;
430 
431   /* Check if we have loopback address (127.0.0.1 or ::1). */
432 
433   if (is_ip_loopback(ip))
434   {
435     DBUG_PRINT("info", ("Loopback address detected."));
436 
437     /* Do not count connect errors from localhost. */
438     *hostname= my_localhost;
439 
440     DBUG_RETURN(0);
441   }
442 
443   /* Prepare host name cache key. */
444 
445   char ip_key[HOST_ENTRY_KEY_SIZE];
446   prepare_hostname_cache_key(ip_string, ip_key);
447 
448   /* Check first if we have host name in the cache. */
449 
450   if (!(specialflag & SPECIAL_NO_HOST_CACHE))
451   {
452     ulonglong now= my_hrtime().val;
453 
454     mysql_mutex_lock(&hostname_cache->lock);
455 
456     Host_entry *entry= hostname_cache_search(ip_key);
457 
458     if (entry)
459     {
460       entry->m_last_seen= now;
461       *connect_errors= entry->m_errors.m_connect;
462 
463       if (unlikely(entry->m_errors.m_connect >= max_connect_errors))
464       {
465         entry->m_errors.m_host_blocked++;
466         entry->set_error_timestamps(now);
467         mysql_mutex_unlock(&hostname_cache->lock);
468         DBUG_RETURN(RC_BLOCKED_HOST);
469       }
470 
471       /*
472         If there is an IP -> HOSTNAME association in the cache,
473         but for a hostname that was not validated,
474         do not return that hostname: perform the network validation again.
475       */
476       if (entry->m_host_validated)
477       {
478         if (entry->m_hostname_length)
479           *hostname= my_strdup(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(hostname_buffer, MYF(0));
930 
931       if (!*hostname)
932       {
933         DBUG_PRINT("error", ("Out of memory."));
934 
935         if (free_addr_info_list)
936           freeaddrinfo(addr_info_list);
937         DBUG_RETURN(true);
938       }
939 
940       break;
941     }
942   }
943 
944   /* Log resolved IP-addresses if no match was found. */
945 
946   if (!*hostname)
947   {
948     errors.m_FCrDNS= 1;
949 
950     sql_print_warning("Hostname '%s' does not resolve to '%s'.",
951                       (const char *) hostname_buffer,
952                       (const char *) ip_key);
953     sql_print_information("Hostname '%s' has the following IP addresses:",
954                           (const char *) hostname_buffer);
955 
956     for (struct addrinfo *addr_info= addr_info_list;
957          addr_info; addr_info= addr_info->ai_next)
958     {
959       char ip_buffer[HOST_ENTRY_KEY_SIZE];
960 
961       err_status=
962         vio_get_normalized_ip_string(addr_info->ai_addr, (int)addr_info->ai_addrlen,
963                                      ip_buffer, sizeof (ip_buffer));
964       DBUG_ASSERT(!err_status);
965 
966       sql_print_information(" - %s", (const char *) ip_buffer);
967     }
968   }
969 
970   /* Add an entry for the IP to the cache. */
971   add_hostname(ip_key, *hostname, true, &errors);
972 
973   /* Free the result of getaddrinfo(). */
974   if (free_addr_info_list)
975     freeaddrinfo(addr_info_list);
976 
977   DBUG_RETURN(false);
978 }
979