1 /* Copyright 2000, International Business Machines Corporation and others.
4 * This software has been released under the terms of the IBM Public
5 * License. For details, see the LICENSE file in the top-level source
6 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #include <afs/cellconfig.h>
18 #include "cm_dns_private.h"
22 #include <afs/afsint.h>
23 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500)
30 /*extern void afsi_log(char *pattern, ...);*/
32 static char dns_addr[30];
33 static int cm_dnsEnabled = -1;
35 void DNSlowerCase(char *str)
39 for (i=0; i<strlen(str); i++)
40 /*str[i] = tolower(str[i]);*/
41 if (str[i] >= 'A' && str[i] <= 'Z')
45 int cm_InitDNS(int enabled)
54 fprintf(stderr, "DNS support disabled\n");
59 /* First try AFS_NS environment var. */
60 addr = getenv("AFS_NS");
61 if (addr && inet_addr(addr) != -1) {
62 strcpy(dns_addr, addr);
64 /* Now check for the AFSDNS.INI file */
65 code = GetWindowsDirectory(configpath, sizeof(configpath));
66 if (code == 0 || code > sizeof(configpath)) return -1;
67 strcat(configpath, "\\afsdns.ini");
69 /* Currently we only get (and query) the first nameserver. Getting
70 list of mult. nameservers should be easy to do. */
71 len = GetPrivateProfileString("AFS Domain Name Servers", "ns1", NULL,
72 dns_addr, sizeof(dns_addr),
75 if (len == 0 || inet_addr(dns_addr) == -1) {
76 fprintf(stderr, "No valid name server addresses found, DNS lookup is "
78 cm_dnsEnabled = 0; /* failed */
79 return -1; /* No name servers defined */
82 fprintf(stderr, "Found DNS server %s\n", dns_addr);
84 #endif /* DNSAPI_ENV */
90 SOCKADDR_IN setSockAddr(char *server, int port)
93 int addrLen = sizeof(SOCKADDR_IN);
95 #ifndef WIN32_LEAN_AND_MEAN
96 bzero(&sockAddr,addrLen);
97 #endif /*WIN32_LEAN_AND_MEAN*/
98 sockAddr.sin_family = AF_INET;
99 sockAddr.sin_port = htons( port );
100 sockAddr.sin_addr.s_addr = inet_addr( server );
101 /*inet_aton(server, &sockAddr.sin_addr.s_addr);*/
106 int getRRCount(PDNS_HDR ptr)
108 return(ntohs(ptr->rr_count));
112 int send_DNS_Addr_Query(char* query,
113 SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
116 PDNS_QTAIL pDNS_qtail;
121 #ifndef WIN32_LEAN_AND_MEAN
122 bzero(buffer,BUFSIZE);
123 #endif /*WIN32_LEAN_AND_MEAN*/
125 /*********************************
126 * Build DNS Query Message *
128 * hard-coded Adrress (A) query *
129 *********************************/
131 pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
132 pDNShdr->id = htons( 0xDADE );
133 pDNShdr->flags = htons( DNS_FLAG_RD ); /* do recurse */
134 pDNShdr->q_count = htons( 1 ); /* one query */
135 pDNShdr->rr_count = 0; /* none in query */
136 pDNShdr->auth_count = 0; /* none in query */
137 pDNShdr->add_count = 0; /* none in query */
139 queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
140 queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
142 fprintf(stderr, "send_DNS_Addr: query=%s, queryLen=%d\n", query, queryLen);
146 pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
147 pDNS_qtail->qtype = htons(255);/*htons(DNS_RRTYPE_A); */
148 pDNS_qtail->qclass = htons(DNS_RRCLASS_IN);
149 queryLen += DNS_QTAIL_LEN;
151 /**************************
152 * Send DNS Query Message *
153 **************************/
156 res = sendto( commSock,
160 (struct sockaddr *) &sockAddr,
161 sizeof( SOCKADDR_IN ) );
163 /*dumpSbuffer(buffer,queryLen);*/
168 fprintf(stderr, "send_DNS_Addr_Query: error %d, errno %d\n", res, errno);
169 fprintf(stderr, "sendto() failed \n");
175 /*printf( "sendto() succeeded\n");*/
183 int send_DNS_AFSDB_Query(char* query,
184 SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
186 /*static char buffer[BUFSIZE];*/
189 PDNS_QTAIL pDNS_qtail;
194 #ifndef WIN32_LEAN_AND_MEAN
195 bzero(buffer,BUFSIZE);
196 #endif /*WIN32_LEAN_AND_MEAN*/
198 /***************************
199 * Build DNS Query Message *
201 * hard-coded AFSDB query *
202 ***************************/
204 pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
205 pDNShdr->id = htons( 0xDEAD );
206 pDNShdr->flags = htons( DNS_FLAG_RD ); /* do recurse */
207 pDNShdr->q_count = htons( 1 ); /* one query */
208 pDNShdr->rr_count = 0; /* none in query */
209 pDNShdr->auth_count = 0; /* none in query */
210 pDNShdr->add_count = 0; /* none in query */
212 queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
213 queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
216 pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
217 pDNS_qtail->qtype = htons(DNS_RRTYPE_AFSDB);
218 pDNS_qtail->qclass = htons(DNS_RRCLASS_IN);
219 queryLen += DNS_QTAIL_LEN;
221 /**************************
222 * Send DNS Query Message *
223 **************************/
225 res = sendto( commSock,
229 (struct sockaddr *) &sockAddr,
230 sizeof( SOCKADDR_IN ) );
232 /*dumpSbuffer(buffer,queryLen);*/
237 fprintf(stderr, "send_DNS_AFSDB_Query: error %d, errno %d\n", res, errno);
238 fprintf(stderr, "sendto() failed \n");
244 /*printf( "sendto() succeeded\n");*/
252 PDNS_HDR get_DNS_Response(SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
254 /*static char buffer[BUFSIZE];*/
256 int addrLen = sizeof(SOCKADDR_IN);
259 #ifndef WIN32_LEAN_AND_MEAN
260 bzero(buffer,BUFSIZE);
261 #endif /*WIN32_LEAN_AND_MEAN*/
263 /*****************************
264 * Receive DNS Reply Message *
265 *****************************/
267 /*printf( "calling recvfrom() on connected UDP socket\n" );*/
269 size = recvfrom( commSock,
273 (struct sockaddr *) &sockAddr,
275 if (size < 0) { fprintf(stderr, "recvfrom error %d\n", errno); return NULL; }
277 /*dumpRbuffer(buffer,res);*/
280 fprintf(stderr, "recvfrom returned %d bytes from %s: \n",
281 size, inet_ntoa( sockAddr.sin_addr ) );
284 return((PDNS_HDR)&( buffer[ 0 ] ));
289 int putQName( char *pHostName, char *pQName )
296 DNSlowerCase(pHostName);
297 /*printf( "Hostname: [%s]\n", pHostName );*/
299 for ( i = 0; *( pHostName + i ); i++ )
301 c = *( pHostName + i ); /* get next character */
306 /* dot encountered, fill in previous length */
307 if (k!=0){ /*don't process repeated dots*/
308 /*printf( "%c", c );*/
310 j = j+k+1; /* set index to next counter */
311 k = 0; /* reset segment length */
316 /*printf( "%c", c );*/
317 *( pQName + j + k + 1 ) = c; /* assign to QName */
318 k++; /* inc count of seg chars */
322 *(pQName + j ) = k; /* count for final segment */
324 *(pQName + j + k + 1 ) = 0; /* count for trailing NULL segment is 0 */
329 return ( j + k + 1 ); /* return total length of QName */
331 return ( j + k + 2 );
332 } /* end putQName() */
335 u_char * skipRRQName(u_char *pQName)
344 /* skip the 'compression' pointer */
348 /* skip a normal qname segment */
355 /* ptr now pointing at terminating zero of query QName,
356 or the pointer for the previous occurrence
362 } /* end skipRRQName() */
366 u_char * printRRQName( u_char *pQName, PDNS_HDR buffer )
369 u_char *buffPtr = (u_char *) buffer;
378 for ( i = 0; i < BUFSIZE; i++ )
389 for ( k = 1; k <= c; k++ )
391 fprintf(stderr, "%c", *( namePtr + k ) );
397 fprintf(stderr,"\n");
398 namePtr++; /* skip terminating zero */
405 } /* end printRRQName() */
408 u_char * sPrintRRQName( u_char *pQName, PDNS_HDR buffer, char *str )
411 u_char *buffPtr = (u_char *) buffer;
422 for ( i = 0; i < BUFSIZE; i++ )
433 for ( k = 1; k <= c; k++ )
435 sprintf(section,"%c", *( namePtr + k ) );
442 namePtr++; /* skip terminating zero */
449 } /* end sPrintRRQName() */
452 void printReplyBuffer_AFSDB(PDNS_HDR replyBuff)
454 u_char *ptr = (u_char *) replyBuff;
455 int answerCount = ntohs((replyBuff)->rr_count);
462 /* ptr now pointing at start of QName in query field */
463 ptr = skipRRQName(ptr);
466 /* skip the query type and class fields */
469 /* ptr should now be at the start of the answer RR sections */
471 fprintf(stderr,"---------------------------------\n");
472 for (i=0; i<answerCount ; i++){
473 ptr = skipRRQName(ptr);
474 rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
475 ptr+= DNS_AFSDB_RR_HDR_LEN;
476 if ( ntohs(rrPtr->rr_afsdb_class) == 1) {
477 fprintf(stderr,"AFDB class %d -> ",ntohs(rrPtr->rr_afsdb_class));
478 ptr = printRRQName(ptr,replyBuff); }
480 ptr = skipRRQName(ptr);
482 fprintf(stderr,"---------------------------------\n");
487 void processReplyBuffer_AFSDB(SOCKET commSock, PDNS_HDR replyBuff, int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
488 unsigned short ports[], unsigned short adminRanks[], int *numServers, int *ttl)
489 /*PAFS_SRV_LIST (srvList)*/
491 u_char *ptr = (u_char *) replyBuff;
492 int answerCount = ntohs((replyBuff)->rr_count);
503 /* ptr now pointing at start of QName in query field */
504 ptr = skipRRQName(ptr);
507 /* skip the query type and class fields */
510 /* ptr should now be at the start of the answer RR sections */
512 answerCount = min(answerCount, AFSMAXCELLHOSTS);
514 fprintf(stderr, "processRep_AFSDB: answerCount=%d\n", answerCount);
517 for (i=0; i<answerCount ; i++){
518 ptr = skipRRQName(ptr);
519 rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
520 ptr+= DNS_AFSDB_RR_HDR_LEN;
521 if ((ntohs(rrPtr->rr_afsdb_class) == 1) &&
522 (srvCount < MAX_AFS_SRVS)) {
523 /*ptr = sPrintRRQName(ptr,replyBuff,srvList->host[srvList->count]);*/
524 ptr = sPrintRRQName(ptr,replyBuff,hostName);
525 /*ptr = printRRQName(ptr,replyBuff);*/
526 *ttl = ntohl(rrPtr->rr_ttl);
529 fprintf(stderr, "resolving name %s\n", hostName);
531 /* resolve name from DNS query */
532 rc = DNSgetAddr(commSock, hostName, &addr);
534 continue; /* skip this entry */
536 fprintf(stderr, "processRep_AFSDB: resolved name %s to addr %x\n", hostName, addr);
538 memcpy(&cellHostAddrs[srvCount], &addr.s_addr, sizeof(addr.s_addr));
539 strncpy(cellHostNames[srvCount], hostName, CELL_MAXNAMELEN);
540 cellHostNames[srvCount][CELL_MAXNAMELEN-1] = '\0';
541 adminRanks[srvCount] = 0;
542 ports[srvCount] = htons(7003);
546 ptr = skipRRQName(ptr);
550 *numServers = srvCount;
555 u_char * processReplyBuffer_Addr(PDNS_HDR replyBuff)
557 u_char *ptr = (u_char *) replyBuff;
558 int answerCount = ntohs((replyBuff)->rr_count);
563 fprintf(stderr, "processReplyBuffer_Addr: answerCount=%d\n", answerCount);
565 if (answerCount == 0) return 0;
569 /* ptr now pointing at start of QName in query field */
570 ptr = skipRRQName(ptr);
573 /* skip the query type and class fields */
576 /* ptr should now be at the start of the answer RR sections */
577 ptr = skipRRQName(ptr);
578 rrPtr = (PDNS_A_RR_HDR) ptr;
581 fprintf(stderr, "type:%d, class:%d, ttl:%d, rdlength:%d\n",
582 ntohs(rrPtr->rr_type),ntohs(rrPtr->rr_class),
583 ntohl(rrPtr->rr_ttl),ntohs(rrPtr->rr_rdlength));
584 fprintf(stderr, "Count %d\tand Answer %8x\n",answerCount,rrPtr->rr_addr);
587 ptr += DNS_A_RR_HDR_LEN;
593 int DNSgetAddr(SOCKET commSock, char *hostName, struct in_addr *iNet)
595 /* Variables for DNS message parsing and creation */
598 SOCKADDR_IN sockAddr;
599 char buffer[BUFSIZE];
604 /**********************
605 * Get a DGRAM socket *
606 **********************/
608 sockAddr = setSockAddr(dns_addr, DNS_PORT);
610 rc = send_DNS_Addr_Query(hostName,commSock,sockAddr, buffer);
611 if (rc < 0) return rc;
612 pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
616 addr = processReplyBuffer_Addr(pDNShdr);
620 aPtr = (u_long *) addr;
622 iNet->s_addr = *aPtr;
626 #endif /* DNSAPI_ENV */
628 int getAFSServer(const char *service, const char *protocol, const char *cellName,
629 unsigned short afsdbPort, /* network byte order */
630 int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
631 unsigned short ports[], /* network byte order */
632 unsigned short adminRanks[],
633 int *numServers, int *ttl)
637 SOCKADDR_IN sockAddr;
639 char buffer[BUFSIZE];
644 fprintf(stderr, "getAFSServer: cell %s, cm_dnsEnabled=%d\n", cellName, cm_dnsEnabled);
650 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
651 if (cm_dnsEnabled == -1) { /* not yet initialized, eg when called by klog */
652 cm_InitDNS(1); /* assume enabled */
655 if (cm_dnsEnabled == 0) { /* possibly we failed in cm_InitDNS above */
656 fprintf(stderr, "DNS initialization failed, disabled\n");
660 if (service == NULL || protocol == NULL || cellName == NULL) {
661 fprintf(stderr, "invalid input\n");
665 sockAddr = setSockAddr(dns_addr, DNS_PORT);
667 commSock = socket( AF_INET, SOCK_DGRAM, 0 );
670 /*afsi_log("socket() failed\n");*/
671 fprintf(stderr, "getAFSServer: socket() failed, errno=%d\n", errno);
675 StringCbCopyA(query, sizeof(query), cellName);
676 if (query[strlen(query)-1] != '.') {
677 StringCbCatA(query, sizeof(query), ".");
680 rc = send_DNS_AFSDB_Query(query,commSock,sockAddr, buffer);
682 closesocket(commSock);
683 fprintf(stderr,"getAFSServer: send_DNS_AFSDB_Query failed\n");
687 pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
689 /*printReplyBuffer_AFSDB(pDNShdr);*/
691 processReplyBuffer_AFSDB(commSock, pDNShdr, cellHostAddrs, cellHostNames, ports, adminRanks, numServers, ttl);
693 closesocket(commSock);
694 if (*numServers == 0)
698 #else /* DNSAPI_ENV */
699 PDNS_RECORD pDnsCell, pDnsIter, pDnsVol, pDnsVolIter, pDnsCIter;
706 if (service == NULL || protocol == NULL || cellName == NULL)
709 #ifdef AFS_FREELANCE_CLIENT
710 if ( cm_stricmp_utf8N(cellName, "Freelance.Local.Root") == 0 )
712 #endif /* AFS_FREELANCE_CLIENT */
714 /* query the SRV _afs3-vlserver._udp records of cell */
715 StringCbPrintf(query, sizeof(query), "_%s._%s.%s", service, protocol, cellName);
716 if (query[strlen(query)-1] != '.') {
717 StringCbCatA(query, sizeof(query), ".");
720 if (DnsQuery_A(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
721 /* go through the returned records */
722 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
723 /* if we find an SRV record, we found the service */
724 if (pDnsIter->wType == DNS_TYPE_SRV) {
725 StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
726 pDnsIter->Data.SRV.pNameTarget);
727 adminRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
728 ports[*numServers] = htons(pDnsIter->Data.SRV.wPort);
732 *ttl = pDnsIter->dwTtl;
733 if (*numServers == AFSMAXCELLHOSTS)
738 for (i=0;i<*numServers;i++)
739 cellHostAddrs[i] = 0;
741 /* now check if there are any A records in the results */
742 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
743 if(pDnsIter->wType == DNS_TYPE_A)
744 /* check if its for one of the service */
745 for (i=0;i<*numServers;i++)
746 if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
747 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
750 for (i=0;i<*numServers;i++) {
751 /* if we don't have an IP yet, then we should try resolving the afs3-vlserver hostname
752 in a separate query. */
753 if (!cellHostAddrs[i]) {
754 if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
755 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
756 /* if we get an A record, keep it */
757 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
758 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
761 /* if we get a CNAME, look for a corresponding A record */
762 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
763 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
764 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
765 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
769 if (cellHostAddrs[i])
771 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
774 /* we are done with the service lookup */
775 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
779 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
782 /* query the AFSDB records of cell */
783 StringCbCopyA(query, sizeof(query), cellName);
784 if (query[strlen(query)-1] != '.') {
785 StringCbCatA(query, sizeof(query), ".");
788 if (DnsQuery_A(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
789 /* go through the returned records */
790 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
791 /* if we find an AFSDB record with Preference set to 1, we found a service instance */
792 if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
793 StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
794 pDnsIter->Data.Afsdb.pNameExchange);
795 adminRanks[*numServers] = 0;
796 ports[*numServers] = afsdbPort;
800 *ttl = pDnsIter->dwTtl;
801 if (*numServers == AFSMAXCELLHOSTS)
806 for (i=0;i<*numServers;i++)
807 cellHostAddrs[i] = 0;
809 /* now check if there are any A records in the results */
810 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
811 if(pDnsIter->wType == DNS_TYPE_A)
812 /* check if its for one of the service */
813 for (i=0;i<*numServers;i++)
814 if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
815 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
818 for (i=0;i<*numServers;i++) {
819 /* if we don't have an IP yet, then we should try resolving the service hostname
820 in a separate query. */
821 if (!cellHostAddrs[i]) {
822 if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
823 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
824 /* if we get an A record, keep it */
825 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
826 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
829 /* if we get a CNAME, look for a corresponding A record */
830 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
831 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
832 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
833 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
837 if (cellHostAddrs[i])
839 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
842 /* we are done with the service lookup */
843 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
847 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
851 if ( *numServers > 0 )
855 #endif /* DNSAPI_ENV */
858 int getAFSServerW(const cm_unichar_t *service, const cm_unichar_t *protocol, const cm_unichar_t *cellName,
859 unsigned short afsdbPort, /* network byte order */
861 cm_unichar_t cellHostNames[][MAXHOSTCHARS],
862 unsigned short ports[], /* network byte order */
863 unsigned short adminRanks[],
864 int *numServers, int *ttl)
867 PDNS_RECORDW pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
869 cm_unichar_t query[1024];
874 if (service == NULL || protocol == NULL || cellName == NULL)
877 #ifdef AFS_FREELANCE_CLIENT
878 if ( cm_stricmp_utf16(cellName, L"Freelance.Local.Root") == 0 )
880 #endif /* AFS_FREELANCE_CLIENT */
882 /* query the SRV _afs3-vlserver._udp records of cell */
883 StringCbPrintfW(query, sizeof(query), L"_%S._%S.%S", service, protocol, cellName);
884 if (query[wcslen(query)-1] != L'.') {
885 StringCbCatW(query, sizeof(query), L".");
888 if (DnsQuery_W(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
889 NULL) == ERROR_SUCCESS) {
890 /* go through the returned records */
891 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
892 /* if we find an SRV record, we found a service instance */
893 if (pDnsIter->wType == DNS_TYPE_SRV) {
894 StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
895 pDnsIter->Data.SRV.pNameTarget);
896 adminRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
897 ports[*numServers] = htons(pDnsIter->Data.SRV.wPort);
901 *ttl = pDnsIter->dwTtl;
902 if (*numServers == AFSMAXCELLHOSTS)
907 for (i=0;i<*numServers;i++)
908 cellHostAddrs[i] = 0;
910 /* now check if there are any A records in the results */
911 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
912 if(pDnsIter->wType == DNS_TYPE_A)
913 /* check if its for one of the service instances */
914 for (i=0;i<*numServers;i++)
915 if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
916 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
919 for (i=0;i<*numServers;i++) {
920 /* if we don't have an IP yet, then we should try resolving the service hostname
921 in a separate query. */
922 if (!cellHostAddrs[i]) {
923 if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
924 (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
925 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
926 /* if we get an A record, keep it */
927 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
928 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
931 /* if we get a CNAME, look for a corresponding A record */
932 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
933 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
934 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
935 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
939 if (cellHostAddrs[i])
941 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
944 /* we are done with the service lookup */
945 DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
949 DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
952 /* query the AFSDB records of cell */
953 StringCbCopyW(query, sizeof(query), cellName);
954 if (query[wcslen(query)-1] != L'.') {
955 StringCbCatW(query, sizeof(query), L".");
958 if (DnsQuery_W(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
959 NULL) == ERROR_SUCCESS) {
960 /* go through the returned records */
961 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
962 /* if we find an AFSDB record with Preference set to 1, we found a service instance */
963 if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
964 StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
965 pDnsIter->Data.Afsdb.pNameExchange);
966 adminRanks[*numServers] = 0;
967 ports[*numServers] = afsdbPort;
971 *ttl = pDnsIter->dwTtl;
972 if (*numServers == AFSMAXCELLHOSTS)
977 for (i=0;i<*numServers;i++)
978 cellHostAddrs[i] = 0;
980 /* now check if there are any A records in the results */
981 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
982 if(pDnsIter->wType == DNS_TYPE_A)
983 /* check if its for one of the service instances */
984 for (i=0;i<*numServers;i++)
985 if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
986 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
989 for (i=0;i<*numServers;i++) {
990 /* if we don't have an IP yet, then we should try resolving the service hostname
991 in a separate query. */
992 if (!cellHostAddrs[i]) {
993 if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
994 (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
995 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
996 /* if we get an A record, keep it */
997 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
998 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
1001 /* if we get a CNAME, look for a corresponding A record */
1002 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
1003 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
1004 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
1005 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
1009 if (cellHostAddrs[i])
1011 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
1014 /* we are done with the service lookup */
1015 DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
1019 DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
1023 if ( *numServers > 0 )
1026 #endif /* DNSAPI_ENV */