Add AFSCONF_NOCELLNAME error code
[openafs.git] / src / auth / cellconfig.c
index c457e3a..cd65f67 100644 (file)
@@ -9,42 +9,24 @@
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <afs/stds.h>
 
 #include <roken.h>
+#include <afs/opr.h>
 
-#include <afs/stds.h>
-#include <afs/pthread_glock.h>
-#include <sys/types.h>
 #ifdef AFS_NT40_ENV
-#include <winsock2.h>
 #include <sys/utime.h>
-#include <io.h>
 #include <WINNT/afssw.h>
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <sys/file.h>
-#include <sys/time.h>
+#endif
+
 #include <ctype.h>
-#include <arpa/nameser.h>
+
 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
 #include <arpa/nameser_compat.h>
 #endif
-#include <resolv.h>
-#endif /* AFS_NT40_ENV */
+
+#include <afs/pthread_glock.h>
 #include <afs/afsint.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 #include <rx/rxkad.h>
 #include <rx/rx.h>
 
@@ -156,7 +138,7 @@ afsconf_fopen(const char *fname, const char *fmode)
     iop->buffer = malloc(BUFFER);
     if (iop->buffer == NULL) {
        (void) close(fd);
-       free((void *) iop);
+       free(iop);
        errno = ENOMEM;
        return NULL;
     }
@@ -172,8 +154,8 @@ afsconf_fclose(afsconf_FILE *iop)
        return 0;
     }
     close(iop->_file);
-    free((void *)iop->buffer);
-    free((void *)iop);
+    free(iop->buffer);
+    free(iop);
     return 0;
 }
 
@@ -336,51 +318,87 @@ _afsconf_IsClientConfigDirectory(const char *path)
     return 1;
 }
 
-
-int
-_afsconf_Check(struct afsconf_dir *adir)
-{
-    char tbuffer[256];
 #ifdef AFS_NT40_ENV
+static void
+_afsconf_CellServDBPath(struct afsconf_dir *adir, char **path)
+{
     char *p;
-#endif
-    struct stat tstat;
-    afs_int32 code;
 
-#ifdef AFS_NT40_ENV
     /* NT client CellServDB has different file name than NT server or Unix */
     if (_afsconf_IsClientConfigDirectory(adir->name)) {
        if (!afssw_GetClientCellServDBDir(&p)) {
-           strcompose(tbuffer, sizeof(tbuffer), p, "/",
-                      AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
+           if (asprintf(path, "%s/%s", p, AFSDIR_CELLSERVDB_FILE_NTCLIENT) < 0)
+               *path = NULL;
            free(p);
        } else {
-           int len;
-           strncpy(tbuffer, adir->name, sizeof(tbuffer));
-           len = (int)strlen(tbuffer);
-           if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
-               strncat(tbuffer, "\\", sizeof(tbuffer));
-           }
-           strncat(tbuffer, AFSDIR_CELLSERVDB_FILE_NTCLIENT,
-                   sizeof(tbuffer));
-           tbuffer[sizeof(tbuffer) - 1] = '\0';
+           if (asprintf(path, "%s/%s", adir->name,
+                        AFSDIR_CELLSERVDB_FILE_NTCLIENT) < 0)
+               *path = NULL;
        }
     } else {
-       strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE,
-                  NULL);
+       if (asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE) < 0)
+           *path = NULL;
     }
+    return;
+}
 #else
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
+static void
+_afsconf_CellServDBPath(struct afsconf_dir *adir, char **path)
+{
+    if (asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE) < 0)
+       *path = NULL;
+}
 #endif /* AFS_NT40_ENV */
 
