From 41baf5c58fabc62145731be1d6c99c833c8ee003 Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Wed, 7 Oct 2009 09:21:53 -0400 Subject: [PATCH] add SRV record lookups to unix afsconf support suite also create new api call afsconf_LookupServer make afsconf_GetAfsdbInfo call it include T_SRV support Reviewed-on: http://gerrit.openafs.org/594 Reviewed-by: Simon Wilkinson Tested-by: Simon Wilkinson Reviewed-by: Derrick Brashear Reviewed-by: Jeffrey Altman --- src/auth/cellconfig.c | 223 ++++++++++++++++++++++++++--------- src/auth/test/Makefile.in | 7 +- src/auth/test/testcellconf.c | 13 +- 3 files changed, 176 insertions(+), 67 deletions(-) diff --git a/src/auth/cellconfig.c b/src/auth/cellconfig.c index d2351e024..cf29a1e4d 100644 --- a/src/auth/cellconfig.c +++ b/src/auth/cellconfig.c @@ -991,58 +991,93 @@ afsconf_GetExtendedCellInfo(struct afsconf_dir *adir, char *acellName, #ifdef AFS_AFSDB_ENV #if !defined(AFS_NT40_ENV) int -afsconf_GetAfsdbInfo(char *acellName, char *aservice, - struct afsconf_cell *acellInfo) +afsconf_LookupServer(const char *service, const char *protocol, + const char *cellName, unsigned short afsdbPort, + int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS], + unsigned short ports[], unsigned short ipRanks[], + int *numServers, int *ttl, char *realCellName) { - afs_int32 code; - int tservice, i, len; + int code = 0; + int len; unsigned char answer[1024]; unsigned char *p; char *dotcellname; - int cellnamelength; - char realCellName[256]; + int cellnamelength, fullnamelength; char host[256]; int server_num = 0; int minttl = 0; int try_init = 0; + int dnstype = 0; + int pass = 0; + char *IANAname = (char *) afsconf_FindIANAName(service); + int tservice = afsconf_FindService(service); - /* The resolver isn't always MT-safe.. Perhaps this ought to be - * replaced with a more fine-grained lock just for the resolver - * operations. - */ + realCellName = NULL; + + *numServers = 0; + *ttl = 0; + if (tservice <= 0 || !IANAname) + return AFSCONF_NOTFOUND; /* service not found */ + + 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 */ retryafsdb: - if ( ! strchr(acellName,'.') ) { - cellnamelength=strlen(acellName); - dotcellname=malloc(cellnamelength+2); - memcpy(dotcellname,acellName,cellnamelength); - dotcellname[cellnamelength]='.'; - dotcellname[cellnamelength+1]=0; - LOCK_GLOBAL_MUTEX; - len = res_search(dotcellname, C_IN, T_AFSDB, answer, sizeof(answer)); - if ( len < 0 ) { - len = res_search(acellName, C_IN, T_AFSDB, answer, sizeof(answer)); - } - UNLOCK_GLOBAL_MUTEX; - free(dotcellname); - } else { - LOCK_GLOBAL_MUTEX; - len = res_search(acellName, C_IN, T_AFSDB, answer, sizeof(answer)); - UNLOCK_GLOBAL_MUTEX; + switch (pass) { + case 0: + dnstype = T_SRV; + code = snprintf(dotcellname, fullnamelength, "_%s._%s.%s.", + IANAname, protocol, cellName); + break; + case 1: + dnstype = T_AFSDB; + code = snprintf(dotcellname, fullnamelength, "%s.", + cellName); + break; + case 2: + dnstype = T_SRV; + code = snprintf(dotcellname, fullnamelength, "_%s._%s.%s", + IANAname, protocol, cellName); + break; + case 3: + dnstype = T_AFSDB; + code = snprintf(dotcellname, fullnamelength, "%s", + cellName); + break; } + if ((code < 0) || (code >= fullnamelength)) + goto findservererror; + LOCK_GLOBAL_MUTEX; + len = res_search(dotcellname, C_IN, dnstype, answer, sizeof(answer)); + UNLOCK_GLOBAL_MUTEX; + if (len < 0) { if (try_init < 1) { try_init++; res_init(); goto retryafsdb; } - return AFSCONF_NOTFOUND; + if (pass < 3) { + pass++; + goto retryafsdb; + } else { + code = AFSCONF_NOTFOUND; + goto findservererror; + } } p = answer + sizeof(HEADER); /* Skip header */ code = dn_expand(answer, answer + len, p, host, sizeof(host)); - if (code < 0) - return AFSCONF_NOTFOUND; + if (code < 0) { + code = AFSCONF_NOTFOUND; + goto findservererror; + } p += code + QFIXEDSZ; /* Skip name */ @@ -1050,8 +1085,10 @@ afsconf_GetAfsdbInfo(char *acellName, char *aservice, int type, ttl, size; code = dn_expand(answer, answer + len, p, host, sizeof(host)); - if (code < 0) - return AFSCONF_NOTFOUND; + if (code < 0) { + code = AFSCONF_NOTFOUND; + goto findservererror; + } p += code; /* Skip the name */ type = (p[0] << 8) | p[1]; @@ -1072,21 +1109,51 @@ afsconf_GetAfsdbInfo(char *acellName, char *aservice, * right AFSDB type. Write down the true cell name that * the resolver gave us above. */ - strlcpy(realCellName, host, sizeof realCellName); + realCellName = strdup(host); } code = dn_expand(answer, answer + len, p + 2, host, sizeof(host)); - if (code < 0) - return AFSCONF_NOTFOUND; + if (code < 0) { + code = AFSCONF_NOTFOUND; + goto findservererror; + } 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])); + cellHostAddrs[server_num] = ipaddr; + ports[server_num] = htons(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) { + struct hostent *he; + + code = dn_expand(answer, answer + len, p + 6, host, sizeof(host)); + if (code < 0) { + code = AFSCONF_NOTFOUND; + goto findservererror; + } + + 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] = (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) @@ -1097,28 +1164,74 @@ afsconf_GetAfsdbInfo(char *acellName, char *aservice, p += size; } - if (server_num == 0) /* No AFSDB records */ - return AFSCONF_NOTFOUND; + if (server_num == 0) { /* No AFSDB or SRV records */ + code = AFSCONF_NOTFOUND; + goto findservererror; + } - /* Convert the real cell name to lowercase */ - for (p = (unsigned char *)realCellName; *p; p++) - *p = tolower(*p); + if (realCellName) { + /* Convert the real cell name to lowercase */ + for (p = (unsigned char *)realCellName; *p; p++) + *p = tolower(*p); + } - strncpy(acellInfo->name, realCellName, sizeof(acellInfo->name)); - acellInfo->numServers = server_num; + *numServers = server_num; + *ttl = minttl ? (time(0) + minttl) : 0; - 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; - } - } + if ( *numServers > 0 ) + code = 0; + else + code = AFSCONF_NOTFOUND; - acellInfo->timeout = minttl ? (time(0) + minttl) : 0; +findservererror: + free(dotcellname); + return code; +} - return 0; +int +afsconf_GetAfsdbInfo(char *acellName, char *aservice, + struct afsconf_cell *acellInfo) +{ + afs_int32 cellHostAddrs[AFSMAXCELLHOSTS]; + char cellHostNames[AFSMAXCELLHOSTS][MAXHOSTCHARS]; + unsigned short ipRanks[AFSMAXCELLHOSTS]; + unsigned short ports[AFSMAXCELLHOSTS]; + char *realCellName = NULL; + int ttl, numServers, i; + char *service = aservice; + int code; + unsigned short afsdbport; + if (!service) { + service = "afs3-vlserver"; + afsdbport = 7003; + } else { + service = aservice; + afsdbport = afsconf_FindService(service); + } + code = afsconf_LookupServer((const char *)service, "udp", + (const char *)acellName, afsdbport, + cellHostAddrs, cellHostNames, + ports, ipRanks, &numServers, &ttl, + realCellName); + + if (code == 0) { + acellInfo->timeout = ttl; + acellInfo->numServers = numServers; + for (i = 0; i < numServers; i++) { + memcpy(&acellInfo->hostAddr[i].sin_addr.s_addr, &cellHostAddrs[i], + sizeof(afs_int32)); + memcpy(acellInfo->hostName[i], cellHostNames[i], MAXHOSTCHARS); + acellInfo->hostAddr[i].sin_family = AF_INET; + acellInfo->hostAddr[i].sin_port = ports[i]; + + if (realCellName) + strlcpy(acellInfo->name, realCellName, + sizeof(acellInfo->name)); + } + acellInfo->linkedCell = NULL; /* no linked cell */ + acellInfo->flags = 0; + } + return code; } #else /* windows */ int diff --git a/src/auth/test/Makefile.in b/src/auth/test/Makefile.in index 2e6deac35..7582137eb 100644 --- a/src/auth/test/Makefile.in +++ b/src/auth/test/Makefile.in @@ -12,11 +12,8 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INCDIRS= -I./ -I${DESTDIR}/include -LDIRS= -L${DESTDIR}/lib -L${DESTDIR}/lib/afs -L${DESTDIR}/lib/rx -LIBS= -lauth -lsys -lrx -llwp -lafsutil ${XLIBS} - -CFLAGS = ${OPTIMIZE} ${INCDIRS} ${LDIRS} ${XCFLAGS} ${ARCHFLAGS} +LIBS= ../libauth.a ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/libsys.a \ + ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/util.a ${XLIBS} tests all: testcellconf ktctest diff --git a/src/auth/test/testcellconf.c b/src/auth/test/testcellconf.c index af1608ce1..1301c721d 100644 --- a/src/auth/test/testcellconf.c +++ b/src/auth/test/testcellconf.c @@ -47,16 +47,15 @@ PrintOneCell(struct afsconf_cell *ainfo, void *arock, struct afsconf_dir *adir) printf("Cell %s:\n", ainfo->name); for (i = 0; i < ainfo->numServers; i++) { memcpy(&temp, &ainfo->hostAddr[i].sin_addr, sizeof(long)); - printf(" host %s at %x.%x\n", ainfo->hostName[i], temp, + printf(" host %s at %lx.%x\n", ainfo->hostName[i], temp, ainfo->hostAddr[i].sin_port); } return 0; } /*Main for testcellconfig*/ -main(argc, argv) - int argc; - char *argv[]; +int +main(int argc, char *argv[]) { struct afsconf_dir *theDir; char tbuffer[1024]; @@ -87,7 +86,7 @@ main(argc, argv) /* get the cell */ code = afsconf_GetLocalCell(theDir, tbuffer, sizeof(tbuffer)); if (code != 0) { - printf("get local cell failed, code %d\n", code); + printf("get local cell failed, code %ld\n", code); exit(1); } printf("Local cell is '%s'\n\n", tbuffer); @@ -100,7 +99,7 @@ main(argc, argv) printf("start of special test\n"); code = afsconf_GetCellInfo(theDir, NULL, "afsprot", &theCell); if (code) - printf("failed to find afsprot service (%d)\n", code); + printf("failed to find afsprot service (%ld)\n", code); else { printf("AFSPROT service:\n"); PrintOneCell(&theCell, NULL, theDir); @@ -117,7 +116,7 @@ main(argc, argv) for (i = 2; i < argc; i++) { code = afsconf_GetCellInfo(theDir, argv[i], 0, &theCell); if (code) { - printf("Could not find info for cell '%s', code %d\n", + printf("Could not find info for cell '%s', code %ld\n", argv[i], code); } else PrintOneCell(&theCell, NULL, theDir); -- 2.39.5