* directory or online at http://www.openafs.org/dl/license10.html
*/
+#include <afsconfig.h>
#include <afs/param.h>
+
+RCSID("$Header$");
+
#include <afs/stds.h>
#include <afs/pthread_glock.h>
#ifdef UKERNEL
#include <sys/utime.h>
#include <io.h>
#include <WINNT/afssw.h>
+#ifdef AFS_AFSDB_ENV
+#include <cm_dns.h>
+#endif /* AFS_AFSDB_ENV */
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/time.h>
-#endif
+#ifdef AFS_AFSDB_ENV
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif /* AFS_AFSDB_ENV */
+#endif /* AFS_NT40_ENV */
+#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>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#endif /* UKERNEL */
#include <afs/afsutil.h>
#include "cellconfig.h"
static afsconf_Reopen();
static struct afsconf_servPair serviceTable [] = {
- "afs", 7000,
- "afscb", 7001,
- "afsprot", 7002,
- "afsvldb", 7003,
- "afskauth", 7004,
- "afsvol", 7005,
- "afserror", 7006,
- "afsnanny", 7007,
- "afsupdate",7008,
- "afsrmtsys",7009,
- 0, 0 /* insert new services before this spot */
+ { "afs", 7000, },
+ { "afscb", 7001, },
+ { "afsprot", 7002, },
+ { "afsvldb", 7003, },
+ { "afskauth", 7004, },
+ { "afsvol", 7005, },
+ { "afserror", 7006, },
+ { "afsnanny", 7007, },
+ { "afsupdate", 7008, },
+ { "afsrmtsys", 7009, },
+ { "afsres", 7010, }, /* residency database for MR-AFS */
+ { "afsremio", 7011, }, /* remote I/O interface for MR-AFS */
+ { 0, 0 } /* insert new services before this spot */
};
/*
/* lookup a service name */
struct servent *ts;
register struct afsconf_servPair *tsp;
+
#if defined(AFS_OSF_ENV) || defined(AFS_DEC_ENV)
ts = getservbyname(aname, "");
#else
/* we found it in /etc/services, so we use this value */
return ts->s_port; /* already in network byte order */
}
+
/* not found in /etc/services, see if it is one of ours */
for(tsp = serviceTable;; tsp++) {
if (tsp->name == (char *) 0) return -1;
register int tc;
tp = abuffer;
- while (tc = *tp) {
+ while ((tc = *tp)) {
if (!isspace(tc)) break;
tp++;
}
static afsconf_Touch(adir)
register struct afsconf_dir *adir; {
char tbuffer[256];
+#ifndef AFS_NT40_ENV
struct timeval tvp[2];
+#endif
+
+ adir->timeRead = 0; /* just in case */
#ifdef AFS_NT40_ENV
/* NT client CellServDB has different file name than NT server or Unix */
+
if (IsClientConfigDirectory(adir->name)) {
strcompose(tbuffer, 256,
adir->name, "/", AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
strcompose(tbuffer, 256,
adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
}
-#else
- strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
-#endif /* AFS_NT40_ENV */
- adir->timeRead = 0; /* just in case */
-#ifdef AFS_NT40_ENV
return _utime(tbuffer, NULL);
+
#else
+ strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
gettimeofday(&tvp[0], NULL);
tvp[1] = tvp[0];
return utimes(tbuffer, tvp);
LOCK_GLOBAL_MUTEX
/* zero structure and fill in name; rest is done by internal routine */
tdir = (struct afsconf_dir *) malloc(sizeof(struct afsconf_dir));
- bzero(tdir, sizeof(struct afsconf_dir));
+ memset(tdir, 0, sizeof(struct afsconf_dir));
tdir->name = (char *) malloc(strlen(adir)+1);
strcpy(tdir->name, adir);
- code = afsconf_OpenInternal(tdir);
+ code = afsconf_OpenInternal(tdir, 0, 0);
if (code) {
char *afsconf_path, *getenv(), afs_confdir[128];
/* 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;
FILE *fp;
- int len;
+ size_t len;
if (!(home_dir = getenv("HOME"))) {
/* Our last chance is the "/.AFSCONF" file */
}
tdir->name = (char *) malloc(strlen(afsconf_path)+1);
strcpy(tdir->name, afsconf_path);
- code = afsconf_OpenInternal(tdir);
+ code = afsconf_OpenInternal(tdir, 0, 0);
if (code) {
free(tdir->name);
free(tdir);
#endif /* AFS_NT40_ENV */
-static int afsconf_OpenInternal(adir)
-register struct afsconf_dir *adir; {
+static int afsconf_OpenInternal(adir, cell, clones)
+register struct afsconf_dir *adir;
+char *cell;
+char clones[];
+{
FILE *tf;
register char *tp, *bp;
register struct afsconf_entry *curEntry;
#else
i = GetCellUnix(adir);
#endif
+
+#ifndef AFS_FREELANCE_CLIENT /* no local cell not fatal in freelance */
if (i) {
return i;
}
+#endif
/* now parse the individual lines */
curEntry = 0;
curEntry = 0;
}
curEntry = (struct afsconf_entry *) malloc(sizeof(struct afsconf_entry));
- bzero(curEntry, sizeof(struct afsconf_entry));
+ memset(curEntry, 0, sizeof(struct afsconf_entry));
code = ParseCellLine(tbuffer, curEntry->cellInfo.name, linkedcell);
if (code) {
afsconf_CloseInternal(adir);
return -1;
}
i = curEntry->cellInfo.numServers;
- code = ParseHostLine(tbuffer, (char *) &curEntry->cellInfo.hostAddr[i], curEntry->cellInfo.hostName[i]);
+ if (cell && !strcmp(cell, curEntry->cellInfo.name))
+ code = ParseHostLine(tbuffer, (char *) &curEntry->cellInfo.hostAddr[i], curEntry->cellInfo.hostName[i], &clones[i]);
+ else
+ code = ParseHostLine(tbuffer, (char *) &curEntry->cellInfo.hostAddr[i], curEntry->cellInfo.hostName[i], 0);
if (code) {
if (code == AFSCONF_SYNTAX) {
for (bp=tbuffer; *bp != '\n'; bp++) { /* Take out the <cr> from the buffer */
}
/* parse a line of the form
- *"128.2.1.3 #hostname"
+ *"128.2.1.3 #hostname" or
+ *"[128.2.1.3] #hostname" for clones
* into the appropriate pieces.
*/
-static ParseHostLine(aline, addr, aname)
-register struct sockaddr_in *addr;
-char *aline, *aname; {
+static ParseHostLine(aline, addr, aname, aclone)
+ char *aclone;
+ register struct sockaddr_in *addr;
+ char *aline, *aname;
+{
int c1, c2, c3, c4;
register afs_int32 code;
register char *tp;
- code = sscanf(aline, "%d.%d.%d.%d #%s", &c1, &c2, &c3, &c4, aname);
+ if (*aline == '[') {
+ if (aclone) *aclone = 1;
+ code = sscanf(aline, "[%d.%d.%d.%d] #%s", &c1, &c2, &c3, &c4, aname);
+ } else {
+ if (aclone) *aclone = 0;
+ code = sscanf(aline, "%d.%d.%d.%d #%s", &c1, &c2, &c3, &c4, aname);
+ }
if (code != 5) return AFSCONF_SYNTAX;
addr->sin_family = AF_INET;
addr->sin_port = 0;
}
afs_int32 afsconf_SawCell = 0;
+
+afsconf_GetExtendedCellInfo(adir, acellName, aservice, acellInfo, clones)
+ struct afsconf_dir *adir;
+ char *aservice;
+ char *acellName;
+ struct afsconf_cell *acellInfo;
+ char clones[];
+{
+ afs_int32 code;
+ char *cell;
+
+ code = afsconf_GetCellInfo(adir, acellName, aservice, acellInfo);
+ if (code)
+ return code;
+
+ if (acellName)
+ cell = acellName;
+ else
+ cell = (char *) &acellInfo->name;
+
+ code = afsconf_OpenInternal(adir, cell, clones);
+ return code;
+}
+
+#ifdef AFS_AFSDB_ENV
+#if !defined(AFS_NT40_ENV)
+afsconf_GetAfsdbInfo(acellName, aservice, acellInfo)
+ char *acellName;
+ char *aservice;
+ struct afsconf_cell *acellInfo;
+{
+ afs_int32 code;
+ int tservice, i;
+ size_t len;
+ unsigned char answer[1024];
+ unsigned char *p;
+ char realCellName[256];
+ char host[256];
+ int server_num = 0;
+ int minttl = 0;
+
+ /* The resolver isn't always MT-safe.. Perhaps this ought to be
+ * replaced with a more fine-grained lock just for the resolver
+ * operations.
+ */
+ LOCK_GLOBAL_MUTEX
+ len = res_search(acellName, C_IN, T_AFSDB, answer, sizeof(answer));
+ UNLOCK_GLOBAL_MUTEX
+
+ if (len < 0)
+ return AFSCONF_NOTFOUND;
+
+ p = answer + sizeof(HEADER); /* Skip header */
+ code = dn_expand(answer, answer + len, p, host, sizeof(host));
+ if (code < 0)
+ return AFSCONF_NOTFOUND;
+
+ p += code + QFIXEDSZ; /* Skip name */
+
+ while (p < answer + len) {
+ int type, ttl, size;
+
+ code = dn_expand(answer, answer + len, p, host, sizeof(host));
+ if (code < 0)
+ return AFSCONF_NOTFOUND;
+
+ p += code; /* Skip the name */
+ type = (p[0] << 8) | p[1];
+ p += 4; /* Skip type and class */
+ ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ p += 4; /* Skip the TTL */
+ size = (p[0] << 8) | p[1];
+ p += 2; /* Skip the size */
+
+ if (type == T_AFSDB) {
+ struct hostent *he;
+ short afsdb_type;
+
+ afsdb_type = (p[0] << 8) | p[1];
+ if (afsdb_type == 1) {
+ /*
+ * We know this is an AFSDB record for our cell, of the
+ * right AFSDB type. Write down the true cell name that
+ * the resolver gave us above.
+ */
+ strcpy(realCellName, host);
+ }
+
+ code = dn_expand(answer, answer+len, p+2, host, sizeof(host));
+ if (code < 0)
+ return AFSCONF_NOTFOUND;
+
+ 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);
+ acellInfo->hostAddr[server_num].sin_addr.s_addr = ipaddr;
+ strncpy(acellInfo->hostName[server_num], host,
+ sizeof(acellInfo->hostName[server_num]));
+ server_num++;
+
+ if (!minttl || ttl < minttl) minttl = ttl;
+ }
+ }
+
+ p += size;
+ }
+
+ if (server_num == 0) /* No AFSDB records */
+ return AFSCONF_NOTFOUND;
+ strncpy(acellInfo->name, realCellName, sizeof(acellInfo->name));
+ acellInfo->numServers = server_num;
+
+ if (aservice) {
+ tservice = afsconf_FindService(aservice);
+ if (tservice < 0)
+ return AFSCONF_NOTFOUND; /* service not found */
+ for (i=0; i<acellInfo->numServers; i++) {
+ acellInfo->hostAddr[i].sin_port = tservice;
+ }
+ }
+
+ acellInfo->timeout = minttl ? (time(0) + minttl) : 0;
+
+ return 0;
+}
+#else /* windows */
+int afsconf_GetAfsdbInfo(acellName, aservice, acellInfo)
+ char *aservice;
+ char *acellName;
+ struct afsconf_cell *acellInfo;
+{
+ register afs_int32 i;
+ int tservice;
+ struct afsconf_entry DNSce;
+ char *DNStmpStrp; /* a temp string pointer */
+ struct hostent *thp;
+ afs_int32 cellHosts[AFSMAXCELLHOSTS];
+ int numServers;
+ int rc;
+ int *ttl;
+
+ DNSce.cellInfo.numServers=0;
+ DNSce.next = NULL;
+ rc = getAFSServer(acellName, cellHosts, &numServers, &ttl);
+ /* ignore the ttl here since this code is only called by transitory programs
+ like klog, etc. */
+ if (rc < 0)
+ return -1;
+ if (numServers == 0)
+ return -1;
+
+ for (i = 0; i < numServers; i++)
+ {
+ memcpy(&acellInfo->hostAddr[i].sin_addr.s_addr, &cellHosts[i], sizeof(long));
+ acellInfo->hostAddr[i].sin_family = AF_INET;
+
+ /* sin_port supplied by connection code */
+ }
+
+ acellInfo->numServers = numServers;
+ strcpy(acellInfo->name, acellName);
+ if (aservice) {
+ LOCK_GLOBAL_MUTEX
+ tservice = afsconf_FindService(aservice);
+ UNLOCK_GLOBAL_MUTEX
+ if (tservice < 0) {
+ return AFSCONF_NOTFOUND; /* service not found */
+ }
+ for(i=0; i< acellInfo->numServers; i++) {
+ acellInfo->hostAddr[i].sin_port = tservice;
+ }
+ }
+ acellInfo->linkedCell = NULL; /* no linked cell */
+ acellInfo->flags = 0;
+ return 0;
+}
+#endif /* windows */
+#endif /* AFS_AFSDB_ENV */
+
afsconf_GetCellInfo(adir, acellName, aservice, acellInfo)
struct afsconf_dir *adir;
char *aservice;
register afs_int32 i;
int tservice;
char *tcell;
- int cnLen, ambig;
+ size_t cnLen;
+ int ambig;
char tbuffer[64];
LOCK_GLOBAL_MUTEX
tcell = acellName;
cnLen = strlen(tcell)+1;
lcstring (tcell, tcell, cnLen);
- afsconf_SawCell = 1; /* will ignore the AFSCELL switch on future */
- /* call to afsconf_GetLocalCell: like klog */
+ afsconf_SawCell = 1; /* will ignore the AFSCELL switch on future */
+ /* call to afsconf_GetLocalCell: like klog */
} else {
i = afsconf_GetLocalCell(adir, tbuffer, sizeof(tbuffer));
if (i) {
acellInfo->hostAddr[i].sin_port = tservice;
}
}
+ acellInfo->timeout = 0;
UNLOCK_GLOBAL_MUTEX
return 0;
}
else {
UNLOCK_GLOBAL_MUTEX
+#ifdef AFS_AFSDB_ENV
+ return afsconf_GetAfsdbInfo(acellName, aservice, acellInfo);
+#else
return AFSCONF_NOTFOUND;
+#endif /* AFS_AFSDB_ENV */
}
}
if (adir->keystr) free(adir->keystr);
/* reinit */
- bzero(adir, sizeof(struct afsconf_dir));
+ memset(adir, 0, sizeof(struct afsconf_dir));
adir->name = tname; /* restore it */
return 0;
}
register afs_int32 code;
code = afsconf_CloseInternal(adir);
if (code) return code;
- code = afsconf_OpenInternal(adir);
+ code = afsconf_OpenInternal(adir, 0, 0);
return code;
}
struct afsconf_dir *adir;
struct afsconf_keys *astr;
{
+ register afs_int32 code;
+
LOCK_GLOBAL_MUTEX
- afsconf_Check(adir);
- bcopy(adir->keystr, astr, sizeof(struct afsconf_keys));
+ code = afsconf_Check(adir);
+ if (code)
+ return AFSCONF_FAILURE;
+ memcpy(astr, adir->keystr, sizeof(struct afsconf_keys));
UNLOCK_GLOBAL_MUTEX
return 0;
}
register struct afsconf_key *tk;
register afs_int32 best;
struct afsconf_key *bestk;
+ register afs_int32 code;
LOCK_GLOBAL_MUTEX
- afsconf_Check(adir);
+ code = afsconf_Check(adir);
+ if (code)
+ return AFSCONF_FAILURE;
maxa = adir->keystr->nkeys;
best = -1; /* highest kvno we've seen yet */
}
}
if (bestk) { /* found any */
- if (akey) bcopy(bestk->key, akey, 8); /* copy out latest key */
+ if (akey) memcpy(akey, bestk->key, 8); /* copy out latest key */
if (avno) *avno = bestk->kvno; /* and kvno to caller */
UNLOCK_GLOBAL_MUTEX
return 0;
{
register int i, maxa;
register struct afsconf_key *tk;
+ register afs_int32 code;
LOCK_GLOBAL_MUTEX
- afsconf_Check(adir);
+ code = afsconf_Check(adir);
+ if (code)
+ return AFSCONF_FAILURE;
maxa = adir->keystr->nkeys;
for(tk = adir->keystr->key,i=0;i<maxa;i++,tk++) {
if (tk->kvno == avno) {
- bcopy(tk->key, akey, 8);
+ memcpy(akey, tk->key, 8);
UNLOCK_GLOBAL_MUTEX
return 0;
}
register afs_int32 i;
char tbuffer[256];
- bcopy(adir->keystr, &tkeys, sizeof(struct afsconf_keys));
+ memcpy(&tkeys, adir->keystr, sizeof(struct afsconf_keys));
/* convert it to net byte order */
for(i = 0; i<tkeys.nkeys; i++ )
tkey = &tk->key[tk->nkeys++];
}
tkey->kvno = akvno;
- bcopy(akey, tkey->key, 8);
+ memcpy(tkey->key, akey, 8);
i = SaveKeys(adir);
afsconf_Touch(adir);
UNLOCK_GLOBAL_MUTEX
/* otherwise slide the others down. i and tkey point at the guy to delete */
for(;i<tk->nkeys-1; i++,tkey++) {
tkey->kvno = (tkey+1)->kvno;
- bcopy((tkey+1)->key, tkey->key, 8);
+ memcpy(tkey->key, (tkey+1)->key, 8);
}
tk->nkeys--;
i = SaveKeys(adir);