-    code = stat(tbuffer, &tstat);
-    if (code < 0) {
-       return code;
+int
+_afsconf_UpToDate(struct afsconf_dir *adir)
+{
+    char *cellservDB;
+    struct stat tstat;
+    int code;
+    time_t now = time(0);
+
+    if (adir->timeRead && (adir->timeCheck == now)) {
+       return 1; /* stat no more than once a second */
     }
+    adir->timeCheck = now;
+
+    _afsconf_CellServDBPath(adir, &cellservDB);
+    if (cellservDB == NULL)
+       return 0;
+
+    code = stat(cellservDB, &tstat);
+    free(cellservDB);
+    if (code < 0)
+       return 0; /* Can't throw the error, so just say we're not up to date */
+
     /* did file change? */
-    if (tstat.st_mtime == adir->timeRead) {
+    if (tstat.st_mtime == adir->timeRead)
+       return 1;
+
+    /* otherwise file has changed */
+    return 0;
+}
+
+int
+afsconf_UpToDate(void *rock)
+{
+    int code;
+
+    LOCK_GLOBAL_MUTEX;
+    code = _afsconf_UpToDate(rock);
+    UNLOCK_GLOBAL_MUTEX;
+
+    return code;
+}
+
+int
+_afsconf_Check(struct afsconf_dir *adir)
+{
+    /* did configuration change? */
+    if (_afsconf_UpToDate(adir))
        return 0;
-    }
+
     /* otherwise file has changed, so reopen it */
     return afsconf_Reopen(adir);
 }
@@ -389,45 +407,29 @@ _afsconf_Check(struct afsconf_dir *adir)
 int
 _afsconf_Touch(struct afsconf_dir *adir)
 {
-    char tbuffer[256];
+    char *cellservDB;
+    int code;
 #ifndef AFS_NT40_ENV
     struct timeval tvp[2];
-#else
-    char *p;
 #endif
 
     adir->timeRead = 0;                /* just in case */
+    adir->timeCheck = 0;
 
-#ifdef AFS_NT40_ENV
-    /* NT client CellServDB has different file name than NT server or Unix */
-
-    if (_afsconf_IsClientConfigDirectory(adir->name)) {
-       if (!afssw_GetClientCellServDBDir(&p)) {
-           strcompose(tbuffer, sizeof(tbuffer), p, "/",
-                      AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
-           free(p);
-       } else {
-           int len = (int)strlen(tbuffer);
-           if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
-               strncat(tbuffer, "\\", sizeof(tbuffer));
-           }
-           strncat(tbuffer, AFSDIR_CELLSERVDB_FILE_NTCLIENT,
-                   sizeof(tbuffer));
-           tbuffer[sizeof(tbuffer) - 1] = '\0';
-       }
-    } else {
-       strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE,
-                  NULL);
-    }
-
-    return _utime(tbuffer, NULL);
+    _afsconf_CellServDBPath(adir, &cellservDB);
+    if (cellservDB == NULL)
+       return ENOMEM;
 
+#ifdef AFS_NT40_ENV
+    code = _utime(cellservDB, NULL);
 #else
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
     gettimeofday(&tvp[0], NULL);
     tvp[1] = tvp[0];
-    return utimes(tbuffer, tvp);
+    code = utimes(cellservDB, tvp);
 #endif /* AFS_NT40_ENV */
+    free(cellservDB);
+
+    return code;
 }
 
 struct afsconf_dir *
@@ -438,8 +440,7 @@ afsconf_Open(const char *adir)
 
     LOCK_GLOBAL_MUTEX;
     /* zero structure and fill in name; rest is done by internal routine */
-    tdir = (struct afsconf_dir *)malloc(sizeof(struct afsconf_dir));
-    memset(tdir, 0, sizeof(struct afsconf_dir));
+    tdir = calloc(1, sizeof(struct afsconf_dir));
     tdir->name = strdup(adir);
 
     code = afsconf_OpenInternal(tdir, 0, 0);
@@ -452,41 +453,38 @@ afsconf_Open(const char *adir)
            /* The "AFSCONF" environment (or contents of "/.AFSCONF") will be typically set to something like "/afs/<cell>/common/etc" where, by convention, the default files for "ThisCell" and "CellServDB" will reside; note that a major drawback is that a given afs client on that cell may NOT contain the same contents... */
            char *home_dir;
            afsconf_FILE *fp;
-           size_t len;
+           size_t len = 0;
+           int r;
 
            if (!(home_dir = getenv("HOME"))) {
                /* Our last chance is the "/.AFSCONF" file */
                fp = fopen("/.AFSCONF", "r");
-               if (fp == 0) {
-                   free(tdir);
-                   UNLOCK_GLOBAL_MUTEX;
-                   return (struct afsconf_dir *)0;
-               }
-               fgets(afs_confdir, 128, fp);
-               fclose(fp);
+               if (fp == 0)
+                   goto fail;
+
            } else {
-               char pathname[256];
+               char *pathname = NULL;
+
+               r = asprintf(&pathname, "%s/%s", home_dir, ".AFSCONF");
+               if (r < 0 || pathname == NULL)
+                   goto fail;
 
-               sprintf(pathname, "%s/%s", home_dir, ".AFSCONF");
                fp = fopen(pathname, "r");
+               free(pathname);
+
                if (fp == 0) {
                    /* Our last chance is the "/.AFSCONF" file */
                    fp = fopen("/.AFSCONF", "r");
-                   if (fp == 0) {
-                       free(tdir);
-                       UNLOCK_GLOBAL_MUTEX;
-                       return (struct afsconf_dir *)0;
-                   }
+                   if (fp == 0)
+                       goto fail;
                }
-               fgets(afs_confdir, 128, fp);
-               fclose(fp);
-           }
-           len = strlen(afs_confdir);
-           if (len == 0) {
-               free(tdir);
-               UNLOCK_GLOBAL_MUTEX;
-               return (struct afsconf_dir *)0;
            }
+           if (fgets(afs_confdir, 128, fp) != NULL)
+               len = strlen(afs_confdir);
+           fclose(fp);
+           if (len == 0)
+               goto fail;
+
            if (afs_confdir[len - 1] == '\n') {
                afs_confdir[len - 1] = 0;
            }
@@ -496,13 +494,16 @@ afsconf_Open(const char *adir)
        code = afsconf_OpenInternal(tdir, 0, 0);
        if (code) {
            free(tdir->name);
-           free(tdir);
-           UNLOCK_GLOBAL_MUTEX;
-           return (struct afsconf_dir *)0;
+           goto fail;
        }
     }
     UNLOCK_GLOBAL_MUTEX;
     return tdir;
+
+fail:
+    free(tdir);
+    UNLOCK_GLOBAL_MUTEX;
+    return NULL;
 }
 
 static int
@@ -513,7 +514,8 @@ GetCellUnix(struct afsconf_dir *adir)
     char *start, *p;
     afsconf_FILE *fp;
 
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_THISCELL_FILE, NULL);
+    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_THISCELL_FILE,
+       (char *)NULL);
     fp = fopen(tbuffer, "r");
     if (fp == 0) {
        return -1;
@@ -626,12 +628,17 @@ afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
     struct afsconf_aliasentry *curAlias;
     afs_int32 code;
     afs_int32 i;
-    char tbuffer[256], tbuf1[256];
+    char tbuffer[256];
     struct stat tstat;
+    char *cellservDB;
+
 #ifdef AFS_NT40_ENV
     cm_enumCellRegistry_t enumCellRegistry = {0, 0};
 #endif /* AFS_NT40_ENV */
 
+    /* init the keys queue before any call to afsconf_CloseInternal() */
+    _afsconf_InitKeys(adir);
+
     /* figure out the local cell name */
 #ifdef AFS_NT40_ENV
     i = GetCellNT(adir);
@@ -649,48 +656,20 @@ afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
     /* now parse the individual lines */
     curEntry = 0;
 
-#ifdef AFS_NT40_ENV
-    /* NT client/server have a CellServDB that is the same format as Unix.
-     * However, the NT client uses a different file name
-     */
-    if (_afsconf_IsClientConfigDirectory(adir->name)) {
-       /* NT client config dir */
-       char *p;
+    _afsconf_CellServDBPath(adir, &cellservDB);
 
+#ifdef AFS_NT40_ENV
+    if (_afsconf_IsClientConfigDirectory(adir->name))
         enumCellRegistry.client = 1;
-
-       if (!afssw_GetClientCellServDBDir(&p)) {
-           strcompose(tbuffer, sizeof(tbuffer), p, "/",
-                      AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
-           free(p);
-       } else {
-           int len;
-           strncpy(tbuffer, adir->name, sizeof(tbuffer));
-           len = (int)strlen(tbuffer);
-           if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
-               strncat(tbuffer, "\\", sizeof(tbuffer));
-           }
-           strncat(tbuffer, AFSDIR_CELLSERVDB_FILE_NTCLIENT,
-                   sizeof(tbuffer));
-           tbuffer[sizeof(tbuffer) - 1] = '\0';
-       }
-    } else {
-       /* NT server config dir */
-       strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE,
-                  NULL);
-    }
-#else
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
 #endif /* AFS_NT40_ENV */
 
-    if (!stat(tbuffer, &tstat)) {
+    if (!stat(cellservDB, &tstat)) {
        adir->timeRead = tstat.st_mtime;
     } else {
        adir->timeRead = 0;
     }
 
-    strlcpy(tbuf1, tbuffer, sizeof tbuf1);
-    tf = fopen(tbuffer, "r");
+    tf = fopen(cellservDB, "r");
     if (!tf) {
        return -1;
     }
@@ -723,9 +702,7 @@ afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
                adir->entries = curEntry;
                curEntry = 0;
            }
-           curEntry =
-               (struct afsconf_entry *)malloc(sizeof(struct afsconf_entry));
-           memset(curEntry, 0, sizeof(struct afsconf_entry));
+           curEntry = calloc(1, sizeof(struct afsconf_entry));
            code =
                ParseCellLine(tbuffer, curEntry->cellInfo.name, linkedcell);
            if (code) {
@@ -766,7 +743,7 @@ afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
                        *bp = '\0';
                        fprintf(stderr,
                                "Can't properly parse host line \"%s\" in configuration file %s\n",
-                               tbuffer, tbuf1);
+                               tbuffer, cellservDB);
                    }
                    free(curEntry);
                    fclose(tf);
@@ -777,11 +754,12 @@ afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
            } else {
                fprintf(stderr,
                        "Too many hosts for cell %s in configuration file %s\n",
-                       curEntry->cellInfo.name, tbuf1);
+                       curEntry->cellInfo.name, cellservDB);
            }
        }
     }
     fclose(tf);                        /* close the file now */
+    free(cellservDB);
 
     /* end the last partially-completed cell */
     if (curEntry) {
@@ -802,7 +780,8 @@ afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
 #endif /* AFS_NT40_ENV */
 
     /* Read in the alias list */
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLALIAS_FILE, NULL);
+    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLALIAS_FILE,
+       (char *)NULL);
 
     tf = fopen(tbuffer, "r");
     while (tf) {
@@ -833,8 +812,7 @@ afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
            tp++;
        tp[0] = '\0';
 
-       curAlias = malloc(sizeof(*curAlias));
-       memset(curAlias, 0, sizeof(*curAlias));
+       curAlias = calloc(1, sizeof(*curAlias));
 
        strlcpy(curAlias->aliasInfo.aliasName, aliasPtr, sizeof curAlias->aliasInfo.aliasName);
        strlcpy(curAlias->aliasInfo.realName, tbuffer, sizeof curAlias->aliasInfo.realName);
@@ -845,10 +823,13 @@ afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
 
     if (tf != NULL)
        fclose(tf);
-    /* now read the fs keys, if possible */
 
-    _afsconf_InitKeys(adir);
+    /* now read the fs keys, if possible */
     code = _afsconf_LoadKeys(adir);
+    if (code) {
+        return code;
+    }
+    code = _afsconf_LoadRealms(adir);
 
     return code;
 }
@@ -988,12 +969,12 @@ afsconf_LookupServer(const char *service, const char *protocol,
                     int *numServers, int *ttl, char **arealCellName)
 {
     int code = 0;
+    int r;
     int len;
-    unsigned char answer[1024];
+    unsigned char answer[4096];
     unsigned char *p;
-    char *dotcellname;
+    char *dotcellname = NULL;
     char *realCellName;
-    int cellnamelength, fullnamelength;
     char host[256];
     int server_num = 0;
     int minttl = 0;
@@ -1013,12 +994,6 @@ afsconf_LookupServer(const char *service, const char *protocol,
     if (strchr(cellName,'.'))
        pass += 2;
 
-    cellnamelength=strlen(cellName); /* _ ._ . . \0 */
-    fullnamelength=cellnamelength+strlen(protocol)+strlen(IANAname)+6;
-    dotcellname=malloc(fullnamelength);
-    if (!dotcellname)
-       return AFSCONF_NOTFOUND;        /* service not found */
-
 #ifdef HAVE_RES_RETRANSRETRY
     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
       return (0);
@@ -1032,34 +1007,37 @@ afsconf_LookupServer(const char *service, const char *protocol,
 #endif
 
  retryafsdb:
+    r = -1;
     switch (pass) {
     case 0:
        dnstype = T_SRV;
-       code = snprintf(dotcellname, fullnamelength, "_%s._%s.%s.",
-                IANAname, protocol, cellName);
+       r = asprintf(&dotcellname, "_%s._%s.%s.", IANAname, protocol, cellName);
        break;
     case 1:
        dnstype = T_AFSDB;
-       code = snprintf(dotcellname, fullnamelength, "%s.",
-                cellName);
+       r = asprintf(&dotcellname, "%s.", cellName);
        break;
     case 2:
        dnstype = T_SRV;
-       code = snprintf(dotcellname, fullnamelength, "_%s._%s.%s",
-                IANAname, protocol, cellName);
+       r = asprintf(&dotcellname, "_%s._%s.%s", IANAname, protocol, cellName);
        break;
     case 3:
        dnstype = T_AFSDB;
-       code = snprintf(dotcellname, fullnamelength, "%s",
-                cellName);
+       r = asprintf(&dotcellname, "%s", cellName);
        break;
     }
-    if ((code < 0) || (code >= fullnamelength))
+    if (r < 0 || dotcellname == NULL)
        goto findservererror;
+
     LOCK_GLOBAL_MUTEX;
     len = res_search(dotcellname, C_IN, dnstype, answer, sizeof(answer));
     UNLOCK_GLOBAL_MUTEX;
 
+    if (dotcellname != NULL) {
+       free(dotcellname);
+       dotcellname = NULL;
+    }
+
     if (len < 0) {
        if (try_init < 1) {
            try_init++;
@@ -1125,17 +1103,18 @@ afsconf_LookupServer(const char *service, const char *protocol,
            if ((afsdb_type == 1) && (server_num < MAXHOSTSPERCELL) &&
                /* Do we want to get TTL data for the A record as well? */
                (he = gethostbyname(host))) {
-               afs_int32 ipaddr;
-               memcpy(&ipaddr, he->h_addr, he->h_length);
-               cellHostAddrs[server_num] = ipaddr;
-               ports[server_num] = afsdbPort;
-               ipRanks[server_num] = 0;
-               strncpy(cellHostNames[server_num], host,
-                       sizeof(cellHostNames[server_num]));
-               server_num++;
-
-               if (!minttl || ttl < minttl)
-                   minttl = ttl;
+               if (he->h_addrtype == AF_INET) {
+                   afs_int32 ipaddr;
+                   memcpy(&ipaddr, he->h_addr, sizeof(ipaddr));
+                   cellHostAddrs[server_num] = ipaddr;
+                   ports[server_num] = afsdbPort;
+                   ipRanks[server_num] = 0;
+                   strncpy(cellHostNames[server_num], host,
+                           sizeof(cellHostNames[server_num]));
+                   server_num++;
+                   if (!minttl || ttl < minttl)
+                       minttl = ttl;
+               }
            }
        }
        if (type == T_SRV) {
@@ -1158,18 +1137,21 @@ afsconf_LookupServer(const char *service, const char *protocol,
            if ((server_num < MAXHOSTSPERCELL) &&
                /* Do we want to get TTL data for the A record as well? */
                (he = gethostbyname(host))) {
-               afs_int32 ipaddr;
-               memcpy(&ipaddr, he->h_addr, he->h_length);
-               cellHostAddrs[server_num] = ipaddr;
-               ipRanks[server_num] = (p[0] << 8) | p[1];
-               ports[server_num] = htons((p[4] << 8) | p[5]);
-               /* weight = (p[2] << 8) | p[3]; */
-               strncpy(cellHostNames[server_num], host,
-                       sizeof(cellHostNames[server_num]));
-               server_num++;
-
-               if (!minttl || ttl < minttl)
-                   minttl = ttl;
+               if (he->h_addrtype == AF_INET) {
+                   afs_int32 ipaddr;
+
+                   memcpy(&ipaddr, he->h_addr, sizeof(ipaddr));
+                   cellHostAddrs[server_num] = ipaddr;
+                   ipRanks[server_num] = (p[0] << 8) | p[1];
+                   ports[server_num] = htons((p[4] << 8) | p[5]);
+                   /* weight = (p[2] << 8) | p[3]; */
+                   strncpy(cellHostNames[server_num], host,
+                           sizeof(cellHostNames[server_num]));
+                   server_num++;
+
+                   if (!minttl || ttl < minttl)
+                       minttl = ttl;
+               }
            }
        }
 
@@ -1199,7 +1181,6 @@ afsconf_LookupServer(const char *service, const char *protocol,
 findservererror:
     if (code && realCellName)
        free(realCellName);
-    free(dotcellname);
     return code;
 }
 
@@ -1229,6 +1210,21 @@ afsconf_GetAfsdbInfo(char *acellName, char *aservice,
                                ports, ipRanks, &numServers, &ttl,
                                &realCellName);
 
+    /* If we couldn't find an entry for the requested service
+     * and that service happens to be the prservice or kaservice
+     * then fallback to searching for afs3-vlserver and assigning
+     * the port number here. */
+    if (code < 0 && (afsdbport == htons(7002) || afsdbport == htons(7004))) {
+        code = afsconf_LookupServer("afs3-vlserver", "udp",
+                                    (const char *)acellName, afsdbport,
+                                    cellHostAddrs, cellHostNames,
+                                    ports, ipRanks, &numServers, &ttl,
+                                    &realCellName);
+        if (code >= 0) {
+            for (i = 0; i < numServers; i++)
+                ports[i] = afsdbport;
+        }
+    }
     if (code == 0) {
        acellInfo->timeout = ttl;
        acellInfo->numServers = numServers;
@@ -1291,7 +1287,7 @@ afsconf_GetAfsdbInfo(char *acellName, char *aservice,
      * and that service happens to be the prservice or kaservice
      * then fallback to searching for afs3-vlserver and assigning
      * the port number here. */
-    if (rc < 0 && tservice == htons(7002) || tservice == htons(7004)) {
+    if (rc < 0 && (tservice == htons(7002) || tservice == htons(7004))) {
         rc = getAFSServer("afs3-vlserver", "udp", acellName, tservice,
                            cellHostAddrs, cellHostNames, ports, ipRanks, &numServers,
                            &ttl);
@@ -1306,7 +1302,7 @@ afsconf_GetAfsdbInfo(char *acellName, char *aservice,
 
     for (i = 0; i < numServers; i++) {
        memcpy(&acellInfo->hostAddr[i].sin_addr.s_addr, &cellHostAddrs[i],
-              sizeof(long));
+              sizeof(afs_uint32));
        memcpy(acellInfo->hostName[i], cellHostNames[i], MAXHOSTCHARS);
        acellInfo->hostAddr[i].sin_family = AF_INET;
         if (aservice)
@@ -1424,9 +1420,12 @@ afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
                     for (i=0 ; he->h_addr_list[i] && numServers < MAXHOSTSPERCELL; i++) {
                         /* check to see if this is a new address; if so insert it into the list */
                         int k, dup;
+                       afs_uint32 addr;
+                       memcpy(&addr, he->h_addr_list[i], sizeof(addr));
                         for (k=0, dup=0; !dup && k < numServers; k++) {
-                            if (hostAddr[k].sin_addr.s_addr == *(u_long *)he->h_addr_list[i])
+                            if (hostAddr[k].sin_addr.s_addr == addr) {
                                 dup = 1;
+                           }
                         }
                         if (dup)
                             continue;
@@ -1436,7 +1435,7 @@ afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
                         hostAddr[numServers].sin_len = sizeof(struct sockaddr_in);
 #endif
-                        memcpy(&hostAddr[numServers].sin_addr.s_addr, he->h_addr_list[i], sizeof(long));
+                        memcpy(&hostAddr[numServers].sin_addr.s_addr, he->h_addr_list[i], sizeof(afs_uint32));
                         strcpy(hostName[numServers], acellInfo->hostName[j]);
                         foundAddr = 1;
                         numServers++;
@@ -1464,72 +1463,70 @@ afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
     }
 }
 
+/**
+ * Get the current localcell name.
+ *
+ * Internal function to get a pointer to the local cell name.
+ * This function must be called with the global afsconf lock held.
+ *
+ * @param[in]  adir    afsconf object
+ * @param[out] aname   address to a char pointer
+ * @param[in]  check   always perform a config check, even if the
+ *                     the AFSCELL name is set.
+ *
+ * @return status
+ *    @retval 0 success
+ *    @retval AFSCONF_NOCELLNAME cannot determine local cell name
+ *
+ * @internal
+ */
 int
-afsconf_GetLocalCell(struct afsconf_dir *adir, char *aname,
-                    afs_int32 alen)
+_afsconf_GetLocalCell(struct afsconf_dir *adir, char **pname, int check)
 {
     static int afsconf_showcell = 0;
     char *afscell_path;
     afs_int32 code = 0;
 
-    LOCK_GLOBAL_MUTEX;
     /*
      * If a cell switch was specified in a command, then it should override the
      * AFSCELL variable.  If a cell was specified, then the afsconf_SawCell flag
      * is set and the cell name in the adir structure is used.
      * Read the AFSCELL var each time: in case it changes (unsetenv AFSCELL).
+     * Optionally, check the configuration, even if using the environment variable.
      */
     if (!afsconf_SawCell && (afscell_path = getenv("AFSCELL"))) {
+       if (check) {
+           _afsconf_Check(adir);
+       }
        if (!afsconf_showcell) {
            fprintf(stderr, "Note: Operation is performed on cell %s\n",
                    afscell_path);
            afsconf_showcell = 1;
        }
-       strncpy(aname, afscell_path, alen);
+       *pname = afscell_path;
     } else {
        _afsconf_Check(adir);
        if (adir->cellName) {
-           strncpy(aname, adir->cellName, alen);
+           *pname = adir->cellName;
        } else
-           code = AFSCONF_UNKNOWN;
+           code = AFSCONF_NOCELLNAME;
     }
-
-    UNLOCK_GLOBAL_MUTEX;
-    return (code);
+    return code;
 }
 
 int
-afsconf_UpToDate(void *rock)
+afsconf_GetLocalCell(struct afsconf_dir *adir, char *aname, afs_int32 alen)
 {
-    struct afsconf_dir *adir = rock;
-    char tbuffer[256];
-#ifdef AFS_NT40_ENV
-    char *p;
-#endif
-    struct stat tstat;
-    afs_int32 code = 0; /* default to not up to date */
-    LOCK_GLOBAL_MUTEX;
-#ifdef AFS_NT40_ENV
-    /* NT client config dir has no KeyFile; don't risk attempting open
-     * because there might be a random file of this name if dir is shared.
-     */
-    if (_afsconf_IsClientConfigDirectory(adir->name)) {
-       /* Not a server, nothing to reread */
-       code = 1;
-    } else {
-#endif
-       strcompose(tbuffer, 256, adir->name, "/", AFSDIR_KEY_FILE, NULL);
+    afs_int32 code = 0;
+    char *cellname = NULL;
 
-       /* did file change? */
-       code = stat(tbuffer, &tstat);
-       if ((code == 0) && (tstat.st_mtime <= adir->timeRead)) {
-           code = 1;
-       }
-#ifdef AFS_NT40_ENV
+    LOCK_GLOBAL_MUTEX;
+    code = _afsconf_GetLocalCell(adir, &cellname, 0);
+    if (!code && cellname) {
+       strlcpy(aname, cellname, alen);
     }
-#endif
     UNLOCK_GLOBAL_MUTEX;
-    return code;
+    return (code);
 }
 
 int
@@ -1568,6 +1565,7 @@ afsconf_CloseInternal(struct afsconf_dir *adir)
     }
 
     _afsconf_FreeAllKeys(adir);
+    _afsconf_FreeRealms(adir);
 
     /* reinit */
     memset(adir, 0, sizeof(struct afsconf_dir));