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>
17 #include "cm_dns_private.h"
20 #include <afs/afsint.h>
22 /*extern void afsi_log(char *pattern, ...);*/
25 static char dns_addr[30];
27 extern char cm_confDir[];
29 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x500
30 int cm_dnsEnabled = -1;
32 int cm_dnsEnabled = 1; /* assume on */
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)
52 if (!enabled) { fprintf(stderr, "DNS support disabled\n"); cm_dnsEnabled = 0; return 0; }
54 /* First try AFS_NS environment var. */
55 addr = getenv("AFS_NS");
56 if (addr && inet_addr(addr) != -1) {
57 strcpy(dns_addr, addr);
59 /* Now check for the AFSDNS.INI file */
61 strcpy(configpath, cm_confDir);
62 #elif defined(AFS_WIN95_ENV)
63 char *path = getenv("AFSCONF");
64 if (path) strcpy(configpath, path);
65 else strcpy(configpath, "c:\\afscli");
67 code = GetWindowsDirectory(configpath, sizeof(configpath));
68 if (code == 0 || code > sizeof(configpath)) return -1;
70 strcat(configpath, "\\afsdns.ini");
72 /* Currently we only get (and query) the first nameserver. Getting
73 list of mult. nameservers should be easy to do. */
74 len = GetPrivateProfileString("AFS Domain Name Servers", "ns1", NULL,
75 dns_addr, sizeof(dns_addr),
78 if (len == 0 || inet_addr(dns_addr) == -1) {
79 fprintf(stderr, "No valid name server addresses found, DNS lookup is "
81 cm_dnsEnabled = 0; /* failed */
82 return -1; /* No name servers defined */
84 else fprintf(stderr, "Found DNS server %s\n", dns_addr);
91 SOCKADDR_IN setSockAddr(char *server, int port)
94 int addrLen = sizeof(SOCKADDR_IN);
96 #ifndef WIN32_LEAN_AND_MEAN
97 bzero(&sockAddr,addrLen);
98 #endif /*WIN32_LEAN_AND_MEAN*/
99 sockAddr.sin_family = AF_INET;
100 sockAddr.sin_port = htons( port );
101 sockAddr.sin_addr.s_addr = inet_addr( server );
102 /*inet_aton(server, &sockAddr.sin_addr.s_addr);*/
107 int getRRCount(PDNS_HDR ptr)
109 return(ntohs(ptr->rr_count));
113 int send_DNS_Addr_Query(char* query,
114 SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
117 PDNS_QTAIL pDNS_qtail;
122 #ifndef WIN32_LEAN_AND_MEAN
123 bzero(buffer,BUFSIZE);
124 #endif /*WIN32_LEAN_AND_MEAN*/
126 /*********************************
127 * Build DNS Query Message *
129 * hard-coded Adrress (A) query *
130 *********************************/
132 pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
133 pDNShdr->id = htons( 0xDADE );
134 pDNShdr->flags = htons( DNS_FLAG_RD ); /* do recurse */
135 pDNShdr->q_count = htons( 1 ); /* one query */
136 pDNShdr->rr_count = 0; /* none in query */
137 pDNShdr->auth_count = 0; /* none in query */
138 pDNShdr->add_count = 0; /* none in query */
140 queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
141 queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
143 fprintf(stderr, "send_DNS_Addr: query=%s, queryLen=%d\n", query, queryLen);
147 pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
148 pDNS_qtail->qtype = htons(255);/*htons(DNS_RRTYPE_A); */
149 pDNS_qtail->qclass = htons(DNS_RRCLASS_IN);
150 queryLen += DNS_QTAIL_LEN;
152 /**************************
153 * Send DNS Query Message *
154 **************************/
157 res = sendto( commSock,
161 (struct sockaddr *) &sockAddr,
162 sizeof( SOCKADDR_IN ) );
164 /*dumpSbuffer(buffer,queryLen);*/
169 fprintf(stderr, "send_DNS_Addr_Query: error %d, errno %d\n", res, errno);
170 fprintf(stderr, "sendto() failed \n");
176 /*printf( "sendto() succeeded\n");*/
184 int send_DNS_AFSDB_Query(char* query,
185 SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
187 /*static char buffer[BUFSIZE];*/
190 PDNS_QTAIL pDNS_qtail;
195 #ifndef WIN32_LEAN_AND_MEAN
196 bzero(buffer,BUFSIZE);
197 #endif /*WIN32_LEAN_AND_MEAN*/
199 /***************************
200 * Build DNS Query Message *
202 * hard-coded AFSDB query *
203 ***************************/
205 pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
206 pDNShdr->id = htons( 0xDEAD );
207 pDNShdr->flags = htons( DNS_FLAG_RD ); /* do recurse */
208 pDNShdr->q_count = htons( 1 ); /* one query */
209 pDNShdr->rr_count = 0; /* none in query */
210 pDNShdr->auth_count = 0; /* none in query */
211 pDNShdr->add_count = 0; /* none in query */
213 queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
214 queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
217 pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
218 pDNS_qtail->qtype = htons(DNS_RRTYPE_AFSDB);
219 pDNS_qtail->qclass = htons(DNS_RRCLASS_IN);
220 queryLen += DNS_QTAIL_LEN;
222 /**************************
223 * Send DNS Query Message *
224 **************************/
226 res = sendto( commSock,
230 (struct sockaddr *) &sockAddr,
231 sizeof( SOCKADDR_IN ) );
233 /*dumpSbuffer(buffer,queryLen);*/
238 fprintf(stderr, "send_DNS_AFSDB_Query: error %d, errno %d\n", res, errno);
239 fprintf(stderr, "sendto() failed \n");
245 /*printf( "sendto() succeeded\n");*/
253 PDNS_HDR get_DNS_Response(SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
255 /*static char buffer[BUFSIZE];*/
257 int addrLen = sizeof(SOCKADDR_IN);
260 #ifndef WIN32_LEAN_AND_MEAN
261 bzero(buffer,BUFSIZE);
262 #endif /*WIN32_LEAN_AND_MEAN*/
264 /*****************************
265 * Receive DNS Reply Message *
266 *****************************/
268 /*printf( "calling recvfrom() on connected UDP socket\n" );*/
270 size = recvfrom( commSock,
274 (struct sockaddr *) &sockAddr,
276 if (size < 0) { fprintf(stderr, "recvfrom error %d\n", errno); return NULL; }
278 /*dumpRbuffer(buffer,res);*/
281 fprintf(stderr, "recvfrom returned %d bytes from %s: \n",
282 size, inet_ntoa( sockAddr.sin_addr ) );
285 return((PDNS_HDR)&( buffer[ 0 ] ));
290 int putQName( char *pHostName, char *pQName )
297 DNSlowerCase(pHostName);
298 /*printf( "Hostname: [%s]\n", pHostName );*/
300 for ( i = 0; *( pHostName + i ); i++ )
302 c = *( pHostName + i ); /* get next character */
307 /* dot encountered, fill in previous length */
308 if (k!=0){ /*don't process repeated dots*/
309 /*printf( "%c", c );*/
311 j = j+k+1; /* set index to next counter */
312 k = 0; /* reset segment length */
317 /*printf( "%c", c );*/
318 *( pQName + j + k + 1 ) = c; /* assign to QName */
319 k++; /* inc count of seg chars */
323 *(pQName + j ) = k; /* count for final segment */
325 *(pQName + j + k + 1 ) = 0; /* count for trailing NULL segment is 0 */
330 return ( j + k + 1 ); /* return total length of QName */
332 return ( j + k + 2 );
333 } /* end putQName() */
336 u_char * skipRRQName(u_char *pQName)
345 /* skip the 'compression' pointer */
349 /* skip a normal qname segment */
356 /* ptr now pointing at terminating zero of query QName,
357 or the pointer for the previous occurrence
363 } /* end skipRRQName() */
367 u_char * printRRQName( u_char *pQName, PDNS_HDR buffer )
370 u_char *buffPtr = (u_char *) buffer;
379 for ( i = 0; i < BUFSIZE; i++ )
390 for ( k = 1; k <= c; k++ )
392 fprintf(stderr, "%c", *( namePtr + k ) );
398 fprintf(stderr,"\n");
399 namePtr++; /* skip terminating zero */
406 } /* end printRRQName() */
409 u_char * sPrintRRQName( u_char *pQName, PDNS_HDR buffer, char *str )
412 u_char *buffPtr = (u_char *) buffer;
423 for ( i = 0; i < BUFSIZE; i++ )
434 for ( k = 1; k <= c; k++ )
436 sprintf(section,"%c", *( namePtr + k ) );
443 namePtr++; /* skip terminating zero */
450 } /* end sPrintRRQName() */
453 void printReplyBuffer_AFSDB(PDNS_HDR replyBuff)
455 u_char *ptr = (u_char *) replyBuff;
456 int answerCount = ntohs((replyBuff)->rr_count);
463 /* ptr now pointing at start of QName in query field */
464 ptr = skipRRQName(ptr);
467 /* skip the query type and class fields */
470 /* ptr should now be at the start of the answer RR sections */
472 fprintf(stderr,"---------------------------------\n");
473 for (i=0; i<answerCount ; i++){
474 ptr = skipRRQName(ptr);
475 rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
476 ptr+= DNS_AFSDB_RR_HDR_LEN;
477 if ( ntohs(rrPtr->rr_afsdb_class) == 1) {
478 fprintf(stderr,"AFDB class %d -> ",ntohs(rrPtr->rr_afsdb_class));
479 ptr = printRRQName(ptr,replyBuff); }
481 ptr = skipRRQName(ptr);
483 fprintf(stderr,"---------------------------------\n");
488 void processReplyBuffer_AFSDB(SOCKET commSock, PDNS_HDR replyBuff, int *cellHosts, 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(&cellHosts[srvCount], &addr.s_addr, sizeof(addr.s_addr));
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 getAFSServer(char *cellName, int *cellHosts, int *numServers, int *ttl)
591 /*static AFS_SRV_LIST srvList;
592 static int ans = 0;*/
594 SOCKADDR_IN sockAddr;
596 char buffer[BUFSIZE];
600 fprintf(stderr, "getAFSServer: cell %s, cm_dnsEnabled=%d\n", cellName, cm_dnsEnabled);
603 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x500
604 if (cm_dnsEnabled == -1) { /* not yet initialized, eg when called by klog */
605 cm_InitDNS(1); /* assume enabled */
608 if (cm_dnsEnabled == 0) { /* possibly we failed in cm_InitDNS above */
609 fprintf(stderr, "DNS initialization failed, disabled\n");
614 sockAddr = setSockAddr(dns_addr, DNS_PORT);
616 commSock = socket( AF_INET, SOCK_DGRAM, 0 );
619 /*afsi_log("socket() failed\n");*/
620 fprintf(stderr, "getAFSServer: socket() failed, errno=%d\n", errno);
626 /* the win95 sock.vxd will not allow sendto for unbound sockets,
627 * so just bind to nothing and it works */
629 __djgpp_set_socket_blocking_mode(commSock, 0);
630 bind(commSock,0,sizeof( SOCKADDR_IN ) );
633 rc = send_DNS_AFSDB_Query(cellName,commSock,sockAddr, buffer);
635 fprintf(stderr,"getAFSServer: send_DNS_AFSDB_Query failed\n");
640 pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
642 /*printReplyBuffer_AFSDB(pDNShdr);*/
644 processReplyBuffer_AFSDB(commSock, pDNShdr, cellHosts, numServers, ttl);
648 closesocket(commSock);
649 if (*numServers == 0)
656 int DNSgetAddr(SOCKET commSock, char *hostName, struct in_addr *iNet)
658 /* Variables for DNS message parsing and creation */
661 SOCKADDR_IN sockAddr;
662 char buffer[BUFSIZE];
667 /**********************
668 * Get a DGRAM socket *
669 **********************/
671 sockAddr = setSockAddr(dns_addr, DNS_PORT);
673 rc = send_DNS_Addr_Query(hostName,commSock,sockAddr, buffer);
674 if (rc < 0) return rc;
675 pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
679 addr = processReplyBuffer_Addr(pDNShdr);
683 aPtr = (u_long *) addr;
685 iNet->s_addr = *aPtr;
690 #endif /* AFS_AFSDB_ENV */