List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:August 4 2009 12:54pm
Subject:bzr push into mysql-pe branch (davi:3510 to 3512) Bug#45017
View as plain text  
 3512 Davi Arnaut	2009-08-04 [merge]
      Bug#45017: Failure to connect if hostname maps to multiple addresses
      
      The problem is that the C API function mysql_real_connect
      only attempts to connect to the first IP address returned
      for a hostname. This can be a problem if a hostname maps
      to multiple IP address and the server is not bound to the
      first one that is returned.
      
      The solution is to augment mysql_real_connect so that it
      attempts to connect to all IPv4/6 addresses that a domain
      name maps to. The function goes over the list of address
      until a successful connection is established.
      
      No test case is provided as its not possible to test this
      automatically with the current testing infrastructure.
     @ sql-common/client.c
        The client will try to connect to each address from the
        list of addresses that hostname maps to until a successful
        connection is established or there are no more address.

    modified:
      sql-common/client.c
 3511 Davi Arnaut	2009-08-04 [merge]
      Null merge bug 45017. Another fix will follow.

 3510 Satya B	2009-08-04 [merge]
      merge 5.1-bugteam branch to mysql-pe branch

=== modified file 'sql-common/client.c'
--- a/sql-common/client.c	2009-07-08 07:30:40 +0000
+++ b/sql-common/client.c	2009-08-04 12:53:39 +0000
@@ -2378,6 +2378,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
     struct addrinfo *res_lst, hints, *t_res;
     int gai_errno;
     char port_buf[NI_MAXSERV];
+    my_socket sock= SOCKET_ERROR;
+    int saved_error, status= -1;
 
     unix_socket=0;				/* This is not used */
 
@@ -2422,44 +2424,58 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
       goto error;
     }
 
-    /* We only look at the first item (something to think about changing in the future) */
-    t_res= res_lst; 
+    /*
+      A hostname might map to multiple IP addresses (IPv4/IPv6). Go over the
+      list of IP addresses until a successful connection can be established.
+    */
+    for (t_res= res_lst; t_res; t_res= t_res->ai_next)
     {
-      my_socket sock= socket(t_res->ai_family, t_res->ai_socktype,
-                             t_res->ai_protocol);
+      sock= socket(t_res->ai_family, t_res->ai_socktype, t_res->ai_protocol);
       if (sock == SOCKET_ERROR)
       {
-        set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
-                                 ER(CR_IPSOCK_ERROR), socket_errno);
-        freeaddrinfo(res_lst);
-        goto error;
+        saved_error= socket_errno;
+        continue;
       }
 
-      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
-      if (! net->vio )
-      {
-        DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
-        set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
-        closesocket(sock);
-        freeaddrinfo(res_lst);
-        goto error;
-      }
+      status= my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
+                         mysql->options.connect_timeout);
+      if (!status)
+        break;
 
-      if (my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
-                     mysql->options.connect_timeout))
-      {
-        DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,
-                            host));
-        set_mysql_extended_error(mysql, CR_CONN_HOST_ERROR, unknown_sqlstate,
-                                 ER(CR_CONN_HOST_ERROR), host, socket_errno);
-        vio_delete(net->vio);
-        net->vio= 0;
-        freeaddrinfo(res_lst);
-        goto error;
-      }
+      /*
+        Save value as socket errno might be overwritten due to
+        calling a socket function below.
+      */
+      saved_error= socket_errno;
+
+      closesocket(sock);
     }
 
     freeaddrinfo(res_lst);
+
+    if (sock == SOCKET_ERROR)
+    {
+      set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
+                                ER(CR_IPSOCK_ERROR), saved_error);
+      goto error;
+    }
+
+    if (status)
+    {
+      DBUG_PRINT("error",("Got error %d on connect to '%s'", saved_error, host));
+      set_mysql_extended_error(mysql, CR_CONN_HOST_ERROR, unknown_sqlstate,
+                                ER(CR_CONN_HOST_ERROR), host, saved_error);
+      goto error;
+    }
+
+    net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
+    if (! net->vio )
+    {
+      DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
+      set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
+      closesocket(sock);
+      goto error;
+    }
   }
 
   if (!net->vio)


Attachment: [text/bzr-bundle] bzr/davi.arnaut@sun.com-20090804125339-bsxnlamxyfsnjws3.bundle
Thread
bzr push into mysql-pe branch (davi:3510 to 3512) Bug#45017Davi Arnaut4 Aug