int afsconf_LookupServer(const char *service, const char *protocol, const char *cellName, unsigned short afsdbPort, afs_uint32 *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS], unsigned short ports[], unsigned short ipRanks[], int *numServers, int *ttl, char **arealCellName) { int code = 0; int r; int len; unsigned char answer[4096]; unsigned char *p; char *dotcellname = NULL; char *realCellName; 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); realCellName = NULL; *numServers = 0; *ttl = 0; if (tservice <= 0 || !IANAname) return AFSCONF_NOTFOUND; /* service not found */ if (strchr(cellName,'.')) pass += 2; #ifdef HAVE_RES_RETRANSRETRY if ((_res.options & RES_INIT) == 0 && res_init() == -1) return (0); /* * Rx timeout is typically 56 seconds; limit user experience to * similar timeout */ _res.retrans = 18; _res.retry = 3; #endif retryafsdb: r = -1; switch (pass) { case 0: dnstype = T_SRV; r = asprintf(&dotcellname, "_%s._%s.%s.", IANAname, protocol, cellName); break; case 1: dnstype = T_AFSDB; r = asprintf(&dotcellname, "%s.", cellName); break; case 2: dnstype = T_SRV; r = asprintf(&dotcellname, "_%s._%s.%s", IANAname, protocol, cellName); break; case 3: dnstype = T_AFSDB; r = asprintf(&dotcellname, "%s", cellName); break; } 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++; res_init(); goto retryafsdb; } 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) { code = AFSCONF_NOTFOUND; goto findservererror; } 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) { code = AFSCONF_NOTFOUND; goto findservererror; } 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. */ if (!realCellName) realCellName = strdup(host); } code = dn_expand(answer, answer + len, p + 2, host, sizeof(host)); 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))) { if (he->h_addrtype == AF_INET) { afs_uint32 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) { struct hostent *he; /* math here: _ is 1, _ ._ is 3, _ ._ . is 4. then the domain. */ if ((strncmp(host + 1, IANAname, strlen(IANAname)) == 0) && (strncmp(host + strlen(IANAname) + 3, protocol, strlen(protocol)) == 0)) { if (!realCellName) realCellName = strdup(host + strlen(IANAname) + strlen(protocol) + 4); } 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))) { if (he->h_addrtype == AF_INET) { afs_uint32 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; } } } p += size; } if (server_num == 0) { /* No AFSDB or SRV records */ code = AFSCONF_NOTFOUND; goto findservererror; } if (realCellName) { /* Convert the real cell name to lowercase */ for (p = (unsigned char *)realCellName; *p; p++) *p = tolower(*p); } *numServers = server_num; *ttl = minttl ? (time(0) + minttl) : 0; if ( *numServers > 0 ) { code = 0; *arealCellName = realCellName; } else code = AFSCONF_NOTFOUND; findservererror: if (code && realCellName) free(realCellName); return code; }
/* 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; 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)); free(realCellName); realCellName = NULL; } } acellInfo->linkedCell = NULL; /* no linked cell */ acellInfo->flags = 0; } return code; } #else /* windows */ int afsconf_GetAfsdbInfo(char *acellName, char *aservice, struct afsconf_cell *acellInfo) { afs_int32 i; int tservice = afsconf_FindService(aservice); /* network byte order */ const char *ianaName = afsconf_FindIANAName(aservice); struct afsconf_entry DNSce; afs_uint32 cellHostAddrs[AFSMAXCELLHOSTS]; char cellHostNames[AFSMAXCELLHOSTS][MAXHOSTCHARS]; unsigned short ipRanks[AFSMAXCELLHOSTS]; unsigned short ports[AFSMAXCELLHOSTS]; /* network byte order */ int numServers; int rc; int ttl; if (tservice < 0) { if (aservice) return AFSCONF_NOTFOUND; else tservice = 0; /* port will be assigned by caller */ } if (ianaName == NULL) ianaName = "afs3-vlserver"; DNSce.cellInfo.numServers = 0; DNSce.next = NULL; rc = getAFSServer(ianaName, "udp", acellName, tservice, cellHostAddrs, cellHostNames, ports, ipRanks, &numServers, &ttl); /* ignore the ttl here since this code is only called by transitory programs * like klog, etc. */ /* 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 (rc < 0 && (tservice == htons(7002) || tservice == htons(7004))) { rc = getAFSServer("afs3-vlserver", "udp", acellName, tservice, cellHostAddrs, cellHostNames, ports, ipRanks, &numServers, &ttl); if (rc >= 0) { for (i = 0; i < numServers; i++) ports[i] = tservice; } } if (rc < 0 || numServers == 0) return -1; for (i = 0; i < numServers; i++) { memcpy(&acellInfo->hostAddr[i].sin_addr.s_addr, &cellHostAddrs[i], sizeof(afs_uint32)); memcpy(acellInfo->hostName[i], cellHostNames[i], MAXHOSTCHARS); acellInfo->hostAddr[i].sin_family = AF_INET; if (aservice) acellInfo->hostAddr[i].sin_port = ports[i]; else acellInfo->hostAddr[i].sin_port = 0; } acellInfo->numServers = numServers; strlcpy(acellInfo->name, acellName, sizeof acellInfo->name); acellInfo->linkedCell = NULL; /* no linked cell */ acellInfo->flags = 0; return 0; }
$NetBSD$ --- src/auth/cellconfig.c.orig 2012-04-22 23:40:23.000000000 -0400 +++ src/auth/cellconfig.c 2013-01-06 18:00:28.000000000 -0500 @@ -976,6 +976,11 @@ int pass = 0; char *IANAname = (char *) afsconf_FindIANAName(service); int tservice = afsconf_FindService(service); +#ifdef __NetBSD__ + res_state res; +#else +#define res (&_res) +#endif realCellName = NULL; @@ -994,15 +999,18 @@ return AFSCONF_NOTFOUND; /* service not found */ #ifdef HAVE_RES_RETRANSRETRY - if ((_res.options & RES_INIT) == 0 && res_init() == -1) +#ifdef __NetBSD__ + res = __res_get_state(); +#else + if ((res->options & RES_INIT) == 0 && res_init() == -1) return (0); - +#endif /* * Rx timeout is typically 56 seconds; limit user experience to * similar timeout