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
11 #include <afs/cellconfig.h>
14 #include "cm_dns_private.h"
18 #include <afs/afsint.h>
19 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500)
26 /*extern void afsi_log(char *pattern, ...);*/
28 static char dns_addr[30];
29 static int cm_dnsEnabled = -1;
31 void DNSlowerCase(char *str)
35 for (i=0; i<strlen(str); i++)
36 /*str[i] = tolower(str[i]);*/
37 if (str[i] >= 'A' && str[i] <= 'Z')
41 int cm_InitDNS(int enabled)
50 fprintf(stderr, "DNS support disabled\n");
55 /* First try AFS_NS environment var. */
56 addr = getenv("AFS_NS");
57 if (addr && inet_addr(addr) != -1) {
58 strcpy(dns_addr, addr);
60 /* Now check for the AFSDNS.INI file */
61 code = GetWindowsDirectory(configpath, sizeof(configpath));
62 if (code == 0 || code > sizeof(configpath)) return -1;
63 strcat(configpath, "\\afsdns.ini");
65 /* Currently we only get (and query) the first nameserver. Getting
66 list of mult. nameservers should be easy to do. */
67 len = GetPrivateProfileString("AFS Domain Name Servers", "ns1", NULL,
68 dns_addr, sizeof(dns_addr),
71 if (len == 0 || inet_addr(dns_addr) == -1) {
72 fprintf(stderr, "No valid name server addresses found, DNS lookup is "
74 cm_dnsEnabled = 0; /* failed */
75 return -1; /* No name servers defined */
78 fprintf(stderr, "Found DNS server %s\n", dns_addr);
80 #endif /* DNSAPI_ENV */
86 SOCKADDR_IN setSockAddr(char *server, int port)
89 int addrLen = sizeof(SOCKADDR_IN);
91 #ifndef WIN32_LEAN_AND_MEAN
92 bzero(&sockAddr,addrLen);
93 #endif /*WIN32_LEAN_AND_MEAN*/
94 sockAddr.sin_family = AF_INET;
95 sockAddr.sin_port = htons( port );
96 sockAddr.sin_addr.s_addr = inet_addr( server );
97 /*inet_aton(server, &sockAddr.sin_addr.s_addr);*/
102 int getRRCount(PDNS_HDR ptr)
104 return(ntohs(ptr->rr_count));
108 int send_DNS_Addr_Query(char* query,
109 SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
112 PDNS_QTAIL pDNS_qtail;
117 #ifndef WIN32_LEAN_AND_MEAN
118 bzero(buffer,BUFSIZE);
119 #endif /*WIN32_LEAN_AND_MEAN*/
121 /*********************************
122 * Build DNS Query Message *
124 * hard-coded Adrress (A) query *
125 *********************************/
127 pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
128 pDNShdr->id = htons( 0xDADE );
129 pDNShdr->flags = htons( DNS_FLAG_RD ); /* do recurse */
130 pDNShdr->q_count = htons( 1 ); /* one query */
131 pDNShdr->rr_count = 0; /* none in query */
132 pDNShdr->auth_count = 0; /* none in query */
133 pDNShdr->add_count = 0; /* none in query */
135 queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
136 queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
138 fprintf(stderr, "send_DNS_Addr: query=%s, queryLen=%d\n", query, queryLen);
142 pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
143 pDNS_qtail->qtype = htons(255);/*htons(DNS_RRTYPE_A); */
144 pDNS_qtail->qclass = htons(DNS_RRCLASS_IN);
145 queryLen += DNS_QTAIL_LEN;
147 /**************************
148 * Send DNS Query Message *
149 **************************/
152 res = sendto( commSock,
156 (struct sockaddr *) &sockAddr,
157 sizeof( SOCKADDR_IN ) );
159 /*dumpSbuffer(buffer,queryLen);*/
164 fprintf(stderr, "send_DNS_Addr_Query: error %d, errno %d\n", res, errno);
165 fprintf(stderr, "sendto() failed \n");
171 /*printf( "sendto() succeeded\n");*/
179 int send_DNS_AFSDB_Query(char* query,
180 SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
182 /*static char buffer[BUFSIZE];*/
185 PDNS_QTAIL pDNS_qtail;
190 #ifndef WIN32_LEAN_AND_MEAN
191 bzero(buffer,BUFSIZE);
192 #endif /*WIN32_LEAN_AND_MEAN*/
194 /***************************
195 * Build DNS Query Message *
197 * hard-coded AFSDB query *
198 ***************************/
200 pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
201 pDNShdr->id = htons( 0xDEAD );
202 pDNShdr->flags = htons( DNS_FLAG_RD ); /* do recurse */
203 pDNShdr->q_count = htons( 1 ); /* one query */
204 pDNShdr->rr_count = 0; /* none in query */
205 pDNShdr->auth_count = 0; /* none in query */
206 pDNShdr->add_count = 0; /* none in query */
208 queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
209 queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
212 pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
213 pDNS_qtail->qtype = htons(DNS_RRTYPE_AFSDB);
214 pDNS_qtail->qclass = htons(DNS_RRCLASS_IN);
215 queryLen += DNS_QTAIL_LEN;
217 /**************************
218 * Send DNS Query Message *
219 **************************/
221 res = sendto( commSock,
225 (struct sockaddr *) &sockAddr,
226 sizeof( SOCKADDR_IN ) );
228 /*dumpSbuffer(buffer,queryLen);*/
233 fprintf(stderr, "send_DNS_AFSDB_Query: error %d, errno %d\n", res, errno);
234 fprintf(stderr, "sendto() failed \n");
240 /*printf( "sendto() succeeded\n");*/
248 PDNS_HDR get_DNS_Response(SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
250 /*static char buffer[BUFSIZE];*/
252 int addrLen = sizeof(SOCKADDR_IN);
255 #ifndef WIN32_LEAN_AND_MEAN
256 bzero(buffer,BUFSIZE);
257 #endif /*WIN32_LEAN_AND_MEAN*/
259 /*****************************
260 * Receive DNS Reply Message *
261 *****************************/
263 /*printf( "calling recvfrom() on connected UDP socket\n" );*/
265 size = recvfrom( commSock,
269 (struct sockaddr *) &sockAddr,
271 if (size < 0) { fprintf(stderr, "recvfrom error %d\n", errno); return NULL; }
273 /*dumpRbuffer(buffer,res);*/
276 fprintf(stderr, "recvfrom returned %d bytes from %s: \n",
277 size, inet_ntoa( sockAddr.sin_addr ) );
280 return((PDNS_HDR)&( buffer[ 0 ] ));
285 int putQName( char *pHostName, char *pQName )
292 DNSlowerCase(pHostName);
293 /*printf( "Hostname: [%s]\n", pHostName );*/
295 for ( i = 0; *( pHostName + i ); i++ )
297 c = *( pHostName + i ); /* get next character */
302 /* dot encountered, fill in previous length */
303 if (k!=0){ /*don't process repeated dots*/
304 /*printf( "%c", c );*/
306 j = j+k+1; /* set index to next counter */
307 k = 0; /* reset segment length */
312 /*printf( "%c", c );*/
313 *( pQName + j + k + 1 ) = c; /* assign to QName */
314 k++; /* inc count of seg chars */
318 *(pQName + j ) = k; /* count for final segment */
320 *(pQName + j + k + 1 ) = 0; /* count for trailing NULL segment is 0 */
325 return ( j + k + 1 ); /* return total length of QName */
327 return ( j + k + 2 );
328 } /* end putQName() */
331 u_char * skipRRQName(u_char *pQName)
340 /* skip the 'compression' pointer */
344 /* skip a normal qname segment */
351 /* ptr now pointing at terminating zero of query QName,
352 or the pointer for the previous occurrence
358 } /* end skipRRQName() */
362 u_char * printRRQName( u_char *pQName, PDNS_HDR buffer )
365 u_char *buffPtr = (u_char *) buffer;
374 for ( i = 0; i < BUFSIZE; i++ )
385 for ( k = 1; k <= c; k++ )
387 fprintf(stderr, "%c", *( namePtr + k ) );
393 fprintf(stderr,"\n");
394 namePtr++; /* skip terminating zero */
401 } /* end printRRQName() */
404 u_char * sPrintRRQName( u_char *pQName, PDNS_HDR buffer, char *str )
407 u_char *buffPtr = (u_char *) buffer;
418 for ( i = 0; i < BUFSIZE; i++ )
429 for ( k = 1; k <= c; k++ )
431 sprintf(section,"%c", *( namePtr + k ) );
438 namePtr++; /* skip terminating zero */
445 } /* end sPrintRRQName() */
448 void printReplyBuffer_AFSDB(PDNS_HDR replyBuff)
450 u_char *ptr = (u_char *) replyBuff;
451 int answerCount = ntohs((replyBuff)->rr_count);
458 /* ptr now pointing at start of QName in query field */
459 ptr = skipRRQName(ptr);
462 /* skip the query type and class fields */
465 /* ptr should now be at the start of the answer RR sections */
467 fprintf(stderr,"---------------------------------\n");
468 for (i=0; i<answerCount ; i++){
469 ptr = skipRRQName(ptr);
470 rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
471 ptr+= DNS_AFSDB_RR_HDR_LEN;
472 if ( ntohs(rrPtr->rr_afsdb_class) == 1) {
473 fprintf(stderr,"AFDB class %d -> ",ntohs(rrPtr->rr_afsdb_class));
474 ptr = printRRQName(ptr,replyBuff); }
476 ptr = skipRRQName(ptr);
478 fprintf(stderr,"---------------------------------\n");
483 void processReplyBuffer_AFSDB(SOCKET commSock, PDNS_HDR replyBuff, int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
484 unsigned short ports[], unsigned short ipRanks[], int *numServers, int *ttl)
485 /*PAFS_SRV_LIST (srvList)*/
487 u_char *ptr = (u_char *) replyBuff;
488 int answerCount = ntohs((replyBuff)->rr_count);
499 /* ptr now pointing at start of QName in query field */
500 ptr = skipRRQName(ptr);
503 /* skip the query type and class fields */
506 /* ptr should now be at the start of the answer RR sections */
508 answerCount = MIN(answerCount, AFSMAXCELLHOSTS);
510 fprintf(stderr, "processRep_AFSDB: answerCount=%d\n", answerCount);
513 for (i=0; i<answerCount ; i++){
514 ptr = skipRRQName(ptr);
515 rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
516 ptr+= DNS_AFSDB_RR_HDR_LEN;
517 if ((ntohs(rrPtr->rr_afsdb_class) == 1) &&
518 (srvCount < MAX_AFS_SRVS)) {
519 /*ptr = sPrintRRQName(ptr,replyBuff,srvList->host[srvList->count]);*/
520 ptr = sPrintRRQName(ptr,replyBuff,hostName);
521 /*ptr = printRRQName(ptr,replyBuff);*/
522 *ttl = ntohl(rrPtr->rr_ttl);
525 fprintf(stderr, "resolving name %s\n", hostName);
527 /* resolve name from DNS query */
528 rc = DNSgetAddr(commSock, hostName, &addr);
530 continue; /* skip this entry */
532 fprintf(stderr, "processRep_AFSDB: resolved name %s to addr %x\n", hostName, addr);
534 memcpy(&cellHostAddrs[srvCount], &addr.s_addr, sizeof(addr.s_addr));
535 strncpy(cellHostNames[srvCount], hostName, CELL_MAXNAMELEN);
536 cellHostNames[srvCount][CELL_MAXNAMELEN-1] = '\0';
537 ipRanks[srvCount] = 0;
538 ports[srvCount] = htons(7003);
542 ptr = skipRRQName(ptr);
546 *numServers = srvCount;
551 u_char * processReplyBuffer_Addr(PDNS_HDR replyBuff)
553 u_char *ptr = (u_char *) replyBuff;
554 int answerCount = ntohs((replyBuff)->rr_count);
559 fprintf(stderr, "processReplyBuffer_Addr: answerCount=%d\n", answerCount);
561 if (answerCount == 0) return 0;
565 /* ptr now pointing at start of QName in query field */
566 ptr = skipRRQName(ptr);
569 /* skip the query type and class fields */
572 /* ptr should now be at the start of the answer RR sections */
573 ptr = skipRRQName(ptr);
574 rrPtr = (PDNS_A_RR_HDR) ptr;
577 fprintf(stderr, "type:%d, class:%d, ttl:%d, rdlength:%d\n",
578 ntohs(rrPtr->rr_type),ntohs(rrPtr->rr_class),
579 ntohl(rrPtr->rr_ttl),ntohs(rrPtr->rr_rdlength));
580 fprintf(stderr, "Count %d\tand Answer %8x\n",answerCount,rrPtr->rr_addr);
583 ptr += DNS_A_RR_HDR_LEN;
589 int DNSgetAddr(SOCKET commSock, char *hostName, struct in_addr *iNet)
591 /* Variables for DNS message parsing and creation */
594 SOCKADDR_IN sockAddr;
595 char buffer[BUFSIZE];
600 /**********************
601 * Get a DGRAM socket *
602 **********************/
604 sockAddr = setSockAddr(dns_addr, DNS_PORT);
606 rc = send_DNS_Addr_Query(hostName,commSock,sockAddr, buffer);
607 if (rc < 0) return rc;
608 pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
612 addr = processReplyBuffer_Addr(pDNShdr);
616 aPtr = (u_long *) addr;
618 iNet->s_addr = *aPtr;
622 #endif /* DNSAPI_ENV */
624 int getAFSServer(const char *service, const char *protocol, const char *cellName,
625 unsigned short afsdbPort, /* network byte order */
626 int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
627 unsigned short ports[], /* network byte order */
628 unsigned short ipRanks[],
629 int *numServers, int *ttl)
633 SOCKADDR_IN sockAddr;
635 char buffer[BUFSIZE];
640 fprintf(stderr, "getAFSServer: cell %s, cm_dnsEnabled=%d\n", cellName, cm_dnsEnabled);
646 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
647 if (cm_dnsEnabled == -1) { /* not yet initialized, eg when called by klog */
648 cm_InitDNS(1); /* assume enabled */
651 if (cm_dnsEnabled == 0) { /* possibly we failed in cm_InitDNS above */
652 fprintf(stderr, "DNS initialization failed, disabled\n");
656 if (service == NULL || protocol == NULL || cellName == NULL) {
657 fprintf(stderr, "invalid input\n");
661 sockAddr = setSockAddr(dns_addr, DNS_PORT);
663 commSock = socket( AF_INET, SOCK_DGRAM, 0 );
666 /*afsi_log("socket() failed\n");*/
667 fprintf(stderr, "getAFSServer: socket() failed, errno=%d\n", errno);
671 StringCbCopyA(query, sizeof(query), cellName);
672 if (query[strlen(query)-1] != '.') {
673 StringCbCatA(query, sizeof(query), ".");
676 rc = send_DNS_AFSDB_Query(cellName,commSock,sockAddr, buffer);
678 closesocket(commSock);
679 fprintf(stderr,"getAFSServer: send_DNS_AFSDB_Query failed\n");
683 pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
685 /*printReplyBuffer_AFSDB(pDNShdr);*/
687 processReplyBuffer_AFSDB(commSock, pDNShdr, cellHostAddrs, cellHostNames, ports, ipRanks, numServers, ttl);
689 closesocket(commSock);
690 if (*numServers == 0)
694 #else /* DNSAPI_ENV */
695 PDNS_RECORD pDnsCell, pDnsIter, pDnsVol, pDnsVolIter, pDnsCIter;
702 if (service == NULL || protocol == NULL || cellName == NULL)
705 #ifdef AFS_FREELANCE_CLIENT
706 if ( cm_stricmp_utf8N(cellName, "Freelance.Local.Root") == 0 )
708 #endif /* AFS_FREELANCE_CLIENT */
710 /* query the SRV _afs3-vlserver._udp records of cell */
711 StringCbPrintf(query, sizeof(query), "_%s._%s.%s", service, protocol, cellName);
712 if (query[strlen(query)-1] != '.') {
713 StringCbCatA(query, sizeof(query), ".");
716 if (DnsQuery_A(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
717 /* go through the returned records */
718 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
719 /* if we find an SRV record, we found the service */
720 if (pDnsIter->wType == DNS_TYPE_SRV) {
721 StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
722 pDnsIter->Data.SRV.pNameTarget);
723 ipRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
724 ports[*numServers] = htons(pDnsIter->Data.SRV.wPort);
728 *ttl = pDnsIter->dwTtl;
729 if (*numServers == AFSMAXCELLHOSTS)
734 for (i=0;i<*numServers;i++)
735 cellHostAddrs[i] = 0;
737 /* now check if there are any A records in the results */
738 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
739 if(pDnsIter->wType == DNS_TYPE_A)
740 /* check if its for one of the service */
741 for (i=0;i<*numServers;i++)
742 if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
743 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
746 for (i=0;i<*numServers;i++) {
747 /* if we don't have an IP yet, then we should try resolving the afs3-vlserver hostname
748 in a separate query. */
749 if (!cellHostAddrs[i]) {
750 if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
751 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
752 /* if we get an A record, keep it */
753 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
754 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
757 /* if we get a CNAME, look for a corresponding A record */
758 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
759 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
760 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
761 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
765 if (cellHostAddrs[i])
767 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
770 /* we are done with the service lookup */
771 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
775 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
778 /* query the AFSDB records of cell */
779 StringCbCopyA(query, sizeof(query), cellName);
780 if (query[strlen(query)-1] != '.') {
781 StringCbCatA(query, sizeof(query), ".");
784 if (DnsQuery_A(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
785 /* go through the returned records */
786 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
787 /* if we find an AFSDB record with Preference set to 1, we found a service instance */
788 if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
789 StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
790 pDnsIter->Data.Afsdb.pNameExchange);
791 ipRanks[*numServers] = 0;
792 ports[*numServers] = afsdbPort;
796 *ttl = pDnsIter->dwTtl;
797 if (*numServers == AFSMAXCELLHOSTS)
802 for (i=0;i<*numServers;i++)
803 cellHostAddrs[i] = 0;
805 /* now check if there are any A records in the results */
806 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
807 if(pDnsIter->wType == DNS_TYPE_A)
808 /* check if its for one of the service */
809 for (i=0;i<*numServers;i++)
810 if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
811 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
814 for (i=0;i<*numServers;i++) {
815 /* if we don't have an IP yet, then we should try resolving the service hostname
816 in a separate query. */
817 if (!cellHostAddrs[i]) {
818 if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
819 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
820 /* if we get an A record, keep it */
821 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
822 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
825 /* if we get a CNAME, look for a corresponding A record */
826 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
827 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
828 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
829 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
833 if (cellHostAddrs[i])
835 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
838 /* we are done with the service lookup */
839 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
843 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
847 if ( *numServers > 0 )
851 #endif /* DNSAPI_ENV */
854 int getAFSServerW(const cm_unichar_t *service, const cm_unichar_t *protocol, const cm_unichar_t *cellName,
855 unsigned short afsdbPort, /* network byte order */
857 cm_unichar_t cellHostNames[][MAXHOSTCHARS],
858 unsigned short ports[], /* network byte order */
859 unsigned short ipRanks[],
860 int *numServers, int *ttl)
863 PDNS_RECORDW pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
865 cm_unichar_t query[1024];
870 if (service == NULL || protocol == NULL || cellName == NULL)
873 #ifdef AFS_FREELANCE_CLIENT
874 if ( cm_stricmp_utf16(cellName, L"Freelance.Local.Root") == 0 )
876 #endif /* AFS_FREELANCE_CLIENT */
878 /* query the SRV _afs3-vlserver._udp records of cell */
879 StringCbPrintfW(query, sizeof(query), L"_%S._%S.%S", service, protocol, cellName);
880 if (query[wcslen(query)-1] != L'.') {
881 StringCbCatW(query, sizeof(query), L".");
884 if (DnsQuery_W(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
885 NULL) == ERROR_SUCCESS) {
886 /* go through the returned records */
887 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
888 /* if we find an SRV record, we found a service instance */
889 if (pDnsIter->wType == DNS_TYPE_SRV) {
890 StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
891 pDnsIter->Data.SRV.pNameTarget);
892 ipRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
893 ports[*numServers] = htons(pDnsIter->Data.SRV.wPort);
897 *ttl = pDnsIter->dwTtl;
898 if (*numServers == AFSMAXCELLHOSTS)
903 for (i=0;i<*numServers;i++)
904 cellHostAddrs[i] = 0;
906 /* now check if there are any A records in the results */
907 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
908 if(pDnsIter->wType == DNS_TYPE_A)
909 /* check if its for one of the service instances */
910 for (i=0;i<*numServers;i++)
911 if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
912 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
915 for (i=0;i<*numServers;i++) {
916 /* if we don't have an IP yet, then we should try resolving the service hostname
917 in a separate query. */
918 if (!cellHostAddrs[i]) {
919 if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
920 (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
921 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
922 /* if we get an A record, keep it */
923 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
924 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
927 /* if we get a CNAME, look for a corresponding A record */
928 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
929 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
930 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
931 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
935 if (cellHostAddrs[i])
937 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
940 /* we are done with the service lookup */
941 DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
945 DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
948 /* query the AFSDB records of cell */
949 StringCbCopyW(query, sizeof(query), cellName);
950 if (query[wcslen(query)-1] != L'.') {
951 StringCbCatW(query, sizeof(query), L".");
954 if (DnsQuery_W(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
955 NULL) == ERROR_SUCCESS) {
956 /* go through the returned records */
957 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
958 /* if we find an AFSDB record with Preference set to 1, we found a service instance */
959 if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
960 StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
961 pDnsIter->Data.Afsdb.pNameExchange);
962 ipRanks[*numServers] = 0;
963 ports[*numServers] = afsdbPort;
967 *ttl = pDnsIter->dwTtl;
968 if (*numServers == AFSMAXCELLHOSTS)
973 for (i=0;i<*numServers;i++)
974 cellHostAddrs[i] = 0;
976 /* now check if there are any A records in the results */
977 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
978 if(pDnsIter->wType == DNS_TYPE_A)
979 /* check if its for one of the service instances */
980 for (i=0;i<*numServers;i++)
981 if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
982 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
985 for (i=0;i<*numServers;i++) {
986 /* if we don't have an IP yet, then we should try resolving the service hostname
987 in a separate query. */
988 if (!cellHostAddrs[i]) {
989 if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
990 (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
991 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
992 /* if we get an A record, keep it */
993 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
994 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
997 /* if we get a CNAME, look for a corresponding A record */
998 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
999 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
1000 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
1001 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
1005 if (cellHostAddrs[i])
1007 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
1010 /* we are done with the service lookup */
1011 DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
1015 DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
1019 if ( *numServers > 0 )
1022 #endif /* DNSAPI_ENV */