* 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 <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 <errno.h>
#include <ctype.h>
#include <time.h>
/* 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;
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];
}
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;
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
+afsconf_GetAfsdbInfo(acellName, aservice, acellInfo)
+ char *acellName;
+ char *aservice;
+ struct afsconf_cell *acellInfo;
+{
+ afs_int32 code;
+ int tservice, len, i;
+ unsigned char answer[1024];
+ unsigned char *p;
+ 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;
+ strncpy(acellInfo->name, host, sizeof(acellInfo->name));
+
+ 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];
+ 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;
+ 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;
+}
+#endif /* AFS_AFSDB_ENV */
+
afsconf_GetCellInfo(adir, acellName, aservice, acellInfo)
struct afsconf_dir *adir;
char *aservice;
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 */
}
}
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);
+ code = afsconf_Check(adir);
+ if (code)
+ return AFSCONF_FAILURE;
bcopy(adir->keystr, astr, 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 */
{
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++) {