MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:November 6 2009 1:15am
Subject:bzr commit into mysql-5.1-telco-7.0 branch (frazer:3196) Bug#45017
View as plain text  
#At file:///home/frazer/bzr/mysql-5.1-telco-7.0/

 3196 Frazer Clement	2009-11-06
      Bug47757 MySQL Cluster : port bug#45017 to 7.0 (ipv6)
      modified:
        sql-common/client.c

=== modified file 'sql-common/client.c'
--- a/sql-common/client.c	2009-10-01 07:16:52 +0000
+++ b/sql-common/client.c	2009-11-06 01:15:42 +0000
@@ -2048,9 +2048,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
       (!mysql->options.protocol ||
        mysql->options.protocol == MYSQL_PROTOCOL_TCP))
   {
-    struct addrinfo *res_lst= NULL, hints;
+    struct addrinfo *res_lst= NULL, *client_bind_ai_lst= NULL, *t_res, hints;
     int gai_errno;
     char port_buf[NI_MAXSERV];
+    my_socket sock= my_socket_create_invalid();
+    int saved_error, status= -1, bind_result= 0;
  
     unix_socket=0;				/* This is not used */
     if (!port)
@@ -2095,112 +2097,161 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
       goto error;
     }
 
-    /* We only look at the first item (something to think about changing in the future) */
+    /* Get address info for client bind name if it is provided */
+    if (mysql->options.bind_name) 
+    {
+      int bind_gai_errno= 0;
+
+      DBUG_PRINT("info",("Resolving addresses for client bind name : %s",
+                         mysql->options.bind_name));
+      /* Lookup address info for name */
+      bind_gai_errno= getaddrinfo(mysql->options.bind_name, 0,
+                                  &hints, &client_bind_ai_lst);
+      if (bind_gai_errno)
+      {
+        DBUG_PRINT("info",("client bind getaddrinfo error %d", bind_gai_errno));
+        set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate,
+                                 ER(CR_UNKNOWN_HOST), mysql->options.bind_name, errno);
+        
+        if (client_bind_ai_lst)
+          freeaddrinfo(client_bind_ai_lst);
+        
+        freeaddrinfo(res_lst);
+        goto error;
+      }
+      DBUG_PRINT("info", ("  got address info for client bind name"));
+    }
+
+    /* 
+      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 each IP address, attempt to bind the socket to each client address 
+      for the client-side bind hostname until the bind is successful.
+    */
+    my_bool create_ok, bind_ok;
+    for (t_res= res_lst; t_res; t_res= t_res->ai_next)    
     {
       DBUG_PRINT("info",("Creating socket : Family %d, Type %d, Protocol %d",
-                         res_lst->ai_family, res_lst->ai_socktype, res_lst->ai_protocol));
-      sock= my_socket_create(res_lst->ai_family, res_lst->ai_socktype, res_lst->ai_protocol);
+                         t_res->ai_family, t_res->ai_socktype, t_res->ai_protocol));
+      create_ok= bind_ok= 0;
+      sock= my_socket_create(t_res->ai_family, t_res->ai_socktype, t_res->ai_protocol);
       if (!my_socket_valid(sock))
       {
         DBUG_PRINT("info",("Socket created was invalid"));
-        set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
-                                 ER(CR_IPSOCK_ERROR), socket_errno);
-        
-        freeaddrinfo(res_lst);
-        goto error; 
+        /* Try next address if there is one */
+        saved_error= socket_errno;
+        continue;
       }
+      create_ok= 1;
 
