dnsapi: Build the DNS reply records on the PE side.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
aec19e86f6
commit
d193c164b7
|
@ -125,7 +125,7 @@ struct resolv_funcs
|
|||
{
|
||||
DNS_STATUS (CDECL *get_searchlist)( DNS_TXT_DATAW *list, DWORD *len );
|
||||
DNS_STATUS (CDECL *get_serverlist)( USHORT family, DNS_ADDR_ARRAY *addrs, DWORD *len );
|
||||
DNS_STATUS (CDECL *query)( const char *name, WORD type, DWORD options, DNS_RECORDA **result );
|
||||
DNS_STATUS (CDECL *query)( const char *name, WORD type, DWORD options, void *buf, DWORD *len );
|
||||
DNS_STATUS (CDECL *set_serverlist)( const IP4_ARRAY *addrs );
|
||||
};
|
||||
|
||||
|
|
|
@ -109,90 +109,6 @@ static DWORD dnsapi_umbstowcs( const char *src, WCHAR *dst, DWORD dstlen )
|
|||
}
|
||||
}
|
||||
|
||||
const char *debugstr_type( unsigned short type )
|
||||
{
|
||||
const char *str;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
#define X(x) case (x): str = #x; break;
|
||||
X(DNS_TYPE_ZERO)
|
||||
X(DNS_TYPE_A)
|
||||
X(DNS_TYPE_NS)
|
||||
X(DNS_TYPE_MD)
|
||||
X(DNS_TYPE_MF)
|
||||
X(DNS_TYPE_CNAME)
|
||||
X(DNS_TYPE_SOA)
|
||||
X(DNS_TYPE_MB)
|
||||
X(DNS_TYPE_MG)
|
||||
X(DNS_TYPE_MR)
|
||||
X(DNS_TYPE_NULL)
|
||||
X(DNS_TYPE_WKS)
|
||||
X(DNS_TYPE_PTR)
|
||||
X(DNS_TYPE_HINFO)
|
||||
X(DNS_TYPE_MINFO)
|
||||
X(DNS_TYPE_MX)
|
||||
X(DNS_TYPE_TEXT)
|
||||
X(DNS_TYPE_RP)
|
||||
X(DNS_TYPE_AFSDB)
|
||||
X(DNS_TYPE_X25)
|
||||
X(DNS_TYPE_ISDN)
|
||||
X(DNS_TYPE_RT)
|
||||
X(DNS_TYPE_NSAP)
|
||||
X(DNS_TYPE_NSAPPTR)
|
||||
X(DNS_TYPE_SIG)
|
||||
X(DNS_TYPE_KEY)
|
||||
X(DNS_TYPE_PX)
|
||||
X(DNS_TYPE_GPOS)
|
||||
X(DNS_TYPE_AAAA)
|
||||
X(DNS_TYPE_LOC)
|
||||
X(DNS_TYPE_NXT)
|
||||
X(DNS_TYPE_EID)
|
||||
X(DNS_TYPE_NIMLOC)
|
||||
X(DNS_TYPE_SRV)
|
||||
X(DNS_TYPE_ATMA)
|
||||
X(DNS_TYPE_NAPTR)
|
||||
X(DNS_TYPE_KX)
|
||||
X(DNS_TYPE_CERT)
|
||||
X(DNS_TYPE_A6)
|
||||
X(DNS_TYPE_DNAME)
|
||||
X(DNS_TYPE_SINK)
|
||||
X(DNS_TYPE_OPT)
|
||||
X(DNS_TYPE_UINFO)
|
||||
X(DNS_TYPE_UID)
|
||||
X(DNS_TYPE_GID)
|
||||
X(DNS_TYPE_UNSPEC)
|
||||
X(DNS_TYPE_ADDRS)
|
||||
X(DNS_TYPE_TKEY)
|
||||
X(DNS_TYPE_TSIG)
|
||||
X(DNS_TYPE_IXFR)
|
||||
X(DNS_TYPE_AXFR)
|
||||
X(DNS_TYPE_MAILB)
|
||||
X(DNS_TYPE_MAILA)
|
||||
X(DNS_TYPE_ANY)
|
||||
X(DNS_TYPE_WINS)
|
||||
X(DNS_TYPE_WINSR)
|
||||
#undef X
|
||||
default:
|
||||
return wine_dbg_sprintf( "0x%04x", type );
|
||||
}
|
||||
|
||||
return wine_dbg_sprintf( "%s", str );
|
||||
}
|
||||
|
||||
static const char *debugstr_section( ns_sect section )
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case ns_s_qd: return "Question";
|
||||
case ns_s_an: return "Answer";
|
||||
case ns_s_ns: return "Authority";
|
||||
case ns_s_ar: return "Additional";
|
||||
default:
|
||||
return wine_dbg_sprintf( "0x%02x", section );
|
||||
}
|
||||
}
|
||||
|
||||
/* call res_init() just once because of a bug in Mac OS X 10.4 */
|
||||
/* call once per thread on systems that have per-thread _res */
|
||||
static void init_resolver( void )
|
||||
|
@ -239,27 +155,6 @@ static unsigned long map_options( DWORD options )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static DNS_STATUS map_error( int error )
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case ns_r_noerror: return ERROR_SUCCESS;
|
||||
case ns_r_formerr: return DNS_ERROR_RCODE_FORMAT_ERROR;
|
||||
case ns_r_servfail: return DNS_ERROR_RCODE_SERVER_FAILURE;
|
||||
case ns_r_nxdomain: return DNS_ERROR_RCODE_NAME_ERROR;
|
||||
case ns_r_notimpl: return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
|
||||
case ns_r_refused: return DNS_ERROR_RCODE_REFUSED;
|
||||
case ns_r_yxdomain: return DNS_ERROR_RCODE_YXDOMAIN;
|
||||
case ns_r_yxrrset: return DNS_ERROR_RCODE_YXRRSET;
|
||||
case ns_r_nxrrset: return DNS_ERROR_RCODE_NXRRSET;
|
||||
case ns_r_notauth: return DNS_ERROR_RCODE_NOTAUTH;
|
||||
case ns_r_notzone: return DNS_ERROR_RCODE_NOTZONE;
|
||||
default:
|
||||
FIXME( "unmapped error code: %d\n", error );
|
||||
return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
static DNS_STATUS map_h_errno( int error )
|
||||
{
|
||||
switch (error)
|
||||
|
@ -472,462 +367,18 @@ static DNS_STATUS CDECL resolv_set_serverlist( const IP4_ARRAY *addrs )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static char *dname_from_msg( ns_msg msg, const unsigned char *pos )
|
||||
{
|
||||
char *str, dname[NS_MAXDNAME] = ".";
|
||||
|
||||
/* returns *compressed* length, ignore it */
|
||||
ns_name_uncompress( ns_msg_base(msg), ns_msg_end(msg), pos, dname, sizeof(dname) );
|
||||
|
||||
if ((str = RtlAllocateHeap( GetProcessHeap(), 0, strlen(dname) + 1 ))) strcpy( str, dname );
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *str_from_rdata( const unsigned char *rdata )
|
||||
{
|
||||
char *str;
|
||||
unsigned int len = rdata[0];
|
||||
|
||||
if ((str = RtlAllocateHeap( GetProcessHeap(), 0, len + 1 )))
|
||||
{
|
||||
memcpy( str, ++rdata, len );
|
||||
str[len] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static unsigned int get_record_size( const ns_rr *rr )
|
||||
{
|
||||
const unsigned char *pos = rr->rdata;
|
||||
unsigned int num = 0, size = sizeof(DNS_RECORDA);
|
||||
|
||||
switch (rr->type)
|
||||
{
|
||||
case ns_t_key:
|
||||
{
|
||||
pos += sizeof(WORD) + sizeof(BYTE) + sizeof(BYTE);
|
||||
size += rr->rdata + rr->rdlength - pos - 1;
|
||||
break;
|
||||
}
|
||||
case ns_t_sig:
|
||||
{
|
||||
pos += sizeof(PCHAR) + sizeof(WORD) + 2 * sizeof(BYTE);
|
||||
pos += 3 * sizeof(DWORD) + 2 * sizeof(WORD);
|
||||
size += rr->rdata + rr->rdlength - pos - 1;
|
||||
break;
|
||||
}
|
||||
case ns_t_hinfo:
|
||||
case ns_t_isdn:
|
||||
case ns_t_txt:
|
||||
case ns_t_x25:
|
||||
{
|
||||
while (pos[0] && pos < rr->rdata + rr->rdlength)
|
||||
{
|
||||
num++;
|
||||
pos += pos[0] + 1;
|
||||
}
|
||||
size += (num - 1) * sizeof(PCHAR);
|
||||
break;
|
||||
}
|
||||
case ns_t_null:
|
||||
case ns_t_opt:
|
||||
{
|
||||
size += rr->rdlength - 1;
|
||||
break;
|
||||
}
|
||||
case ns_t_nxt:
|
||||
case ns_t_wks:
|
||||
case 0xff01: /* WINS */
|
||||
{
|
||||
FIXME( "unhandled type: %s\n", debugstr_type( rr->type ) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static DNS_STATUS copy_rdata( ns_msg msg, const ns_rr *rr, DNS_RECORDA *r, WORD *dlen )
|
||||
static DNS_STATUS CDECL resolv_query( const char *name, WORD type, DWORD options, void *answer, DWORD *retlen )
|
||||
{
|
||||
DNS_STATUS ret = ERROR_SUCCESS;
|
||||
const unsigned char *pos = rr->rdata;
|
||||
unsigned int i, size;
|
||||
|
||||
switch (rr->type)
|
||||
{
|
||||
case ns_t_a:
|
||||
{
|
||||
r->Data.A.IpAddress = *(const DWORD *)pos;
|
||||
*dlen = sizeof(DNS_A_DATA);
|
||||
break;
|
||||
}
|
||||
case ns_t_aaaa:
|
||||
{
|
||||
for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
|
||||
{
|
||||
r->Data.AAAA.Ip6Address.IP6Dword[i] = *(const DWORD *)pos;
|
||||
pos += sizeof(DWORD);
|
||||
}
|
||||
|
||||
*dlen = sizeof(DNS_AAAA_DATA);
|
||||
break;
|
||||
}
|
||||
case ns_t_key:
|
||||
{
|
||||
/* FIXME: byte order? */
|
||||
r->Data.KEY.wFlags = *(const WORD *)pos; pos += sizeof(WORD);
|
||||
r->Data.KEY.chProtocol = *pos++;
|
||||
r->Data.KEY.chAlgorithm = *pos++;
|
||||
|
||||
size = rr->rdata + rr->rdlength - pos;
|
||||
r->Data.KEY.wKeyLength = size;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
r->Data.KEY.Key[i] = *pos++;
|
||||
|
||||
*dlen = sizeof(DNS_KEY_DATA) + (size - 1) * sizeof(BYTE);
|
||||
break;
|
||||
}
|
||||
case ns_t_rp:
|
||||
case ns_t_minfo:
|
||||
{
|
||||
r->Data.MINFO.pNameMailbox = dname_from_msg( msg, pos );
|
||||
if (!r->Data.MINFO.pNameMailbox) return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
|
||||
return DNS_ERROR_BAD_PACKET;
|
||||
|
||||
r->Data.MINFO.pNameErrorsMailbox = dname_from_msg( msg, pos );
|
||||
if (!r->Data.MINFO.pNameErrorsMailbox)
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.MINFO.pNameMailbox );
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
*dlen = sizeof(DNS_MINFO_DATAA);
|
||||
break;
|
||||
}
|
||||
case ns_t_afsdb:
|
||||
case ns_t_rt:
|
||||
case ns_t_mx:
|
||||
{
|
||||
r->Data.MX.wPreference = ntohs( *(const WORD *)pos );
|
||||
r->Data.MX.pNameExchange = dname_from_msg( msg, pos + sizeof(WORD) );
|
||||
if (!r->Data.MX.pNameExchange) return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
*dlen = sizeof(DNS_MX_DATAA);
|
||||
break;
|
||||
}
|
||||
case ns_t_null:
|
||||
{
|
||||
r->Data.Null.dwByteCount = rr->rdlength;
|
||||
memcpy( r->Data.Null.Data, rr->rdata, rr->rdlength );
|
||||
|
||||
*dlen = sizeof(DNS_NULL_DATA) + rr->rdlength - 1;
|
||||
break;
|
||||
}
|
||||
case ns_t_opt:
|
||||
{
|
||||
r->Data.OPT.wDataLength = rr->rdlength;
|
||||
r->Data.OPT.wPad = 0;
|
||||
memcpy( r->Data.OPT.Data, rr->rdata, rr->rdlength );
|
||||
|
||||
*dlen = sizeof(DNS_OPT_DATA) + rr->rdlength - 1;
|
||||
break;
|
||||
}
|
||||
case ns_t_cname:
|
||||
case ns_t_ns:
|
||||
case ns_t_mb:
|
||||
case ns_t_md:
|
||||
case ns_t_mf:
|
||||
case ns_t_mg:
|
||||
case ns_t_mr:
|
||||
case ns_t_ptr:
|
||||
{
|
||||
r->Data.PTR.pNameHost = dname_from_msg( msg, pos );
|
||||
if (!r->Data.PTR.pNameHost) return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
*dlen = sizeof(DNS_PTR_DATAA);
|
||||
break;
|
||||
}
|
||||
case ns_t_sig:
|
||||
{
|
||||
r->Data.SIG.pNameSigner = dname_from_msg( msg, pos );
|
||||
if (!r->Data.SIG.pNameSigner) return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
|
||||
return DNS_ERROR_BAD_PACKET;
|
||||
|
||||
/* FIXME: byte order? */
|
||||
r->Data.SIG.wTypeCovered = *(const WORD *)pos; pos += sizeof(WORD);
|
||||
r->Data.SIG.chAlgorithm = *pos++;
|
||||
r->Data.SIG.chLabelCount = *pos++;
|
||||
r->Data.SIG.dwOriginalTtl = *(const DWORD *)pos; pos += sizeof(DWORD);
|
||||
r->Data.SIG.dwExpiration = *(const DWORD *)pos; pos += sizeof(DWORD);
|
||||
r->Data.SIG.dwTimeSigned = *(const DWORD *)pos; pos += sizeof(DWORD);
|
||||
r->Data.SIG.wKeyTag = *(const WORD *)pos;
|
||||
|
||||
size = rr->rdata + rr->rdlength - pos;
|
||||
r->Data.SIG.wSignatureLength = size;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
r->Data.SIG.Signature[i] = *pos++;
|
||||
|
||||
*dlen = sizeof(DNS_SIG_DATAA) + (size - 1) * sizeof(BYTE);
|
||||
break;
|
||||
}
|
||||
case ns_t_soa:
|
||||
{
|
||||
r->Data.SOA.pNamePrimaryServer = dname_from_msg( msg, pos );
|
||||
if (!r->Data.SOA.pNamePrimaryServer) return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
|
||||
return DNS_ERROR_BAD_PACKET;
|
||||
|
||||
r->Data.SOA.pNameAdministrator = dname_from_msg( msg, pos );
|
||||
if (!r->Data.SOA.pNameAdministrator)
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.SOA.pNamePrimaryServer );
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
|
||||
return DNS_ERROR_BAD_PACKET;
|
||||
|
||||
r->Data.SOA.dwSerialNo = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
|
||||
r->Data.SOA.dwRefresh = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
|
||||
r->Data.SOA.dwRetry = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
|
||||
r->Data.SOA.dwExpire = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
|
||||
r->Data.SOA.dwDefaultTtl = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
|
||||
|
||||
*dlen = sizeof(DNS_SOA_DATAA);
|
||||
break;
|
||||
}
|
||||
case ns_t_srv:
|
||||
{
|
||||
r->Data.SRV.wPriority = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
|
||||
r->Data.SRV.wWeight = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
|
||||
r->Data.SRV.wPort = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
|
||||
|
||||
r->Data.SRV.pNameTarget = dname_from_msg( msg, pos );
|
||||
if (!r->Data.SRV.pNameTarget) return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
*dlen = sizeof(DNS_SRV_DATAA);
|
||||
break;
|
||||
}
|
||||
case ns_t_hinfo:
|
||||
case ns_t_isdn:
|
||||
case ns_t_x25:
|
||||
case ns_t_txt:
|
||||
{
|
||||
i = 0;
|
||||
while (pos[0] && pos < rr->rdata + rr->rdlength)
|
||||
{
|
||||
r->Data.TXT.pStringArray[i] = str_from_rdata( pos );
|
||||
if (!r->Data.TXT.pStringArray[i])
|
||||
{
|
||||
while (i > 0) RtlFreeHeap( GetProcessHeap(), 0, r->Data.TXT.pStringArray[--i] );
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
i++;
|
||||
pos += pos[0] + 1;
|
||||
}
|
||||
r->Data.TXT.dwStringCount = i;
|
||||
*dlen = sizeof(DNS_TXT_DATAA) + (i - 1) * sizeof(PCHAR);
|
||||
break;
|
||||
}
|
||||
case ns_t_atma:
|
||||
case ns_t_loc:
|
||||
case ns_t_nxt:
|
||||
case ns_t_tsig:
|
||||
case ns_t_wks:
|
||||
case 0x00f9: /* TKEY */
|
||||
case 0xff01: /* WINS */
|
||||
case 0xff02: /* WINSR */
|
||||
default:
|
||||
FIXME( "unhandled type: %s\n", debugstr_type( rr->type ) );
|
||||
return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline char *heap_strdup( const char *src )
|
||||
{
|
||||
char *dst;
|
||||
if (!src) return NULL;
|
||||
if ((dst = RtlAllocateHeap( GetProcessHeap(), 0, (strlen( src ) + 1) * sizeof(char) ))) strcpy( dst, src );
|
||||
return dst;
|
||||
}
|
||||
|
||||
static DNS_STATUS copy_record( ns_msg msg, ns_sect section, unsigned short num, DNS_RECORDA **recp )
|
||||
{
|
||||
DNS_STATUS ret;
|
||||
DNS_RECORDA *record;
|
||||
WORD dlen;
|
||||
ns_rr rr;
|
||||
|
||||
if (ns_parserr( &msg, section, num, &rr ) < 0)
|
||||
return DNS_ERROR_BAD_PACKET;
|
||||
|
||||
if (!(record = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, get_record_size( &rr ) )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
if (!(record->pName = heap_strdup( rr.name )))
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, record );
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
record->wType = rr.type;
|
||||
record->Flags.S.Section = section;
|
||||
record->Flags.S.CharSet = DnsCharSetUtf8;
|
||||
record->dwTtl = rr.ttl;
|
||||
|
||||
if ((ret = copy_rdata( msg, &rr, record, &dlen )))
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, record->pName );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, record );
|
||||
return ret;
|
||||
}
|
||||
record->wDataLength = dlen;
|
||||
*recp = record;
|
||||
|
||||
TRACE( "found %s record in %s section\n", debugstr_type( rr.type ), debugstr_section( section ) );
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static void free_record_list( DNS_RECORD *list )
|
||||
{
|
||||
DNS_RECORD *r, *next;
|
||||
unsigned int i;
|
||||
|
||||
for (r = list; (list = r); r = next)
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->pName );
|
||||
|
||||
switch (r->wType)
|
||||
{
|
||||
case DNS_TYPE_HINFO:
|
||||
case DNS_TYPE_ISDN:
|
||||
case DNS_TYPE_TEXT:
|
||||
case DNS_TYPE_X25:
|
||||
{
|
||||
for (i = 0; i < r->Data.TXT.dwStringCount; i++)
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.TXT.pStringArray[i] );
|
||||
break;
|
||||
}
|
||||
case DNS_TYPE_MINFO:
|
||||
case DNS_TYPE_RP:
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.MINFO.pNameMailbox );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.MINFO.pNameErrorsMailbox );
|
||||
break;
|
||||
}
|
||||
case DNS_TYPE_AFSDB:
|
||||
case DNS_TYPE_RT:
|
||||
case DNS_TYPE_MX:
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.MX.pNameExchange );
|
||||
break;
|
||||
}
|
||||
case DNS_TYPE_NXT:
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.NXT.pNameNext );
|
||||
break;
|
||||
}
|
||||
case DNS_TYPE_CNAME:
|
||||
case DNS_TYPE_MB:
|
||||
case DNS_TYPE_MD:
|
||||
case DNS_TYPE_MF:
|
||||
case DNS_TYPE_MG:
|
||||
case DNS_TYPE_MR:
|
||||
case DNS_TYPE_NS:
|
||||
case DNS_TYPE_PTR:
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.PTR.pNameHost );
|
||||
break;
|
||||
}
|
||||
case DNS_TYPE_SIG:
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.SIG.pNameSigner );
|
||||
break;
|
||||
}
|
||||
case DNS_TYPE_SOA:
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.SOA.pNamePrimaryServer );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.SOA.pNameAdministrator );
|
||||
break;
|
||||
}
|
||||
case DNS_TYPE_SRV:
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r->Data.SRV.pNameTarget );
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
next = r->pNext;
|
||||
RtlFreeHeap( GetProcessHeap(), 0, r );
|
||||
}
|
||||
}
|
||||
|
||||
#define DNS_MAX_PACKET_SIZE 4096
|
||||
static DNS_STATUS CDECL resolv_query( const char *name, WORD type, DWORD options, DNS_RECORDA **result )
|
||||
{
|
||||
DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
|
||||
unsigned int i, num;
|
||||
unsigned char answer[DNS_MAX_PACKET_SIZE];
|
||||
ns_sect sections[] = { ns_s_an, ns_s_ar };
|
||||
ns_msg msg;
|
||||
DNS_RECORDA *record = NULL;
|
||||
DNS_RRSET rrset;
|
||||
int len;
|
||||
|
||||
DNS_RRSET_INIT( rrset );
|
||||
|
||||
init_resolver();
|
||||
_res.options |= map_options( options );
|
||||
|
||||
if ((len = res_query( name, ns_c_in, type, answer, sizeof(answer) )) < 0)
|
||||
{
|
||||
if ((len = res_query( name, ns_c_in, type, answer, *retlen )) < 0)
|
||||
ret = map_h_errno( h_errno );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ns_initparse( answer, len, &msg ) < 0)
|
||||
{
|
||||
ret = DNS_ERROR_BAD_PACKET;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#define RCODE_MASK 0x0f
|
||||
if ((msg._flags & RCODE_MASK) != ns_r_noerror)
|
||||
{
|
||||
ret = map_error( msg._flags & RCODE_MASK );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sections); i++)
|
||||
{
|
||||
for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
|
||||
{
|
||||
ret = copy_record( msg, sections[i], num, &record );
|
||||
if (ret != ERROR_SUCCESS) goto exit;
|
||||
|
||||
DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
DNS_RRSET_TERMINATE( rrset );
|
||||
|
||||
if (ret != ERROR_SUCCESS)
|
||||
free_record_list( rrset.pFirstRR );
|
||||
else
|
||||
*result = (DNS_RECORDA *)rrset.pFirstRR;
|
||||
|
||||
*retlen = len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -168,6 +168,8 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser
|
|||
PDNS_RECORDA *result, PVOID *reserved )
|
||||
{
|
||||
DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
|
||||
unsigned char answer[4096];
|
||||
DWORD len = sizeof(answer);
|
||||
|
||||
TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), debugstr_type( type ),
|
||||
options, servers, result, reserved );
|
||||
|
@ -177,7 +179,29 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser
|
|||
|
||||
if ((ret = resolv_funcs->set_serverlist( servers ))) return ret;
|
||||
|
||||
ret = resolv_funcs->query( name, type, options, result );
|
||||
ret = resolv_funcs->query( name, type, options, answer, &len );
|
||||
if (!ret)
|
||||
{
|
||||
DNS_MESSAGE_BUFFER *buffer = (DNS_MESSAGE_BUFFER *)answer;
|
||||
|
||||
if (len < sizeof(buffer->MessageHead)) return DNS_ERROR_BAD_PACKET;
|
||||
DNS_BYTE_FLIP_HEADER_COUNTS( &buffer->MessageHead );
|
||||
switch (buffer->MessageHead.ResponseCode)
|
||||
{
|
||||
case DNS_RCODE_NOERROR: ret = DnsExtractRecordsFromMessage_UTF8( buffer, len, result ); break;
|
||||
case DNS_RCODE_FORMERR: ret = DNS_ERROR_RCODE_FORMAT_ERROR; break;
|
||||
case DNS_RCODE_SERVFAIL: ret = DNS_ERROR_RCODE_SERVER_FAILURE; break;
|
||||
case DNS_RCODE_NXDOMAIN: ret = DNS_ERROR_RCODE_NAME_ERROR; break;
|
||||
case DNS_RCODE_NOTIMPL: ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED; break;
|
||||
case DNS_RCODE_REFUSED: ret = DNS_ERROR_RCODE_REFUSED; break;
|
||||
case DNS_RCODE_YXDOMAIN: ret = DNS_ERROR_RCODE_YXDOMAIN; break;
|
||||
case DNS_RCODE_YXRRSET: ret = DNS_ERROR_RCODE_YXRRSET; break;
|
||||
case DNS_RCODE_NXRRSET: ret = DNS_ERROR_RCODE_NXRRSET; break;
|
||||
case DNS_RCODE_NOTAUTH: ret = DNS_ERROR_RCODE_NOTAUTH; break;
|
||||
case DNS_RCODE_NOTZONE: ret = DNS_ERROR_RCODE_NOTZONE; break;
|
||||
default: ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == DNS_ERROR_RCODE_NAME_ERROR && type == DNS_TYPE_A &&
|
||||
!(options & DNS_QUERY_NO_NETBT))
|
||||
|
|
|
@ -108,6 +108,18 @@ extern "C" {
|
|||
#define DNS_QUERY_DNSSEC_CHECKING_DISABLED 0x02000000
|
||||
#define DNS_QUERY_RESERVED 0xff000000
|
||||
|
||||
#define INLINE_WORD_FLIP(out, in) { WORD _in = (in); (out) = (_in << 8) | (_in >> 8); }
|
||||
#define INLINE_HTONS(out, in) INLINE_WORD_FLIP(out, in)
|
||||
#define INLINE_NTOHS(out, in) INLINE_WORD_FLIP(out, in)
|
||||
|
||||
#define DNS_BYTE_FLIP_HEADER_COUNTS(header) { \
|
||||
DNS_HEADER *_head = (header); \
|
||||
INLINE_HTONS( _head->Xid, _head->Xid ); \
|
||||
INLINE_HTONS( _head->QuestionCount, _head->QuestionCount ); \
|
||||
INLINE_HTONS( _head->AnswerCount, _head->AnswerCount ); \
|
||||
INLINE_HTONS( _head->NameServerCount, _head->NameServerCount ); \
|
||||
INLINE_HTONS( _head->AdditionalCount, _head->AdditionalCount ); }
|
||||
|
||||
typedef enum _DNS_NAME_FORMAT
|
||||
{
|
||||
DnsNameDomain,
|
||||
|
@ -182,7 +194,11 @@ typedef struct
|
|||
#define DNS_ADDRESS_STRING_LENGTH IP6_ADDRESS_STRING_LENGTH
|
||||
#define IP4_ADDRESS_STRING_BUFFER_LENGTH IP4_ADDRESS_STRING_LENGTH
|
||||
#define IP6_ADDRESS_STRING_BUFFER_LENGTH IP6_ADDRESS_STRING_LENGTH
|
||||
#define DNS_MAX_NAME_BUFFER_LENGTH 256
|
||||
|
||||
#define DNS_MAX_NAME_LENGTH 255
|
||||
#define DNS_MAX_LABEL_LENGTH 63
|
||||
#define DNS_MAX_NAME_BUFFER_LENGTH (DNS_MAX_NAME_LENGTH + 1)
|
||||
#define DNS_MAX_LABEL_BUFFER_LENGTH (DNS_MAX_LABEL_LENGTH + 1)
|
||||
|
||||
typedef struct _IP4_ARRAY
|
||||
{
|
||||
|
@ -190,6 +206,36 @@ typedef struct _IP4_ARRAY
|
|||
IP4_ADDRESS AddrArray[1];
|
||||
} IP4_ARRAY, *PIP4_ARRAY;
|
||||
|
||||
#define DNS_OPCODE_QUERY 0
|
||||
#define DNS_OPCODE_IQUERY 1
|
||||
#define DNS_OPCODE_SERVER_STATUS 2
|
||||
#define DNS_OPCODE_UNKNOWN 3
|
||||
#define DNS_OPCODE_NOTIFY 4
|
||||
#define DNS_OPCODE_UPDATE 5
|
||||
|
||||
#define DNS_RCODE_NOERROR 0
|
||||
#define DNS_RCODE_FORMERR 1
|
||||
#define DNS_RCODE_SERVFAIL 2
|
||||
#define DNS_RCODE_NXDOMAIN 3
|
||||
#define DNS_RCODE_NOTIMPL 4
|
||||
#define DNS_RCODE_REFUSED 5
|
||||
#define DNS_RCODE_YXDOMAIN 6
|
||||
#define DNS_RCODE_YXRRSET 7
|
||||
#define DNS_RCODE_NXRRSET 8
|
||||
#define DNS_RCODE_NOTAUTH 9
|
||||
#define DNS_RCODE_NOTZONE 10
|
||||
#define DNS_RCODE_MAX 15
|
||||
#define DNS_RCODE_BADVERS 16
|
||||
#define DNS_RCODE_BADSIG 16
|
||||
#define DNS_RCODE_BADKEY 17
|
||||
#define DNS_RCODE_BADTIME 18
|
||||
|
||||
#define DNS_RCODE_NO_ERROR DNS_RCODE_NOERROR
|
||||
#define DNS_RCODE_FORMAT_ERROR DNS_RCODE_FORMERR
|
||||
#define DNS_RCODE_SERVER_FAILURE DNS_RCODE_SERVFAIL
|
||||
#define DNS_RCODE_NAME_ERROR DNS_RCODE_NXDOMAIN
|
||||
#define DNS_RCODE_NOT_IMPLEMENTED DNS_RCODE_NOTIMPL
|
||||
|
||||
#include <pshpack1.h>
|
||||
typedef struct _DNS_HEADER
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue