#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>
iop->buffer = malloc(BUFFER);
if (iop->buffer == NULL) {
(void) close(fd);
- free((void *) iop);
+ free(iop);
errno = ENOMEM;
return NULL;
}
return 0;
}
close(iop->_file);
- free((void *)iop->buffer);
- free((void *)iop);
+ free(iop->buffer);
+ free(iop);
return 0;
}
return 1;
}
-int
-_afsconf_UpToDate(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);
+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 */
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 *
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);
/* 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;
}
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
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;
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);
/* 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;
}
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) {
*bp = '\0';
fprintf(stderr,
"Can't properly parse host line \"%s\" in configuration file %s\n",
- tbuffer, tbuf1);
+ tbuffer, cellservDB);
}
free(curEntry);
fclose(tf);
} 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) {
#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) {
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);
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;
}
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;
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);
#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++;
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) {
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;
+ }
}
}
findservererror:
if (code && realCellName)
free(realCellName);
- free(dotcellname);
return code;
}
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;
* 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);
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)
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;
#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++;
}
}
+/**
+ * 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;
}
+ return code;
+}
+int
+afsconf_GetLocalCell(struct afsconf_dir *adir, char *aname, afs_int32 alen)
+{
+ afs_int32 code = 0;
+ char *cellname = NULL;
+
+ LOCK_GLOBAL_MUTEX;
+ code = _afsconf_GetLocalCell(adir, &cellname, 0);
+ if (!code && cellname) {
+ strlcpy(aname, cellname, alen);
+ }
UNLOCK_GLOBAL_MUTEX;
return (code);
}
}
_afsconf_FreeAllKeys(adir);
+ _afsconf_FreeRealms(adir);
/* reinit */
memset(adir, 0, sizeof(struct afsconf_dir));