-      if (mysql->options.bind_name) {
+      if (client_bind_ai_lst) 
+      {
         /* TODOs for client bind:
            - check error codes
            - don't use socket for localhost if this option is given
         */
-        struct addrinfo* clientBindAddrInfo= NULL;
-        struct addrinfo* currAddr= NULL;
-        int gai_errno= 0;
-        int bindResult= -1;
-
-        DBUG_PRINT("info",("Attempting client bind to address : %s",
-                           mysql->options.bind_name));
-        /* Lookup address info for name */
-        gai_errno= getaddrinfo(mysql->options.bind_name, 0,
-                               &hints, &clientBindAddrInfo);
-        if (gai_errno)
-        {
-          DBUG_PRINT("info",("getaddrinfo error %d", gai_errno));
-          set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate,
-                                   ER(CR_UNKNOWN_HOST), mysql->options.bind_name, errno);
+        struct addrinfo* curr_bind_ai= NULL;
+        DBUG_PRINT("info", ("Attempting to bind socket to bind address(es)"));
 
-          if (clientBindAddrInfo)
-            freeaddrinfo(clientBindAddrInfo);
-          
-          freeaddrinfo(res_lst);
-          goto error;
-        }
-        
-        DBUG_PRINT("info",("Got address info for address, attempting bind"));
-        
-        /* We'll attempt to bind to each of the addresses returned, until
-         * we find one that works
-         */
-        currAddr= clientBindAddrInfo;
+        /* 
+           We'll attempt to bind to each of the addresses returned, until
+           we find one that works.
+           If none works, we'll try the next destination host address
+           (if any)
+        */
+        curr_bind_ai= client_bind_ai_lst;
 
-        while((currAddr != NULL) && (bindResult != 0))
+        while (curr_bind_ai != NULL)
         {
-          /* Bind the socket to the given address */
-          bindResult= my_bind(sock, 
-                              currAddr->ai_addr, 
-                              currAddr->ai_addrlen);
-
-          if (bindResult)
-          {
-            DBUG_PRINT("info",("bind failed, attempting another bind address"));
-            /* Problem with the bind, move to next address if present */
-            currAddr= currAddr->ai_next;
-          }
+          /* Attempt to bind the socket to the given address */
+          bind_result= my_bind(sock, 
+                               curr_bind_ai->ai_addr, 
+                               curr_bind_ai->ai_addrlen);
+
+          if (!bind_result)
+            break;   /* Success */
+
+          DBUG_PRINT("info", ("bind failed, attempting another bind address"));
+          /* Problem with the bind, move to next address if present */
+          curr_bind_ai= curr_bind_ai->ai_next;
         }
 
-        freeaddrinfo(clientBindAddrInfo);
-
-        if (bindResult)
+        if (bind_result)
         {
-          set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
-                                   ER(CR_IPSOCK_ERROR), mysql->options.bind_name, errno);
-          freeaddrinfo(res_lst);
-          goto error;
+          DBUG_PRINT("info", ("All bind attempts with this address failed"));
+          saved_error= errno;
+          my_socket_close(sock);
+          my_socket_invalidate(&sock);
+          
+          /* 
+             Could not bind to any client-side address with this destination
+             Try the next destination address (if any)
+          */
+          continue;
         }
         DBUG_PRINT("info", ("Successfully bound client side of socket"));
       }
+      bind_ok= 1;
 
-      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
-      if (! net->vio )
+      status= my_connect(MY_SOCKET_FORMAT_VALUE(sock), t_res->ai_addr, t_res->ai_addrlen,
+                         mysql->options.connect_timeout);
+      
+      if (!status)
       {
-        DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
-        set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
-        my_socket_close(sock);
-        my_socket_invalidate(&sock);
-        freeaddrinfo(res_lst);
-        goto error;
+        break;    /* Success */
       }
 
-      if (my_connect(MY_SOCKET_FORMAT_VALUE(sock), res_lst->ai_addr, res_lst->ai_addrlen,
-                     mysql->options.connect_timeout))
+      /*
+        Save value as socket errno might be overwritten due to
+        calling a socket function below.
+      */
+      saved_error= socket_errno;
+
+      my_socket_close(sock);
+      my_socket_invalidate(&sock);
+    }
+
+    freeaddrinfo(res_lst);
+    if (client_bind_ai_lst)
+      freeaddrinfo(client_bind_ai_lst);
+
+    if (status != 0)
+    {
+      /* Some error creating socket, binding client side, or connecting */
+      assert(!my_socket_valid(sock));
+      if (!create_ok)
       {
-        DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,
-                            host));
+        DBUG_PRINT("error",("Got error %d when attempting to create socket",
+                            saved_error));
+        set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
+                                 ER(CR_IPSOCK_ERROR), saved_error);
+      }
+      else if (!bind_ok)
+      {
+        DBUG_PRINT("error",("Got error %d when attempting client socket bind",
+                            saved_error));
+        set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
+                                 ER(CR_IPSOCK_ERROR), mysql->options.bind_name, saved_error);
+      }
+      else
+      {
+        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, socket_errno);
-        vio_delete(net->vio);
-        net->vio = 0;
-        my_socket_close(sock);
-        my_socket_invalidate(&sock);
-        freeaddrinfo(res_lst);
-
-        goto error; 
+                                 ER(CR_CONN_HOST_ERROR), host, saved_error);
       }
+      goto error;
     }
 
-    freeaddrinfo(res_lst);
+    /* Managed to connect if we get here, now setup VIO */
+    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);
+      my_socket_close(sock);
+      my_socket_invalidate(&sock);
+      goto error;
+    }
   }
 
   if (!net->vio)

Thread
bzr commit into mysql-5.1-telco-7.0 branch (frazer:3196) Bug#45017Frazer Clement6 Nov