changeset 952:a490d94a5b8e

2008-03-28 Brian Masney <masneyb@gftp.org> * lib/Makefile.am lib/misc.c lib/socket-connect.c lib/socket-connect-getaddrinfo.c lib/socket-connect-gethostbyname.c lib/sockutils.c lib/gftp.h - cleaned up more of the socket functions and split them up into their own files. Cleanups and bug fixes to the DNS lookup code.
author masneyb
date Fri, 28 Mar 2008 11:44:36 +0000
parents 99f8858bbf02
children b2c90c337e08
files ChangeLog lib/Makefile.am lib/gftp.h lib/misc.c lib/socket-connect-getaddrinfo.c lib/socket-connect-gethostbyname.c lib/socket-connect.c lib/sockutils.c
diffstat 8 files changed, 413 insertions(+), 348 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat Mar 08 11:36:14 2008 +0000
+++ b/ChangeLog	Fri Mar 28 11:44:36 2008 +0000
@@ -1,3 +1,10 @@
+2008-03-28 Brian Masney <masneyb@gftp.org>
+	* lib/Makefile.am lib/misc.c lib/socket-connect.c
+	lib/socket-connect-getaddrinfo.c lib/socket-connect-gethostbyname.c
+	lib/sockutils.c lib/gftp.h - cleaned up more of the socket functions
+	and split them up into their own files. Cleanups and bug fixes to the
+	DNS lookup code.
+
 2008-03-04 Brian Masney <masneyb@gftp.org>
 	* lib/gftp.h lib/socket-connect.c lib/sockutils.c lib/protocols.c
 	lib/Makefile.am lib/charset-conv.c lib/parse-dir-listing.c - split
--- a/lib/Makefile.am	Sat Mar 08 11:36:14 2008 +0000
+++ b/lib/Makefile.am	Fri Mar 28 11:44:36 2008 +0000
@@ -5,6 +5,7 @@
 libgftp_a_SOURCES=bookmark.c cache.c charset-conv.c config_file.c fsp.c ftps.c \
                   https.c local.c misc.c mkstemps.c parse-dir-listing.c \
                   protocols.c pty.c rfc959.c rfc2068.c sshv2.c sslcommon.c \
-                  socket-connect.c sockutils.c
+                  socket-connect.c socket-connect-getaddrinfo.c \
+                  socket-connect-gethostbyname.c sockutils.c
 INCLUDES=@GLIB_CFLAGS@ @PTHREAD_CFLAGS@ -I../intl -DSHARE_DIR=\"$(datadir)/gftp\" -DLOCALE_DIR=\"$(datadir)/locale\"
 noinst_HEADERS=gftp.h ftpcommon.h httpcommon.h options.h
--- a/lib/gftp.h	Sat Mar 08 11:36:14 2008 +0000
+++ b/lib/gftp.h	Fri Mar 28 11:44:36 2008 +0000
@@ -385,10 +385,8 @@
   int wakeup_main_thread[2];	/* FD that gets written to by the threads
                                    to wakeup the parent */
 
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
   void *remote_addr;
   size_t remote_addr_len;
-#endif
   int ai_family;
 
   int server_type;		/* The type of server we are connected to.
@@ -1010,15 +1008,6 @@
 					  void (*update_func) 
 						( gftp_transfer * transfer ));
 
-struct hostent *r_gethostbyname 	( const char *name, 
-					  struct hostent *result_buf, 
-					  int *h_errnop );
-
-struct servent *r_getservbyname 	( const char *name, 
-					  const char *proto,
-					  /*@out@*/ struct servent *result_buf, 
-					  int *h_errnop );
-
 int gftp_set_config_options 		( gftp_request * request );
 
 void print_file_list 			( GList * list );
@@ -1094,6 +1083,29 @@
 					  char *proxy_hostname,
 					  unsigned int proxy_port );
 
