35 #if defined( USE_TCP ) && defined( USE_DNSSRV )
37 #if defined( _MSC_VER )
38 #pragma message( " Building with DNS SRV enabled." )
53 #if defined( _MSC_VER ) && defined( _PREFAST_ )
54 #define OUT_STRING_OPT __out_bcount_z
56 #define OUT_STRING_OPT( size )
68 ( OUT_STRING_OPT( namelen ) \
71 typedef CHECK_RETVAL struct hostent
FAR * ( SOCKET_API *GETHOSTBYNAME )\
73 STDC_NONNULL_ARG( ( 1 ) );
74 typedef CHECK_RETVAL char FAR * ( SOCKET_API *INET_NTOA )(
struct in_addr in );
75 #if defined( _MSC_VER ) && ( _MSC_VER > 800 )
77 (
IN_STRING const LPSTR lpstrName,
const WORD wType,
78 const DWORD fOptions,
const PIP4_ARRAY aipServers,
79 OUT_PTR PDNS_RECORD *ppQueryResultsSet,
82 typedef VOID ( WINAPI *DNSFREEFN )\
83 (
IN PVOID pData, DNS_FREE_TYPE FreeType ) \
85 typedef VOID ( WINAPI *DNSRECORDLISTFREE )\
86 (
IN PDNS_RECORD pRecordList, DNS_FREE_TYPE FreeType ) \
93 static GETHOSTNAME pgethostname = NULL;
94 static GETHOSTBYNAME pgethostbyname = NULL;
95 static INET_NTOA pinet_ntoa = NULL;
96 static DNSQUERY pDnsQuery = NULL;
97 static DNSFREEFN pDnsFreeFn = NULL;
99 #define gethostname pgethostname
100 #define gethostbyname pgethostbyname
101 #define inet_ntoa pinet_ntoa
102 #define DnsQuery pDnsQuery
103 #define DnsFreeFn pDnsFreeFn
107 static INSTANCE_HANDLE hDNS;
110 int initDNSSRV(
const INSTANCE_HANDLE hTCP )
113 gethostname = ( GETHOSTNAME ) DynamicBind( hTCP,
TEXT(
"gethostname" ) );
114 gethostbyname = ( GETHOSTBYNAME ) DynamicBind( hTCP,
TEXT(
"gethostbyname" ) );
115 inet_ntoa = ( INET_NTOA ) DynamicBind( hTCP,
TEXT(
"inet_ntoa" ) );
116 if( gethostname == NULL || gethostbyname == NULL || inet_ntoa == NULL )
120 #if defined( __WIN16__ )
121 hDNS = NULL_INSTANCE;
123 #if defined( __WIN32__ )
124 hDNS = DynamicLoad(
"dnsapi.dll" );
125 #elif defined( __WINCE__ )
128 if( hDNS != NULL_INSTANCE )
130 DnsQuery = ( DNSQUERY ) DynamicBind( hDNS,
TEXT(
"DnsQuery_A" ) );
131 DnsFreeFn = ( DNSFREEFN ) DynamicBind( hDNS,
TEXT(
"DnsFree" ) );
132 if( DnsFreeFn == NULL )
133 DnsFreeFn = ( DNSFREEFN ) DynamicBind( hDNS,
TEXT(
"DnsRecordListFree" ) );
134 if( ( DnsQuery == NULL || DnsFreeFn == NULL ) && hDNS != hTCP )
136 DynamicUnload( hDNS );
137 hDNS = NULL_INSTANCE;
146 void endDNSSRV(
const INSTANCE_HANDLE hTCP )
148 if( hDNS != NULL_INSTANCE && hDNS != hTCP )
149 DynamicUnload( hDNS );
150 hDNS = NULL_INSTANCE;
160 #if defined( __WINDOWS__ ) && !defined( __WIN16__ )
167 const int hostNameLength = strlen( hostName ) + 1;
170 assert(
isReadPtr( srvName, srvNameMaxLen ) );
177 memset( srvName, 0,
min( 16, srvNameMaxLen ) );
181 if( 16 + hostNameLength > srvNameMaxLen )
187 for( i = 0; i < hostNameLength; i++ )
189 if( hostName[ i ] ==
'.' )
192 memcpy( srvName,
"_pkiboot._tcp.", 14 );
193 if( i < hostNameLength )
194 memcpy( srvName + 14, hostName + i, hostNameLength - i );
196 memcpy( srvName + 14, hostName, hostNameLength );
206 PDNS_RECORD pDns = NULL;
207 struct hostent *hostInfo;
209 static time_t lastFetchTime = 0;
211 char fqdnBuffer[
MAX_DNS_SIZE + 8 ], *fqdnPtr = fqdnBuffer;
223 memset( fqdn, 0,
min( 16, fqdnMaxLen ) );
228 if( lastFetchTime >=
getTime() - 60 )
230 strlcpy_s( fqdn, fqdnMaxLen, cachedFQDN );
241 ( hostInfo = gethostbyname( cachedFQDN ) ) != NULL )
246 i < IP_ADDR_COUNT && hostInfo->h_addr_list[ i ] != NULL;
249 struct in_addr address;
253 address.S_un.S_addr = *( (
DWORD * ) hostInfo->h_addr_list[ i ] );
255 inet_ntoa( address ) );
258 if( DnsQuery( cachedFQDN, DNS_TYPE_PTR, DNS_QUERY_BYPASS_CACHE,
259 NULL, &pDns, NULL ) == 0 )
265 return( setSocketError( netStream,
266 "Couldn't determine FQDN of local machine",
270 unicodeToAscii( fqdnBuffer,
MAX_DNS_SIZE, pDns->Data.PTR.pNameHost,
271 wcslen( pDns->Data.PTR.pNameHost ) + 1 );
273 fqdnPtr = pDns->Data.PTR.pNameHost;
275 status = convertToSrv( cachedFQDN,
MAX_DNS_SIZE, fqdnPtr );
276 DnsFreeFn( pDns, DnsFreeRecordList );
279 return( setSocketError( netStream,
280 "Couldn't convert FQDN into SRV query name",
286 strlcpy_s( fqdn, fqdnMaxLen, cachedFQDN );
300 PDNS_RECORD pDns = NULL, pDnsInfo = NULL, pDnsCursor;
303 int priority = 32767, i;
306 assert(
isWritePtr( hostName, hostNameMaxLen ) );
307 assert(
isWritePtr( hostPort,
sizeof(
int ) ) );
315 memset( hostName, 0,
min( 16, hostNameMaxLen ) );
319 memcpy( nameBuffer, name, nameLen );
325 if( hDNS == NULL_INSTANCE )
327 return( setSocketError( netStream,
"DNS services not available", 26,
336 const int status = getSrvFQDN( netStream, hostName, hostNameMaxLen );
346 dwRet = DnsQuery( (
const LPSTR ) name, DNS_TYPE_SRV, DNS_QUERY_STANDARD,
348 if( dwRet != 0 || pDns == NULL )
354 for( pDnsCursor = pDns, i = 0;
355 pDnsCursor != NULL && i < IP_ADDR_COUNT;
356 pDnsCursor = pDnsCursor->pNext, i++ )
358 if( pDnsCursor->Data.SRV.wPriority < priority )
360 priority = pDnsCursor->Data.SRV.wPriority;
361 pDnsInfo = pDnsCursor;
365 if( pDnsInfo == NULL || \
366 wcslen( pDnsInfo->Data.SRV.pNameTarget ) + 1 > hostNameMaxLen )
368 if( pDnsInfo == NULL || \
369 strlen( pDnsInfo->Data.SRV.pNameTarget ) + 1 > hostNameMaxLen )
372 DnsFreeFn( pDns, DnsFreeRecordList );
373 return( setSocketError( netStream,
"Invalid DNS SRV entry for host", 30,
379 unicodeToAscii( hostName, hostNameMaxLen,
380 pDnsInfo->Data.SRV.pNameTarget,
381 wcslen( pDnsInfo->Data.SRV.pNameTarget ) + 1 );
383 strlcpy_s( hostName, hostNameMaxLen, pDnsInfo->Data.SRV.pNameTarget );
385 *hostPort = pDnsInfo->Data.SRV.wPort;
388 DnsFreeFn( pDns, DnsFreeRecordList );
398 #elif defined( __UNIX__ ) && \
399 !( defined( __CYGWIN__) || ( defined( sun ) && OSVERSION <= 5 ) || \
400 defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \
401 defined( __UCLIBC__ ) )
403 #define SRV_PRIORITY_OFFSET ( NS_RRFIXEDSZ + 0 )
404 #define SRV_WEIGHT_OFFSET ( NS_RRFIXEDSZ + 2 )
405 #define SRV_PORT_OFFSET ( NS_RRFIXEDSZ + 4 )
406 #define SRV_NAME_OFFSET ( NS_RRFIXEDSZ + 6 )
413 struct hostent *hostInfo;
414 char *hostNamePtr = NULL;
423 memset( fqdn, 0,
min( 16, fqdnMaxLen ) );
432 if( gethostname( fqdn, fqdnMaxLen ) == -1 )
434 fqdn[ fqdnMaxLen - 1 ] =
'\0';
435 if( strchr( fqdn,
'.' ) != NULL )
442 if( ( hostInfo = gethostbyname( fqdn ) ) == NULL )
444 for( addressCount = 0;
445 addressCount < IP_ADDR_COUNT && \
446 hostInfo->h_addr_list[ addressCount ] != NULL; addressCount++ )
454 if( strchr( hostInfo->h_name,
'.' ) != NULL )
456 hostNamePtr = hostInfo->h_name;
461 if( hostInfo->h_aliases == NULL )
463 for( aliasPtrPtr = hostInfo->h_aliases, i = 0;
464 *aliasPtrPtr != NULL && !strchr( *aliasPtrPtr,
'.' ) && \
466 aliasPtrPtr++, i++ );
467 if( *aliasPtrPtr != NULL )
469 hostNamePtr = *aliasPtrPtr;
473 if( hostNamePtr == NULL )
477 if( strlen( hostNamePtr ) + 1 > fqdnMaxLen )
479 strlcpy_s( fqdn, fqdnMaxLen, hostNamePtr );
495 BYTE *namePtr, *endPtr;
497 int resultLen, nameSegmentLen, qCount, aCount, minPriority = 32767;
501 assert(
isWritePtr( hostName, hostNameMaxLen ) );
502 assert(
isWritePtr( hostPort,
sizeof(
int ) ) );
510 memset( hostName, 0,
min( 16, hostNameMaxLen ) );
514 memcpy( nameBuffer, name, nameLen );
523 const int status = getFQDN( netStream, hostName, hostNameMaxLen );
534 name = bufferToEbcdic( hostName, name );
545 resultLen = res_query( name,
C_IN, T_SRV, dnsQueryInfo.buffer,
547 if( resultLen < NS_HFIXEDSZ || resultLen > NS_PACKETSZ )
553 if( dnsQueryInfo.header.rcode != 0 || dnsQueryInfo.header.tc != 0 )
562 return( setSocketError( netStream,
563 "RR contains non-zero response code or "
564 "response was truncated", 60,
567 qCount = ntohs( dnsQueryInfo.header.qdcount );
568 aCount = ntohs( dnsQueryInfo.header.ancount );
569 if( qCount < 0 || qCount > 100 || aCount <= 0 || aCount > 100 )
573 return( setSocketError( netStream,
"RR contains no answer entries", 29,
578 namePtr = dnsQueryInfo.buffer + NS_HFIXEDSZ;
579 endPtr = dnsQueryInfo.buffer + resultLen;
580 for( i = 0; i < qCount && namePtr < endPtr && i < 100; i++ )
582 nameSegmentLen = dn_skipname( namePtr, endPtr );
583 if( nameSegmentLen <= 0 || nameSegmentLen >
MAX_DNS_SIZE )
585 return( setSocketError( netStream,
586 "RR contains invalid question", 28,
589 namePtr += nameSegmentLen + NS_QFIXEDSZ;
591 if( namePtr > endPtr )
593 return( setSocketError( netStream,
"RR contains invalid data", 24,
605 nameSegmentLen = dn_skipname( namePtr, endPtr );
606 if( nameSegmentLen <= 0 || nameSegmentLen > MAX_DNS_SIZE )
608 return( setSocketError( netStream,
"RR contains invalid answer", 26,
611 namePtr += nameSegmentLen;
612 priority = ntohs( *( ( u_short * ) ( namePtr + SRV_PRIORITY_OFFSET ) ) );
613 port = ntohs( *( ( u_short * ) ( namePtr + SRV_PORT_OFFSET ) ) );
614 namePtr += NS_SRVFIXEDSZ;
615 if( priority < minPriority )
618 nameSegmentLen = dn_expand( dnsQueryInfo.buffer, endPtr,
619 namePtr, hostName, hostNameMaxLen );
621 minPriority = priority;
626 nameSegmentLen = dn_skipname( namePtr, endPtr );
628 if( nameSegmentLen <= 0 || nameSegmentLen > MAX_DNS_SIZE )
630 return( setSocketError( netStream,
"RR contains invalid answer", 26,
633 hostName[ nameSegmentLen ] =
'\0';
634 namePtr += nameSegmentLen;
636 if( namePtr > endPtr )
638 return( setSocketError( netStream,
"RR contains invalid data", 24,
642 ebcdicToAscii( hostName, strlen( hostName ) );