add SRV record lookups to unix afsconf support suite also
authorDerrick Brashear <shadow@dementia.org>
Wed, 7 Oct 2009 13:21:53 +0000 (09:21 -0400)
committerJeffrey Altman <jaltman|account-1000011@unknown>
Wed, 14 Oct 2009 21:51:15 +0000 (14:51 -0700)
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 <sxw@inf.ed.ac.uk>
Tested-by: Simon Wilkinson <sxw@inf.ed.ac.uk>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>

src/auth/cellconfig.c
src/auth/test/Makefile.in
src/auth/test/testcellconf.c

index d2351e0..cf29a1e 100644 (file)
@@ -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
index 2e6deac..7582137 100644 (file)
@@ -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
 
index af1608c..1301c72 100644 (file)
@@ -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);