+/* socket-connect-getaddrinfo.c */
+struct addrinfo * lookup_host_with_getaddrinfo
+					( gftp_request *request,
+					  char *service,
+					  char *proxy_hostname,
+					  int proxy_port );
+
+int gftp_connect_server_with_getaddrinfo
+					( gftp_request * request,
+					  char *service,
+					  char *proxy_hostname,
+					  unsigned int proxy_port );
+
+/* socket-connect-gethostbyname.c */
+int lookup_host_with_gethostbyname	( gftp_request *request,
+					  char *proxy_hostname,
+					  struct hostent *hostp );
+
+int gftp_connect_server_legacy		( gftp_request * request,
+					  char *service,
+					  char *proxy_hostname,
+					  unsigned int proxy_port );
+
 /* sockutils.c */
 ssize_t gftp_get_line 			( gftp_request * request, 
 					  /*@out@*/ gftp_getline_buffer ** rbuf,
@@ -1122,3 +1134,8 @@
 					  int fd, 
 					  int non_blocking );
 
+struct servent * r_getservbyname	( const char *name,
+					  const char *proto,
+					  struct servent *result_buf,
+					  int *h_errnop );
+
--- a/lib/misc.c	Sat Mar 08 11:36:14 2008 +0000
+++ b/lib/misc.c	Fri Mar 28 11:44:36 2008 +0000
@@ -930,60 +930,6 @@
 }
 
 
-struct hostent *
-r_gethostbyname (const char *name, struct hostent *result_buf, int *h_errnop)
-{
-  static GStaticMutex hostfunclock = G_STATIC_MUTEX_INIT; 
-  struct hostent *hent;
-
-  if (g_thread_supported ())
-    g_static_mutex_lock (&hostfunclock);
-
-  if ((hent = gethostbyname (name)) == NULL)
-    {
-      if (h_errnop)
-        *h_errnop = h_errno;
-    }
-  else
-    {
-      *result_buf = *hent;
-      hent = result_buf;
-    }
-
-  if (g_thread_supported ())
-    g_static_mutex_unlock (&hostfunclock);
-
-  return (hent);
-}
-
-
-struct servent *
-r_getservbyname (const char *name, const char *proto,
-                 struct servent *result_buf, int *h_errnop)
-{
-  static GStaticMutex servfunclock = G_STATIC_MUTEX_INIT;
-  struct servent *sent;
-
-  if (g_thread_supported ())
-    g_static_mutex_lock (&servfunclock);
-
-  if ((sent = getservbyname (name, proto)) == NULL)
-    {
-      if (h_errnop)
-        *h_errnop = h_errno;
-    }
-  else
-    {
-      *result_buf = *sent;
-      sent = result_buf;
-    }
-
-  if (g_thread_supported ())
-    g_static_mutex_unlock (&servfunclock);
-  return (sent);
-}
-
-
 char *
 base64_encode (char *str)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/socket-connect-getaddrinfo.c	Fri Mar 28 11:44:36 2008 +0000
