vos: GetServer search for non-loopback address
authorJeffrey Altman <jaltman@your-file-system.com>
Sun, 15 Dec 2013 00:38:50 +0000 (19:38 -0500)
committerD Brashear <shadow@your-file-system.com>
Thu, 20 Mar 2014 21:28:02 +0000 (14:28 -0700)
GetServer() is used to obtain an IP address for the 'aname' parameter.
'aname' can be either a dotted address or a host name.   If it is a dotted
address, it is returned immediately.  If it is a host name, then
gethostbyname() is used to obtain an IP address.

The prior version of this function had two failings:

1. It assumed that a struct hostent only contained a single address.
   It used the former h_addr field.  For all platforms supported by
   OpenAFS h_addr is a macro referencing the first address in the
   h_addr_list array.  If h_addr was a loopback address, it would
   ignore any additional addresses that might be in the list.

2. It assumed that if gethostbyname(aname) returned a loopback
   address as h_addr that 'aname' must be referring to the machine
   that the vos command is being executed on.  It therefore used
   gethostname() to obtain an alternate name to use for a gethostbyname()
   query.  The results of this query were not checked to be a loopback.
   As a result, a loopback address could be returned to the caller which
   in turn could be set into the VLDB.

Change-Id: Ib8d513be9daf650045e9c40718b0187f6b9770a2
Reviewed-on: http://gerrit.openafs.org/10585
Reviewed-by: D Brashear <shadow@your-file-system.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Harald Barth <haba+gerrit@kth.se>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/volser/vos.c

index b6cb029..95df17b 100644 (file)
@@ -208,7 +208,7 @@ GetServerNoresolve(char *aname)
        return 0;
 }
 /*
- * Parse a server name/address and return the address in network byte order
+ * Parse a server name/address and return a non-loopback address in network byte order
  */
 afs_uint32
 GetServer(char *aname)
@@ -217,25 +217,50 @@ GetServer(char *aname)
     afs_uint32 addr; /* in network byte order */
     afs_int32 code;
     char hostname[MAXHOSTCHARS];
+    int i;
 
-    if ((addr = GetServerNoresolve(aname)) == 0) {
-       th = gethostbyname(aname);
-       if (!th)
+    addr = GetServerNoresolve(aname);
+    if (addr != 0) {
+       if (!rx_IsLoopbackAddr(ntohl(addr)))
+           return addr;
+       else
            return 0;
-       memcpy(&addr, th->h_addr, sizeof(addr));
     }
 
-    if (rx_IsLoopbackAddr(ntohl(addr))) {      /* local host */
+    th = gethostbyname(aname);
+    if (th != NULL) {
+       for (i=0; i < th->h_length; i++) {
+           if (!rx_IsLoopbackAddr(ntohl(*(afs_uint32 *)th->h_addr_list[i]))) {
+               memcpy(&addr, th->h_addr_list[i], sizeof(addr));
+               return addr;
+           }
+       }
+
+       /*
+        * If we reach this point all of the addresses returned by
+        * gethostbyname() are loopback addresses.  We assume that means
+        * that the name is supposed to describe the machine this code
+        * is executing on.  Try gethostname() to and check to see if
+        * that name can provide us a non-loopback address.
+        */
        code = gethostname(hostname, MAXHOSTCHARS);
-       if (code)
-           return 0;
-       th = gethostbyname(hostname);
-       if (!th)
-           return 0;
-       memcpy(&addr, th->h_addr, sizeof(addr));
+       if (code == 0) {
+           th = gethostbyname(hostname);
+           if (th != NULL) {
+               for (i=0; i < th->h_length; i++) {
+                   if (!rx_IsLoopbackAddr(ntohl(*(afs_uint32 *)th->h_addr_list[i]))) {
+                       memcpy(&addr, th->h_addr_list[i], sizeof(addr));
+                       return addr;
+                   }
+               }
+           }
+       }
     }
 
-    return (addr);
+    /*
+     * No non-loopback address could be obtained for 'aname'.
+     */
+    return 0;
 }
 
 afs_int32