Blob Blame History Raw
From 8ab57ebcf775bf97fc99c0315a4b7b29435c34c2 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 20 Apr 2016 17:07:53 -0400
Subject: [PATCH] common: limit potentially expensive name lookups

Right now we're doing name look ups when we don't have to.  These
name look ups can cause lengthy timeouts in misconfigured environments.

This commit reduces the name looks used by GDM to make it more resiliant
to failure.

Ported from RHEL 6 to RHEL 7 by Ashish Shah <ashishks@redhat.com>
---
 common/gdm-address.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/common/gdm-address.c b/common/gdm-address.c
index 3448038..a8b73e2 100644
--- a/common/gdm-address.c
+++ b/common/gdm-address.c
@@ -193,159 +193,160 @@ gdm_address_equal (GdmAddress *a,
         return FALSE;
 }
 
 /* for debugging */
 static const char *
 address_family_str (GdmAddress *address)
 {
         const char *str;
         switch (address->ss->ss_family) {
         case AF_INET:
                 str = "inet";
                 break;
         case AF_INET6:
                 str = "inet6";
                 break;
         case AF_UNIX:
                 str = "unix";
                 break;
         case AF_UNSPEC:
                 str = "unspecified";
                 break;
         default:
                 str = "unknown";
                 break;
         }
         return str;
 }
 
 static void
 _gdm_address_debug (GdmAddress *address,
-                    const char *hostname,
                     const char *host,
                     const char *port)
 {
-        g_debug ("Address family:%d (%s) hostname:%s host:%s port:%s local:%d loopback:%d",
+        g_debug ("Address family:%d (%s) host:%s port:%s local:%d loopback:%d",
+
                  address->ss->ss_family,
                  address_family_str (address) ? address_family_str (address) : "(null)",
-                 hostname ? hostname : "(null)",
                  host ? host : "(null)",
                  port ? port : "(null)",
                  gdm_address_is_local (address),
                  gdm_address_is_loopback (address));
 }
 
 void
 gdm_address_debug (GdmAddress *address)
 {
-        char *hostname;
-        char *host;
-        char *port;
+        char *hostname = NULL;
+        char *host = NULL;
+        char *port = NULL;
 
-        gdm_address_get_hostname (address, &hostname);
         gdm_address_get_numeric_info (address, &host, &port);
 
+        _gdm_address_debug (address, host, port);
+
         g_free (hostname);
         g_free (host);
         g_free (port);
 }
 
 gboolean
 gdm_address_get_hostname (GdmAddress *address,
                           char      **hostnamep)
 {
         char     host [NI_MAXHOST];
         int      res;
         gboolean ret;
 
         g_return_val_if_fail (address != NULL, FALSE);
         g_return_val_if_fail (address->ss != NULL, FALSE);
 
         ret = FALSE;
 
         host [0] = '\0';
         res = getnameinfo ((const struct sockaddr *)address->ss,
                            (int) gdm_sockaddr_len (address->ss),
                            host, sizeof (host),
                            NULL, 0,
                            0);
         if (res == 0) {
                 ret = TRUE;
                 goto done;
         } else {
                 const char *err_msg;
 
                 err_msg = gai_strerror (res);
                 g_warning ("Unable to lookup hostname: %s",
                         err_msg ? err_msg : "(null)");
-                _gdm_address_debug (address, NULL, NULL, NULL);
+                _gdm_address_debug (address, NULL, NULL);
+
         }
 
         /* try numeric? */
 
  done:
         if (hostnamep != NULL) {
                 *hostnamep = g_strdup (host);
         }
 
         return ret;
 }
 
 gboolean
 gdm_address_get_numeric_info (GdmAddress *address,
                               char      **hostp,
                               char      **servp)
 {
         char     host [NI_MAXHOST];
         char     serv [NI_MAXSERV];
         int      res;
         gboolean ret;
 
         g_return_val_if_fail (address != NULL, FALSE);
         g_return_val_if_fail (address->ss != NULL, FALSE);
 
         ret = FALSE;
 
         host [0] = '\0';
         serv [0] = '\0';
         res = getnameinfo ((const struct sockaddr *)address->ss,
                            (int) gdm_sockaddr_len (address->ss),
                            host, sizeof (host),
                            serv, sizeof (serv),
                            NI_NUMERICHOST | NI_NUMERICSERV);
         if (res != 0) {
                 const char *err_msg;
 
                 err_msg = gai_strerror (res);
                 g_warning ("Unable to lookup numeric info: %s",
                         err_msg ? err_msg : "(null)");
-                _gdm_address_debug (address, NULL, NULL, NULL);
+                _gdm_address_debug (address, NULL, NULL);
         } else {
                 ret = TRUE;
         }
 
         if (servp != NULL) {
                 if (g_str_has_prefix (serv, "::ffff:")) {
                         *servp = g_strdup (serv + 7);
                 } else {
                         *servp = g_strdup (serv);
                 }
         }
         if (hostp != NULL) {
                 if (g_str_has_prefix (host, "::ffff:")) {
                         *hostp = g_strdup (host + 7);
                 } else {
                         *hostp = g_strdup (host);
                 }
         }
 
         return ret;
 }
 
 gboolean
 gdm_address_is_loopback (GdmAddress *address)
 {
         g_return_val_if_fail (address != NULL, FALSE);
         g_return_val_if_fail (address->ss != NULL, FALSE);
 
         switch (address->ss->ss_family){
 #ifdef  AF_INET6
@@ -377,94 +378,93 @@ add_local_siocgifconf (GList **list)
                 perror ("socket");
                 return;
         }
 
         ifc.ifc_len = sizeof (buf);
         ifc.ifc_buf = buf;
         if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0) {
                 perror ("SIOCGIFCONF");
                 close (sock);
                 return;
         }
 
         /* Get IP address of each active IP network interface. */
         the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
 
         for (ifr = ifc.ifc_req; ifr < the_end; ifr++) {
                 if (ifr->ifr_addr.sa_family == AF_INET) {
                         /* IP net interface */
                         ifreq = *ifr;
 
                         if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
                                 perror("SIOCGIFFLAGS");
                         } else if (ifreq.ifr_flags & IFF_UP) {  /* active interface */
                                 if (ioctl (sock, SIOCGIFADDR, (char *) &ifreq) < 0) {
                                         perror("SIOCGIFADDR");
                                 } else {
                                         GdmAddress *address;
                                         address = gdm_address_new_from_sockaddr ((struct sockaddr *)&ifreq.ifr_addr,
                                                                                  sizeof (struct sockaddr));
 
-                                        gdm_address_debug (address);
-
                                         *list = g_list_append (*list, address);
                                 }
                         }
                 }
 
                 /* Support for variable-length addresses. */
 #ifdef HAS_SA_LEN
                 ifr = (struct ifreq *) ((caddr_t) ifr
                                         + ifr->ifr_addr.sa_len - sizeof(struct sockaddr));
 #endif
         }
 
         close (sock);
 }
 
 static void
 add_local_addrinfo (GList **list)
 {
         char             hostbuf[BUFSIZ];
         struct addrinfo *result;
         struct addrinfo *res;
         struct addrinfo  hints;
 
         hostbuf[BUFSIZ-1] = '\0';
         if (gethostname (hostbuf, BUFSIZ-1) != 0) {
                 g_debug ("%s: Could not get server hostname, using localhost", "gdm_peek_local_address_list");
                 snprintf (hostbuf, BUFSIZ-1, "localhost");
         }
 
         memset (&hints, 0, sizeof (hints));
         hints.ai_family = AF_UNSPEC;
-        hints.ai_flags = AI_CANONNAME;
+        hints.ai_flags = AI_CANONNAME | AI_NUMERICHOST;
+
 
         g_debug ("GdmAddress: looking up hostname: %s", hostbuf);
         result = NULL;
         if (getaddrinfo (hostbuf, NULL, &hints, &result) != 0) {
                 g_debug ("%s: Could not get address from hostname!", "gdm_peek_local_address_list");
 
                 return;
         }
 
         for (res = result; res != NULL; res = res->ai_next) {
                 GdmAddress *address;
 
                 g_debug ("family=%d sock_type=%d protocol=%d flags=0x%x canonname=%s\n",
                          res->ai_family,
                          res->ai_socktype,
                          res->ai_protocol,
                          res->ai_flags,
                          res->ai_canonname ? res->ai_canonname : "(null)");
                 address = gdm_address_new_from_sockaddr (res->ai_addr, res->ai_addrlen);
                 *list = g_list_append (*list, address);
         }
 
         if (result != NULL) {
                 freeaddrinfo (result);
                 result = NULL;
         }
 }
 
 const GList *
 gdm_address_peek_local_list (void)
-- 
2.8.1