@@ -0,0 +1,158 @@
+/*****************************************************************************/
+/*  socket-connect-getaddrinfo.c - uses getaddrinfo for connections          */
+/*  Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org>                  */
+/*                                                                           */
+/*  This program is free software; you can redistribute it and/or modify     */
+/*  it under the terms of the GNU General Public License as published by     */
+/*  the Free Software Foundation; either version 2 of the License, or        */
+/*  (at your option) any later version.                                      */
+/*                                                                           */
+/*  This program is distributed in the hope that it will be useful,          */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/*  GNU General Public License for more details.                             */
+/*                                                                           */
+/*  You should have received a copy of the GNU General Public License        */
+/*  along with this program; if not, write to the Free Software              */
+/*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+
+static int
+get_port (struct addrinfo *addr)
+{
+  struct sockaddr_in * saddr;
+  int port;
+
+  if (addr->ai_family == AF_INET)
+    {
+      saddr = (struct sockaddr_in *) addr->ai_addr;
+      port = ntohs (saddr->sin_port);
+    }
+  else
+    port = 0;
+
+  return (port);
+}
+
+
+struct addrinfo *
+lookup_host_with_getaddrinfo (gftp_request *request, char *service,
+                              char *proxy_hostname, int proxy_port)
+{
+  struct addrinfo hints, *hostp;
+  intptr_t enable_ipv6;
+  char serv[8], *connect_host;
+  int ret, connect_port;
+
+  if (request->use_proxy)
+    {
+      connect_host = proxy_hostname;
+      connect_port = proxy_port;
+    }
+  else
+    {
+      connect_host = request->hostname;
+      connect_port = request->port;
+    }
+
+  gftp_lookup_request_option (request, "enable_ipv6", &enable_ipv6);
+
+  memset (&hints, 0, sizeof (hints));
+  hints.ai_flags = AI_CANONNAME;
+
+  hints.ai_family = enable_ipv6 ? PF_UNSPEC : AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+
+  if (connect_port == 0)
+    strcpy (serv, service); 
+  else
+    snprintf (serv, sizeof (serv), "%d", connect_port);
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Looking up %s\n"), connect_host);
+  if ((ret = getaddrinfo (connect_host, serv, &hints, 
+                             &hostp)) != 0)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot look up hostname %s: %s\n"),
+                                 connect_host, gai_strerror (ret));
+      return (NULL);
+    }
+
+  return (hostp);
+}
+
+
+int
+gftp_connect_server_with_getaddrinfo (gftp_request * request, char *service,
+                                      char *proxy_hostname,
+                                      unsigned int proxy_port)
+{
+  struct addrinfo *res, *hostp, *current_hostp;
+  unsigned int port;
+  int sock = -1;
+
+  hostp = lookup_host_with_getaddrinfo (request, service, proxy_hostname,
+                                        proxy_port);
+  if (hostp == NULL)
+    return (GFTP_ERETRYABLE);
+
+  for (res = hostp; res != NULL; res = res->ai_next)
+    {
+      port = get_port (res);
+      if (!request->use_proxy)
+        request->port = port;
+
+      if ((sock = socket (res->ai_family, res->ai_socktype, 
+                          res->ai_protocol)) < 0)
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Failed to create a socket: %s\n"),
+                                     g_strerror (errno));
+          continue; 
+        } 
+
+      request->logging_function (gftp_logging_misc, request,
+                                 _("Trying %s:%d\n"), res[0].ai_canonname,
+                                 port);
+
+      if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Cannot connect to %s: %s\n"),
+                                     res[0].ai_canonname, g_strerror (errno));
+          close (sock);
+          continue;
+        }
+
+      current_hostp = res;
+      request->ai_family = res->ai_family;
+      break;
+    }
+
+  if (res == NULL)
+    {
+      if (hostp != NULL)
+        freeaddrinfo (hostp);
+      
+      return (GFTP_ERETRYABLE);
+    }
+
+  request->remote_addr_len = current_hostp->ai_addrlen;
+  request->remote_addr = g_malloc0 (request->remote_addr_len);
+  memcpy (request->remote_addr, &((struct sockaddr_in *) current_hostp->ai_addr)->sin_addr,
+          request->remote_addr_len);
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Connected to %s:%d\n"), res[0].ai_canonname,
+                             port);
+
+  return (sock);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/socket-connect-gethostbyname.c	Fri Mar 28 11:44:36 2008 +0000
@@ -0,0 +1,165 @@
+/*****************************************************************************/
+/*  socket-connect.c - contains functions for connecting to a server         */
+/*  Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org>                  */
+/*                                                                           */
+/*  This program is free software; you can redistribute it and/or modify     */
+/*  it under the terms of the GNU General Public License as published by     */
+/*  the Free Software Foundation; either version 2 of the License, or        */
+/*  (at your option) any later version.                                      */
+/*                                                                           */
+/*  This program is distributed in the hope that it will be useful,          */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/*  GNU General Public License for more details.                             */
+/*                                                                           */
+/*  You should have received a copy of the GNU General Public License        */
+/*  along with this program; if not, write to the Free Software              */
+/*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+#if !defined (HAVE_GETADDRINFO) || !defined (HAVE_GAI_STRERROR)
+
+static struct hostent *
+r_gethostbyname (const char *name, struct hostent *result_buf, int *h_errnop)
+{
+  static GStaticMutex hostfunclock = G_STATIC_MUTEX_INIT; 
+  struct hostent *hent;
+
+  if (g_thread_supported ())
+    g_static_mutex_lock (&hostfunclock);
+
+  if ((hent = gethostbyname (name)) == NULL)
+    {
+      if (h_errnop)
+        *h_errnop = h_errno;
+    }
+  else
+    {
+      *result_buf = *hent;
+      hent = result_buf;
+    }
+
+  if (g_thread_supported ())
+    g_static_mutex_unlock (&hostfunclock);
+
+  return (hent);
+}
+
+
+int
+lookup_host_with_gethostbyname (gftp_request *request, char *proxy_hostname,
+                                struct hostent *hostp)
+{
+  char *connect_host;
+
+  if (request->use_proxy)
+    connect_host = proxy_hostname;
+  else
+    connect_host = request->hostname;
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Looking up %s\n"), connect_host);
+
+  if ((r_gethostbyname (connect_host, hostp, NULL)) == NULL)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot look up hostname %s: %s\n"),
+                                 connect_host, g_strerror (errno));
+      return (GFTP_ERETRYABLE);
+    }
+
+  return (0);
+}
+
+
+int
+gftp_connect_server_legacy (gftp_request * request, char *service,
+                            char *proxy_hostname, unsigned int proxy_port)
+{
+  int sock, curhost, ret, connect_port;
+  struct sockaddr_in remote_address;
+  struct servent serv_struct;
+  struct hostent host;
+
+  ret = lookup_host_with_gethostbyname (request, proxy_hostname, &host);
+  if (ret != 0)
+    return (ret);
+
+  if (request->use_proxy)
+    connect_port = proxy_port;
+  else
+    connect_port = request->port;
+
+  if (connect_port == 0)
+    {
+      if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Cannot look up service name %s/tcp. Please check your services file\n"),
+                                     service);
+          return (GFTP_ERETRYABLE);
+        }
+
+      connect_port = ntohs (serv_struct.s_port);
+
+      if (!request->use_proxy)
+        request->port = connect_port;
+    }
+
+  sock = GFTP_ERETRYABLE;
+  request->ai_family = AF_INET;
+
+  for (curhost = 0; host.h_addr_list[curhost] != NULL; curhost++)
+    {
+      if ((sock = socket (request->ai_family, SOCK_STREAM, IPPROTO_TCP)) < 0)
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Failed to create a IPv4 socket: %s\n"),
+                                     g_strerror (errno));
+          return (GFTP_ERETRYABLE);
+        }
+
+      memset (&remote_address, 0, sizeof (remote_address));
+      remote_address.sin_family = AF_INET;
+      remote_address.sin_port = htons (connect_port);
+
+      memcpy (&remote_address.sin_addr,
+              host.h_addr_list[curhost],
+              host.h_length);
+
+      request->logging_function (gftp_logging_misc, request,
+                                 _("Trying %s:%d\n"),
+                                 host.h_name, ntohs (remote_address.sin_port));
+
+      if (connect (sock, (struct sockaddr *) &remote_address,
+                   sizeof (remote_address)) == -1)
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Cannot connect to %s: %s\n"),
+                                     host.h_name, g_strerror (errno));
+          close (sock);
+          continue;
+        }
+
+      break;
+    }
+
+  if (host.h_addr_list[curhost] == NULL)
+    return (GFTP_ERETRYABLE);
+
+  request->remote_addr_len = host.h_length;
+  request->remote_addr = g_malloc0 (request->remote_addr_len);
+  memcpy (request->remote_addr, &host.h_addr_list[curhost],
+          request->remote_addr_len);
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Connected to %s:%d\n"), host.h_name,
+                             ntohs (remote_address.sin_port));
+
+  return (sock);
+}
+
+#endif
--- a/lib/socket-connect.c	Sat Mar 08 11:36:14 2008 +0000
+++ b/lib/socket-connect.c	Fri Mar 28 11:44:36 2008 +0000
@@ -20,26 +20,21 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
 
-/* FIXME - clean up this function */
 static int
 gftp_need_proxy (gftp_request * request, char *service, char *proxy_hostname, 
-                 unsigned int proxy_port)
+                 unsigned int proxy_port, void **connect_data)
 {
   gftp_config_list_vars * proxy_hosts;
   gftp_proxy_hosts * hostname;
   size_t hostlen, domlen;
   unsigned char addy[4];
-  struct sockaddr *addr;
   GList * templist;
   gint32 netaddr;
   char *pos;
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-  struct addrinfo hints, *hostp;
-  unsigned int port;
-  int errnum;
-  char serv[8];
-#else
-  struct hostent host, *hostp;
+
+#if !defined (HAVE_GETADDRINFO) || !defined (HAVE_GAI_STRERROR)
+  struct hostent host;
+  int ret;
 #endif
 
   gftp_lookup_global_option ("dont_use_proxy", &proxy_hosts);
@@ -50,48 +45,22 @@
     return (proxy_hostname != NULL && 
             *proxy_hostname != '\0');
 
-  hostp = NULL;
 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-  memset (&hints, 0, sizeof (hints));
-  hints.ai_flags = AI_CANONNAME;
-  hints.ai_family = PF_UNSPEC;
-  hints.ai_socktype = SOCK_STREAM;
-
-  port = request->use_proxy ? proxy_port : request->port;
-  if (port == 0)
-    strcpy (serv, service);
-  else
-    snprintf (serv, sizeof (serv), "%d", port);
 
-  request->logging_function (gftp_logging_misc, request,
-                             _("Looking up %s\n"), request->hostname);
-
-  if ((errnum = getaddrinfo (request->hostname, serv, &hints, 
-                             &hostp)) != 0)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot look up hostname %s: %s\n"),
-                                 request->hostname, gai_strerror (errnum));
-      return (GFTP_ERETRYABLE);
-    }
-
-  addr = hostp->ai_addr;
+  *connect_data = lookup_host_with_getaddrinfo (request, service,
+                                                proxy_hostname, proxy_port);
+  if (*connect_data == NULL)
+    return (GFTP_ERETRYABLE);
 
 #else /* !HAVE_GETADDRINFO */
