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/param.h>
13 #include <afs/cellconfig.h>
16 #include "cm_dns_private.h"
20 #include <afs/afsint.h>
21 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500)
28 /*extern void afsi_log(char *pattern, ...);*/
30 static char dns_addr[30];
31 static int cm_dnsEnabled = -1;
33 void DNSlowerCase(char *str)
37 for (i=0; i<strlen(str); i++)
38 /*str[i] = tolower(str[i]);*/
39 if (str[i] >= 'A' && str[i] <= 'Z')
43 int cm_InitDNS(int enabled)
52 fprintf(stderr, "DNS support disabled\n");
57 /* First try AFS_NS environment var. */
58 addr = getenv("AFS_NS");
59 if (addr && inet_addr(addr) != -1) {
60 strcpy(dns_addr, addr);
62 /* Now check for the AFSDNS.INI file */
63 code = GetWindowsDirectory(configpath, sizeof(configpath));
64 if (code == 0 || code > sizeof(configpath)) return -1;
65 strcat(configpath, "\\afsdns.ini");
67 /* Currently we only get (and query) the first nameserver. Getting
68 list of mult. nameservers should be easy to do. */
69 len = GetPrivateProfileString("AFS Domain Name Servers", "ns1", NULL,
70 dns_addr, sizeof(dns_addr),
73 if (len == 0 || inet_addr(dns_addr) == -1) {
74 fprintf(stderr, "No valid name server addresses found, DNS lookup is "
76 cm_dnsEnabled = 0; /* failed */
77 return -1; /* No name servers defined */
80 fprintf(stderr, "Found DNS server %s\n", dns_addr);
82 #endif /* DNSAPI_ENV */
88 SOCKADDR_IN setSockAddr(char *server, int port)
91 int addrLen = sizeof(SOCKADDR_IN);
93 #ifndef WIN32_LEAN_AND_MEAN
94 bzero(&sockAddr,addrLen);
95 #endif /*WIN32_LEAN_AND_MEAN*/
96 sockAddr.sin_family = AF_INET;
97 sockAddr.sin_port = htons( port );
98 sockAddr.sin_addr.s_addr = inet_addr( server );
99 /*inet_aton(server, &sockAddr.sin_addr.s_addr);*/
104 int getRRCount(PDNS_HDR ptr)
106 return(ntohs(ptr->rr_count));
110 int send_DNS_Addr_Query(char* query,
111 SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
114 PDNS_QTAIL pDNS_qtail;
119 #ifndef WIN32_LEAN_AND_MEAN
120 bzero(buffer,BUFSIZE);
121 #endif /*WIN32_LEAN_AND_MEAN*/
123 /*********************************
124 * Build DNS Query Message *
126 * hard-coded Adrress (A) query *
127 *********************************/
129 pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
130 pDNShdr->id = htons( 0xDADE );
131 pDNShdr->flags = htons( DNS_FLAG_RD ); /* do recurse */
132 pDNShdr->q_count = htons( 1 ); /* one query */
133 pDNShdr->rr_count = 0; /* none in query */
134 pDNShdr->auth_count = 0; /* none in query */
135 pDNShdr->add_count = 0; /* none in query */
137 queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
138 queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
140 fprintf(stderr, "send_DNS_Addr: query=%s, queryLen=%d\n", query, queryLen);
144 pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
145 pDNS_qtail->qtype = htons(255);/*htons(DNS_RRTYPE_A); */
146 pDNS_qtail->qclass = htons(DNS_RRCLASS_IN);
147 queryLen += DNS_QTAIL_LEN;
149 /**************************
150 * Send DNS Query Message *
151 **************************/
154 res = sendto( commSock,
158 (struct sockaddr *) &sockAddr,
159 sizeof( SOCKADDR_IN ) );
161 /*dumpSbuffer(buffer,queryLen);*/
166 fprintf(stderr, "send_DNS_Addr_Query: error %d, errno %d\n", res, errno);
167 fprintf(stderr, "sendto() failed \n");
173 /*printf( "sendto() succeeded\n");*/
181 int send_DNS_AFSDB_Query(char* query,
182 SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
184 /*static char buffer[BUFSIZE];*/
187 PDNS_QTAIL pDNS_qtail;
192 #ifndef WIN32_LEAN_AND_MEAN
193 bzero(buffer,BUFSIZE);
194 #endif /*WIN32_LEAN_AND_MEAN*/
196 /***************************
197 * Build DNS Query Message *
199 * hard-coded AFSDB query *
200 ***************************/
202 pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
203 pDNShdr->id = htons( 0xDEAD );
204 pDNShdr->flags = htons( DNS_FLAG_RD ); /* do recurse */
205 pDNShdr->q_count = htons( 1 ); /* one query */
206 pDNShdr->rr_count = 0; /* none in query */
207 pDNShdr->auth_count = 0; /* none in query */
208 pDNShdr->add_count = 0; /* none in query */
210 queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
211 queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
214 pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
215 pDNS_qtail->qtype = htons(DNS_RRTYPE_AFSDB);
216 pDNS_qtail->qclass = htons(DNS_RRCLASS_IN);
217 queryLen += DNS_QTAIL_LEN;
219 /**************************
220 * Send DNS Query Message *
221 **************************/
223 res = sendto( commSock,
227 (struct sockaddr *) &sockAddr,
228 sizeof( SOCKADDR_IN ) );
230 /*dumpSbuffer(buffer,queryLen);*/
235 fprintf(stderr, "send_DNS_AFSDB_Query: error %d, errno %d\n", res, errno);
236 fprintf(stderr, "sendto() failed \n");
242 /*printf( "sendto() succeeded\n");*/
250 PDNS_HDR get_DNS_Response(SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
252 /*static char buffer[BUFSIZE];*/
254 int addrLen = sizeof(SOCKADDR_IN);
257 #ifndef WIN32_LEAN_AND_MEAN
258 bzero(buffer,BUFSIZE);
259 #endif /*WIN32_LEAN_AND_MEAN*/
261 /*****************************
262 * Receive DNS Reply Message *
263 *****************************/
265 /*printf( "calling recvfrom() on connected UDP socket\n" );*/
267 size = recvfrom( commSock,
271 (struct sockaddr *) &sockAddr,
273 if (size < 0) { fprintf(stderr, "recvfrom error %d\n", errno); return NULL; }
275 /*dumpRbuffer(buffer,res);*/
278 fprintf(stderr, "recvfrom returned %d bytes from %s: \n",
279 size, inet_ntoa( sockAddr.sin_addr ) );
282 return((PDNS_HDR)&( buffer[ 0 ] ));
287 int putQName( char *pHostName, char *pQName )
294 DNSlowerCase(pHostName);
295 /*printf( "Hostname: [%s]\n", pHostName );*/
297 for ( i = 0; *( pHostName + i ); i++ )
299 c = *( pHostName + i ); /* get next character */
304 /* dot encountered, fill in previous length */
305 if (k!=0){ /*don't process repeated dots*/
306 /*printf( "%c", c );*/
308 j = j+k+1; /* set index to next counter */
309 k = 0; /* reset segment length */
314 /*printf( "%c", c );*/
315 *( pQName + j + k + 1 ) = c; /* assign to QName */
316 k++; /* inc count of seg chars */
320 *(pQName + j ) = k; /* count for final segment */
322 *(pQName + j + k + 1 ) = 0; /* count for trailing NULL segment is 0 */
327 return ( j + k + 1 ); /* return total length of QName */
329 return ( j + k + 2 );
330 } /* end putQName() */
333 u_char * skipRRQName(u_char *pQName)
342 /* skip the 'compression' pointer */
346 /* skip a normal qname segment */
353 /* ptr now pointing at terminating zero of query QName,
354 or the pointer for the previous occurrence
360 } /* end skipRRQName() */
364 u_char * printRRQName( u_char *pQName, PDNS_HDR buffer )
367 u_char *buffPtr = (u_char *) buffer;
376 for ( i = 0; i < BUFSIZE; i++ )
387 for ( k = 1; k <= c; k++ )
389 fprintf(stderr, "%c", *( namePtr + k ) );
395 fprintf(stderr,"\n");
396 namePtr++; /* skip terminating zero */
403 } /* end printRRQName() */
406 u_char * sPrintRRQName( u_char *pQName, PDNS_HDR buffer, char *str )
409 u_char *buffPtr = (u_char *) buffer;
420 for ( i = 0; i < BUFSIZE; i++ )
431 for ( k = 1; k <= c; k++ )
433 sprintf(section,"%c", *( namePtr + k ) );
440 namePtr++; /* skip terminating zero */
447 } /* end sPrintRRQName() */
450 void printReplyBuffer_AFSDB(PDNS_HDR replyBuff)
452 u_char *ptr = (u_char *) replyBuff;
453 int answerCount = ntohs((replyBuff)->rr_count);
460 /* ptr now pointing at start of QName in query field */
461 ptr = skipRRQName(ptr);
464 /* skip the query type and class fields */
467 /* ptr should now be at the start of the answer RR sections */
469 fprintf(stderr,"---------------------------------\n");
470 for (i=0; i<answerCount ; i++){
471 ptr = skipRRQName(ptr);
472 rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
473 ptr+= DNS_AFSDB_RR_HDR_LEN;
474 if ( ntohs(rrPtr->rr_afsdb_class) == 1) {
475 fprintf(stderr,"AFDB class %d -> ",ntohs(rrPtr->rr_afsdb_class));
476 ptr = printRRQName(ptr,replyBuff); }
478 ptr = skipRRQName(ptr);
480 fprintf(stderr,"---------------------------------\n");
485 void processReplyBuffer_AFSDB(SOCKET commSock, PDNS_HDR replyBuff, int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
486 unsigned short ports[], unsigned short ipRanks[], int *numServers, int *ttl)
487 /*PAFS_SRV_LIST (srvList)*/
489 u_char *ptr = (u_char *) replyBuff;
490 int answerCount = ntohs((replyBuff)->rr_count);
501 /* ptr now pointing at start of QName in query field */
502 ptr = skipRRQName(ptr);
505 /* skip the query type and class fields */
508 /* ptr should now be at the start of the answer RR sections */
510 answerCount = MIN(answerCount, AFSMAXCELLHOSTS);
512 fprintf(stderr, "processRep_AFSDB: answerCount=%d\n", answerCount);
515 for (i=0; i<answerCount ; i++){
516 ptr = skipRRQName(ptr);
517 rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
518 ptr+= DNS_AFSDB_RR_HDR_LEN;
519 if ((ntohs(rrPtr->rr_afsdb_class) == 1) &&
520 (srvCount < MAX_AFS_SRVS)) {
521 /*ptr = sPrintRRQName(ptr,replyBuff,srvList->host[srvList->count]);*/
522 ptr = sPrintRRQName(ptr,replyBuff,hostName);
523 /*ptr = printRRQName(ptr,replyBuff);*/
524 *ttl = ntohl(rrPtr->rr_ttl);
527 fprintf(stderr, "resolving name %s\n", hostName);
529 /* resolve name from DNS query */
530 rc = DNSgetAddr(commSock, hostName, &addr);
532 continue; /* skip this entry */
534 fprintf(stderr, "processRep_AFSDB: resolved name %s to addr %x\n", hostName, addr);
536 memcpy(&cellHostAddrs[srvCount], &addr.s_addr, sizeof(addr.s_addr));
537 strncpy(cellHostNames[srvCount], hostName, CELL_MAXNAMELEN);
538 cellHostNames[srvCount][CELL_MAXNAMELEN-1] = '\0';
539 ipRanks[srvCount] = 0;
540 ports[srvCount] = htons(7003);
544 ptr = skipRRQName(ptr);
548 *numServers = srvCount;
553 u_char * processReplyBuffer_Addr(PDNS_HDR replyBuff)
555 u_char *ptr = (u_char *) replyBuff;
556 int answerCount = ntohs((replyBuff)->rr_count);
561 fprintf(stderr, "processReplyBuffer_Addr: answerCount=%d\n", answerCount);
563 if (answerCount == 0) return 0;
567 /* ptr now pointing at start of QName in query field */
568 ptr = skipRRQName(ptr);
571 /* skip the query type and class fields */
574 /* ptr should now be at the start of the answer RR sections */
575 ptr = skipRRQName(ptr);
576 rrPtr = (PDNS_A_RR_HDR) ptr;
579 fprintf(stderr, "type:%d, class:%d, ttl:%d, rdlength:%d\n",
580 ntohs(rrPtr->rr_type),ntohs(rrPtr->rr_class),
581 ntohl(rrPtr->rr_ttl),ntohs(rrPtr->rr_rdlength));
582 fprintf(stderr, "Count %d\tand Answer %8x\n",answerCount,rrPtr->rr_addr);
585 ptr += DNS_A_RR_HDR_LEN;
591 int DNSgetAddr(SOCKET commSock, char *hostName, struct in_addr *iNet)
593 /* Variables for DNS message parsing and creation */
596 SOCKADDR_IN sockAddr;
597 char buffer[BUFSIZE];
602 /**********************
603 * Get a DGRAM socket *
604 **********************/
606 sockAddr = setSockAddr(dns_addr, DNS_PORT);
608 rc = send_DNS_Addr_Query(hostName,commSock,sockAddr, buffer);
609 if (rc < 0) return rc;
610 pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
614 addr = processReplyBuffer_Addr(pDNShdr);
618 aPtr = (u_long *) addr;
620 iNet->s_addr = *aPtr;
624 #endif /* DNSAPI_ENV */
626 int getAFSServer(const char *service, const char *protocol, const char *cellName,
627 unsigned short afsdbPort,
628 int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
629 unsigned short ports[], unsigned short ipRanks[],
630 int *numServers, int *ttl)
634 SOCKADDR_IN sockAddr;
636 char buffer[BUFSIZE];
641 fprintf(stderr, "getAFSServer: cell %s, cm_dnsEnabled=%d\n", cellName, cm_dnsEnabled);
647 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
648 if (cm_dnsEnabled == -1) { /* not yet initialized, eg when called by klog */
649 cm_InitDNS(1); /* assume enabled */
652 if (cm_dnsEnabled == 0) { /* possibly we failed in cm_InitDNS above */
653 fprintf(stderr, "DNS initialization failed, disabled\n");
657 if (service == NULL || protocol == NULL || cellName == NULL) {
658 fprintf(stderr, "invalid input\n");
662 sockAddr = setSockAddr(dns_addr, DNS_PORT);
664 commSock = socket( AF_INET, SOCK_DGRAM, 0 );
667 /*afsi_log("socket() failed\n");*/
668 fprintf(stderr, "getAFSServer: socket() failed, errno=%d\n", errno);
672 StringCbCopyA(query, sizeof(query), cellName);
673 if (query[strlen(query)-1] != '.') {
674 StringCbCatA(query, sizeof(query), ".");
677 rc = send_DNS_AFSDB_Query(cellName,commSock,sockAddr, buffer);
679 closesocket(commSock);
680 fprintf(stderr,"getAFSServer: send_DNS_AFSDB_Query failed\n");
684 pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
686 /*printReplyBuffer_AFSDB(pDNShdr);*/
688 processReplyBuffer_AFSDB(commSock, pDNShdr, cellHostAddrs, cellHostNames, ports, ipRanks, numServers, ttl);
690 closesocket(commSock);
691 if (*numServers == 0)
695 #else /* DNSAPI_ENV */
696 PDNS_RECORD pDnsCell, pDnsIter, pDnsVol, pDnsVolIter, pDnsCIter;
703 if (service == NULL || protocol == NULL || cellName == NULL)
706 #ifdef AFS_FREELANCE_CLIENT
707 if ( cm_stricmp_utf8N(cellName, "Freelance.Local.Root") == 0 )
709 #endif /* AFS_FREELANCE_CLIENT */
711 /* query the SRV _afs3-vlserver._udp records of cell */
712 StringCbPrintf(query, sizeof(query), "_%s._%s.%s", service, protocol, cellName);
713 if (query[strlen(query)-1] != '.') {
714 StringCbCatA(query, sizeof(query), ".");
717 if (DnsQuery_A(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
718 /* go through the returned records */
719 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
720 /* if we find an SRV record, we found the service */
721 if (pDnsIter->wType == DNS_TYPE_SRV) {
722 StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
723 pDnsIter->Data.SRV.pNameTarget);
724 ipRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
725 ports[*numServers] = pDnsIter->Data.SRV.wPort;
729 *ttl = pDnsIter->dwTtl;
730 if (*numServers == AFSMAXCELLHOSTS)
735 for (i=0;i<*numServers;i++)
736 cellHostAddrs[i] = 0;
738 /* now check if there are any A records in the results */
739 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
740 if(pDnsIter->wType == DNS_TYPE_A)
741 /* check if its for one of the service */
742 for (i=0;i<*numServers;i++)
743 if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
744 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
747 for (i=0;i<*numServers;i++) {
748 /* if we don't have an IP yet, then we should try resolving the afs3-vlserver hostname
749 in a separate query. */
750 if (!cellHostAddrs[i]) {
751 if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
752 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
753 /* if we get an A record, keep it */
754 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
755 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
758 /* if we get a CNAME, look for a corresponding A record */
759 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
760 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
761 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
762 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
766 if (cellHostAddrs[i])
768 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
771 /* we are done with the service lookup */
772 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
776 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
779 /* query the AFSDB records of cell */
780 StringCbCopyA(query, sizeof(query), cellName);
781 if (query[strlen(query)-1] != '.') {
782 StringCbCatA(query, sizeof(query), ".");
785 if (DnsQuery_A(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
786 /* go through the returned records */
787 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
788 /* if we find an AFSDB record with Preference set to 1, we found a service instance */
789 if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
790 StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
791 pDnsIter->Data.Afsdb.pNameExchange);
792 ipRanks[*numServers] = 0;
793 ports[*numServers] = htons(afsdbPort);
797 *ttl = pDnsIter->dwTtl;
798 if (*numServers == AFSMAXCELLHOSTS)
803 for (i=0;i<*numServers;i++)
804 cellHostAddrs[i] = 0;
806 /* now check if there are any A records in the results */
807 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
808 if(pDnsIter->wType == DNS_TYPE_A)
809 /* check if its for one of the service */
810 for (i=0;i<*numServers;i++)
811 if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
812 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
815 for (i=0;i<*numServers;i++) {
816 /* if we don't have an IP yet, then we should try resolving the service hostname
817 in a separate query. */
818 if (!cellHostAddrs[i]) {
819 if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
820 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
821 /* if we get an A record, keep it */
822 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
823 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
826 /* if we get a CNAME, look for a corresponding A record */
827 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
828 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
829 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
830 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
834 if (cellHostAddrs[i])
836 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
839 /* we are done with the service lookup */
840 DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
844 DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
848 if ( *numServers > 0 )
852 #endif /* DNSAPI_ENV */
855 int getAFSServerW(const cm_unichar_t *service, const cm_unichar_t *protocol, const cm_unichar_t *cellName,
856 unsigned short afsdbPort,
858 cm_unichar_t cellHostNames[][MAXHOSTCHARS],
859 unsigned short ports[],
860 unsigned short ipRanks[],
861 int *numServers, int *ttl)
864 PDNS_RECORDW pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
866 cm_unichar_t query[1024];
871 if (service == NULL || protocol == NULL || cellName == NULL)
874 #ifdef AFS_FREELANCE_CLIENT
875 if ( cm_stricmp_utf16(cellName, L"Freelance.Local.Root") == 0 )
877 #endif /* AFS_FREELANCE_CLIENT */
879 /* query the SRV _afs3-vlserver._udp records of cell */
880 StringCbPrintfW(query, sizeof(query), L"_%S._%S.%S", service, protocol, cellName);
881 if (query[wcslen(query)-1] != L'.') {
882 StringCbCatW(query, sizeof(query), L".");
885 if (DnsQuery_W(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
886 NULL) == ERROR_SUCCESS) {
887 /* go through the returned records */
888 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
889 /* if we find an SRV record, we found a service instance */
890 if (pDnsIter->wType == DNS_TYPE_SRV) {
891 StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
892 pDnsIter->Data.SRV.pNameTarget);
893 ipRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
894 ports[*numServers] = pDnsIter->Data.SRV.wPort;
898 *ttl = pDnsIter->dwTtl;
899 if (*numServers == AFSMAXCELLHOSTS)
904 for (i=0;i<*numServers;i++)
905 cellHostAddrs[i] = 0;
907 /* now check if there are any A records in the results */
908 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
909 if(pDnsIter->wType == DNS_TYPE_A)
910 /* check if its for one of the service instances */
911 for (i=0;i<*numServers;i++)
912 if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
913 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
916 for (i=0;i<*numServers;i++) {
917 /* if we don't have an IP yet, then we should try resolving the service hostname
918 in a separate query. */
919 if (!cellHostAddrs[i]) {
920 if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
921 (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
922 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
923 /* if we get an A record, keep it */
924 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
925 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
928 /* if we get a CNAME, look for a corresponding A record */
929 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
930 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
931 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
932 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
936 if (cellHostAddrs[i])
938 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
941 /* we are done with the service lookup */
942 DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
946 DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
949 /* query the AFSDB records of cell */
950 StringCbCopyW(query, sizeof(query), cellName);
951 if (query[wcslen(query)-1] != L'.') {
952 StringCbCatW(query, sizeof(query), L".");
955 if (DnsQuery_W(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
956 NULL) == ERROR_SUCCESS) {
957 /* go through the returned records */
958 for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
959 /* if we find an AFSDB record with Preference set to 1, we found a service instance */
960 if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
961 StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
962 pDnsIter->Data.Afsdb.pNameExchange);
963 ipRanks[*numServers] = 0;
964 ports[*numServers] = htons(afsdbPort);
968 *ttl = pDnsIter->dwTtl;
969 if (*numServers == AFSMAXCELLHOSTS)
974 for (i=0;i<*numServers;i++)
975 cellHostAddrs[i] = 0;
977 /* now check if there are any A records in the results */
978 for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
979 if(pDnsIter->wType == DNS_TYPE_A)
980 /* check if its for one of the service instances */
981 for (i=0;i<*numServers;i++)
982 if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
983 cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
986 for (i=0;i<*numServers;i++) {
987 /* if we don't have an IP yet, then we should try resolving the service hostname
988 in a separate query. */
989 if (!cellHostAddrs[i]) {
990 if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
991 (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
992 for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
993 /* if we get an A record, keep it */
994 if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
995 cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
998 /* if we get a CNAME, look for a corresponding A record */
999 if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
1000 for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
1001 if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
1002 cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
1006 if (cellHostAddrs[i])
1008 /* TODO: if the additional section is missing, then do another lookup for the CNAME */
1011 /* we are done with the service lookup */
1012 DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
1016 DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
1020 if ( *numServers > 0 )
1023 #endif /* DNSAPI_ENV */
1026 #endif /* AFS_AFSDB_ENV */