-  request->logging_function (gftp_logging_misc, request,
-                             _("Looking up %s\n"), request->hostname);
 
-  if (!(hostp = r_gethostbyname (request->hostname, &host, NULL)))
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot look up hostname %s: %s\n"),
-                                 request->hostname, g_strerror (errno));
-      return (GFTP_ERETRYABLE);
-    }
+  ret = lookup_host_with_gethostbyname (request, proxy_hostname, &host);
+  if (ret != 0)
+    return (ret);
 
-  addr = (struct sockaddr *) host.h_addr_list[0];
+  connect_data = NULL; /* FIXME */
 
-#endif /* HAVE_GETADDRINFO */
+#endif
 
   templist = proxy_hosts->list;
   while (templist != NULL)
@@ -111,7 +80,7 @@
 
       if (hostname->ipv4_network_address != 0)
         {
-          memcpy (addy, addr, sizeof (*addy));
+          memcpy (addy, request->remote_addr, sizeof (*addy));
           netaddr =
             (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) |
              ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) & 
@@ -126,248 +95,23 @@
 }
 
 
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-static int
-get_port (struct addrinfo *addr)
-{
-  struct sockaddr_in * saddr;
-  int port;
-
-  if (addr->ai_family == AF_INET)
-    {
-      saddr = (struct sockaddr_in *) addr->ai_addr;
-      port = ntohs (saddr->sin_port);
-    }
-  else
-    port = 0;
-
-  return (port);
-}
-
-
-static int
-gftp_connect_server_with_getaddr (gftp_request * request, char *service,
-                                  char *proxy_hostname, unsigned int proxy_port)
-{
-  struct addrinfo *hostp, *current_hostp;
-  char *connect_host, *disphost;
-  struct addrinfo hints, *res;
-  intptr_t enable_ipv6;
-  unsigned int port;
-  int ret, sock = -1;
-  char serv[8];
-
-  if ((ret = gftp_need_proxy (request, service, proxy_hostname,
-                                 proxy_port)) < 0)
-    return (ret);
-  else
-    request->use_proxy = ret;
-
-  gftp_lookup_request_option (request, "enable_ipv6", &enable_ipv6);
-
-  memset (&hints, 0, sizeof (hints));
-  hints.ai_flags = AI_CANONNAME;
-
-  hints.ai_family = enable_ipv6 ? PF_UNSPEC : AF_INET;
-  hints.ai_socktype = SOCK_STREAM;
-
-  if (request->use_proxy)
-    {
-      connect_host = proxy_hostname;
-      port = proxy_port;
-    }
-  else
-    {
-      connect_host = request->hostname;
-      port = request->port;
-    }
-
-  if (port == 0)
-    strcpy (serv, service); 
-  else
-    snprintf (serv, sizeof (serv), "%d", port);
-
-  request->logging_function (gftp_logging_misc, request,
-                             _("Looking up %s\n"), connect_host);
-  if ((ret = getaddrinfo (connect_host, serv, &hints, 
-                             &hostp)) != 0)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot look up hostname %s: %s\n"),
-                                 connect_host, gai_strerror (ret));
-      return (GFTP_ERETRYABLE);
-    }
-
-  disphost = connect_host;
-  for (res = hostp; res != NULL; res = res->ai_next)
-    {
-      disphost = res->ai_canonname ? res->ai_canonname : connect_host;
-      port = get_port (res);
-      if (!request->use_proxy)
-        request->port = port;
-
-      if ((sock = socket (res->ai_family, res->ai_socktype, 
-                          res->ai_protocol)) < 0)
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Failed to create a socket: %s\n"),
-                                     g_strerror (errno));
-          continue; 
-        } 
-
-      request->logging_function (gftp_logging_misc, request,
-                                 _("Trying %s:%d\n"), disphost, port);
-
-      if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Cannot connect to %s: %s\n"),
-                                     disphost, g_strerror (errno));
-          close (sock);
-          continue;
-        }
-
-      current_hostp = res;
-      request->ai_family = res->ai_family;
-      break;
-    }
-
-  if (res == NULL)
-    {
-      if (hostp != NULL)
-        freeaddrinfo (hostp);
-      
-      return (GFTP_ERETRYABLE);
-    }
-
-  request->remote_addr_len = current_hostp->ai_addrlen;
-  request->remote_addr = g_malloc0 (request->remote_addr_len);
-  memcpy (request->remote_addr, &((struct sockaddr_in *) current_hostp->ai_addr)->sin_addr,
-          request->remote_addr_len);
-
-  request->logging_function (gftp_logging_misc, request,
-                             _("Connected to %s:%d\n"), connect_host, port);
-
-  return (sock);
-}
-#endif
-
-
-static int
-gftp_connect_server_legacy (gftp_request * request, char *service,
-                            char *proxy_hostname, unsigned int proxy_port)
-{
-  struct sockaddr_in remote_address;
-  char *connect_host, *disphost;
-  struct hostent host, *hostp;
-  struct servent serv_struct;
-  int ret, sock, curhost;
-  unsigned int port;
-
-  if ((ret = gftp_need_proxy (request, service, proxy_hostname,
-                              proxy_port)) < 0)
-    return (ret);
-
-  request->use_proxy = ret;
-  if (request->use_proxy == 1)
-    hostp = NULL;
-
-  request->ai_family = AF_INET;
-  if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Failed to create a IPv4 socket: %s\n"),
-                                 g_strerror (errno));
-      return (GFTP_ERETRYABLE);
-    }
-
-  memset (&remote_address, 0, sizeof (remote_address));
-  remote_address.sin_family = AF_INET;
-
-  if (request->use_proxy)
-    {
-      connect_host = proxy_hostname;
-      port = proxy_port;
-    }
-  else
-    {
-      connect_host = request->hostname;
-      port = request->port;
-    }
-
-  if (port == 0)
-    {
-      if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Cannot look up service name %s/tcp. Please check your services file\n"),
-                                     service);
-          close (sock);
-          return (GFTP_EFATAL);
-        }
-
-      port = ntohs (serv_struct.s_port);
-
-      if (!request->use_proxy)
-        request->port = port;
-    }
-
-  remote_address.sin_port = htons (port);
-
-  request->logging_function (gftp_logging_misc, request,
-                             _("Looking up %s\n"), connect_host);
-
-  if (!(hostp = r_gethostbyname (connect_host, &host, NULL)))
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot look up hostname %s: %s\n"),
-                                 connect_host, g_strerror (errno));
-      close (sock);
-      return (GFTP_ERETRYABLE);
-    }
-
-  disphost = NULL;
-  for (curhost = 0;
-       host.h_addr_list[curhost] != NULL;
-       curhost++)
-    {
-      disphost = host.h_name;
-      memcpy (&remote_address.sin_addr,
-              host.h_addr_list[curhost],
-              host.h_length);
-      request->logging_function (gftp_logging_misc, request,
-                                 _("Trying %s:%d\n"),
-                                 host.h_name, port);
-
-      if (connect (sock, (struct sockaddr *) &remote_address,
-                   sizeof (remote_address)) == -1)
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Cannot connect to %s: %s\n"),
-                                     connect_host, g_strerror (errno));
-        }
-      break;
-    }
-
-  if (host.h_addr_list[curhost] == NULL)
-    {
-      close (sock);
-      return (GFTP_ERETRYABLE);
-    }
-
-  return (sock);
-}
-
-
 int
 gftp_connect_server (gftp_request * request, char *service,
                      char *proxy_hostname, unsigned int proxy_port)
 {
-  int sock;
+  void *connect_data;
+  int sock, ret;
 
+  if ((ret = gftp_need_proxy (request, service, proxy_hostname,
+                              proxy_port, &connect_data)) < 0)
+    return (ret);
+  request->use_proxy = ret;
+
+  /* FIXME - pass connect_data to these functions. This is to bypass a
+     second DNS lookup */
 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-  sock = gftp_connect_server_with_getaddr (request, service, proxy_hostname,
-                                           proxy_port);
+  sock = gftp_connect_server_with_getaddrinfo (request, service, proxy_hostname,
+                                               proxy_port);
 #else
   sock = gftp_connect_server_legacy (request, service, proxy_hostname,
                                      proxy_port);
--- a/lib/sockutils.c	Sat Mar 08 11:36:14 2008 +0000
+++ b/lib/sockutils.c	Fri Mar 28 11:44:36 2008 +0000
@@ -358,3 +358,30 @@
   return (0);
 }
 
+
+struct servent *
+r_getservbyname (const char *name, const char *proto,
+                 struct servent *result_buf, int *h_errnop)
+{
+  static GStaticMutex servfunclock = G_STATIC_MUTEX_INIT;
+  struct servent *sent;
+
+  if (g_thread_supported ())
+    g_static_mutex_lock (&servfunclock);
+
+  if ((sent = getservbyname (name, proto)) == NULL)
+    {
+      if (h_errnop)
+        *h_errnop = h_errno;
+    }
+  else
+    {
+      *result_buf = *sent;
+      sent = result_buf;
+    }
+
+  if (g_thread_supported ())
+    g_static_mutex_unlock (&servfunclock);
+  return (sent);
+}
+