Signed-off-by: Hans Leidekker hans@codeweavers.com --- dlls/dnsapi/Makefile.in | 1 + dlls/dnsapi/dnsapi.h | 19 +- dlls/dnsapi/libresolv.c | 742 ++++++++++++++++++++++++++++++++++++++++ dlls/dnsapi/main.c | 20 ++ dlls/dnsapi/name.c | 23 +- dlls/dnsapi/query.c | 582 +------------------------------ dlls/dnsapi/record.c | 66 +--- 7 files changed, 809 insertions(+), 644 deletions(-) create mode 100644 dlls/dnsapi/libresolv.c
diff --git a/dlls/dnsapi/Makefile.in b/dlls/dnsapi/Makefile.in index d1f66723fc6..a4f80e83fd4 100644 --- a/dlls/dnsapi/Makefile.in +++ b/dlls/dnsapi/Makefile.in @@ -4,6 +4,7 @@ IMPORTS = netapi32 EXTRALIBS = $(RESOLV_LIBS)
C_SRCS = \ + libresolv.c \ main.c \ name.c \ query.c \ diff --git a/dlls/dnsapi/dnsapi.h b/dlls/dnsapi/dnsapi.h index d0a31ea0981..bcd6a6d5bc3 100644 --- a/dlls/dnsapi/dnsapi.h +++ b/dlls/dnsapi/dnsapi.h @@ -18,10 +18,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#ifndef __WINE_CONFIG_H -# error You must include config.h to use this header -#endif - #include "wine/heap.h"
static inline char *strdup_a( const char *src ) @@ -123,4 +119,17 @@ static inline char *strdup_ua( const char *src ) return dst; }
-const char *type_to_str( unsigned short ) DECLSPEC_HIDDEN; +extern const char *type_to_str( unsigned short ) DECLSPEC_HIDDEN; + +extern DNS_STATUS CDECL resolv_get_serverlist( IP4_ARRAY *, DWORD * ) DECLSPEC_HIDDEN; +extern DNS_STATUS CDECL resolv_query( const char *, WORD, DWORD, DNS_RECORDA ** ) DECLSPEC_HIDDEN; +extern DNS_STATUS CDECL resolv_set_serverlist( const IP4_ARRAY * ) DECLSPEC_HIDDEN; + +struct resolv_funcs +{ + DNS_STATUS (CDECL *get_serverlist)( IP4_ARRAY *addrs, DWORD *len ); + DNS_STATUS (CDECL *query)( const char *name, WORD type, DWORD options, DNS_RECORDA **result ); + DNS_STATUS (CDECL *set_serverlist)( const IP4_ARRAY *addrs ); +}; + +extern const struct resolv_funcs *resolv_funcs; diff --git a/dlls/dnsapi/libresolv.c b/dlls/dnsapi/libresolv.c new file mode 100644 index 00000000000..ac52147af01 --- /dev/null +++ b/dlls/dnsapi/libresolv.c @@ -0,0 +1,742 @@ +/* + * Unix interface for libresolv + * + * Copyright 2021 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#ifdef HAVE_RESOLV +#include <stdarg.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +# include <arpa/nameser.h> +#endif +#ifdef HAVE_RESOLV_H +# include <resolv.h> +#endif +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "winbase.h" +#include "winnls.h" +#include "windns.h" + +#include "wine/debug.h" +#include "wine/heap.h" +#include "dnsapi.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dnsapi); + +static 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 ) +{ + if (!(_res.options & RES_INIT)) res_init(); +} + +static unsigned long map_options( DWORD options ) +{ + unsigned long ret = 0; + + if (options == DNS_QUERY_STANDARD) + return RES_DEFAULT; + + if (options & DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE) + ret |= RES_IGNTC; + if (options & DNS_QUERY_USE_TCP_ONLY) + ret |= RES_USEVC; + if (options & DNS_QUERY_NO_RECURSION) + ret &= ~RES_RECURSE; + if (options & DNS_QUERY_NO_LOCAL_NAME) + ret &= ~RES_DNSRCH; + if (options & DNS_QUERY_NO_HOSTS_FILE) + ret |= RES_NOALIASES; + if (options & DNS_QUERY_TREAT_AS_FQDN) + ret &= ~RES_DEFNAMES; + + if (options & DNS_QUERY_DONT_RESET_TTL_VALUES) + FIXME( "option DNS_QUERY_DONT_RESET_TTL_VALUES not implemented\n" ); + if (options & DNS_QUERY_RESERVED) + FIXME( "option DNS_QUERY_RESERVED not implemented\n" ); + if (options & DNS_QUERY_WIRE_ONLY) + FIXME( "option DNS_QUERY_WIRE_ONLY not implemented\n" ); + if (options & DNS_QUERY_NO_WIRE_QUERY) + FIXME( "option DNS_QUERY_NO_WIRE_QUERY not implemented\n" ); + if (options & DNS_QUERY_BYPASS_CACHE) + FIXME( "option DNS_QUERY_BYPASS_CACHE not implemented\n" ); + if (options & DNS_QUERY_RETURN_MESSAGE) + FIXME( "option DNS_QUERY_RETURN_MESSAGE not implemented\n" ); + + if (options & DNS_QUERY_NO_NETBT) + TRACE( "netbios query disabled\n" ); + + 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) + { + case NO_DATA: + case HOST_NOT_FOUND: return DNS_ERROR_RCODE_NAME_ERROR; + case TRY_AGAIN: return DNS_ERROR_RCODE_SERVER_FAILURE; + case NO_RECOVERY: return DNS_ERROR_RCODE_REFUSED; +#ifdef NETDB_INTERNAL + case NETDB_INTERNAL: return DNS_ERROR_RCODE; +#endif + default: + FIXME( "unmapped error code: %d\n", error ); + return DNS_ERROR_RCODE_NOT_IMPLEMENTED; + } +} + +DNS_STATUS CDECL resolv_get_serverlist( IP4_ARRAY *addrs, DWORD *len ) +{ + unsigned int size; + int i; + + init_resolver(); + + size = FIELD_OFFSET(IP4_ARRAY, AddrArray[_res.nscount]); + if (!addrs || *len < size) + { + *len = size; + return ERROR_INSUFFICIENT_BUFFER; + } + + addrs->AddrCount = _res.nscount; + + for (i = 0; i < _res.nscount; i++) + addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr; + + return ERROR_SUCCESS; +} + +DNS_STATUS CDECL resolv_set_serverlist( const IP4_ARRAY *addrs ) +{ + int i; + + init_resolver(); + + if (!addrs || !addrs->AddrCount) return ERROR_SUCCESS; + if (addrs->AddrCount > MAXNS) + { + WARN( "too many servers: %d only using the first: %d\n", + addrs->AddrCount, MAXNS ); + _res.nscount = MAXNS; + } + else _res.nscount = addrs->AddrCount; + + for (i = 0; i < _res.nscount; i++) + _res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i]; + + 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 ) +{ + 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; + + 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; + + 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 +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) + { + 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; + + return ret; +} + +static const struct resolv_funcs funcs = +{ + resolv_get_serverlist, + resolv_query, + resolv_set_serverlist +}; + +NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) +{ + if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS; + *(const struct resolv_funcs **)ptr_out = &funcs; + return STATUS_SUCCESS; +} + +#endif /* HAVE_RESOLV */ diff --git a/dlls/dnsapi/main.c b/dlls/dnsapi/main.c index 4ab294c7c07..f83a54d1469 100644 --- a/dlls/dnsapi/main.c +++ b/dlls/dnsapi/main.c @@ -22,6 +22,7 @@ #include <stdarg.h>
#include "windef.h" +#include "winternl.h" #include "winbase.h" #include "winerror.h" #include "windns.h" @@ -30,6 +31,25 @@
WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
+const struct resolv_funcs *resolv_funcs = NULL; + +BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) +{ + TRACE( "(%p,%u,%p)\n", hinst, reason, reserved ); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( hinst ); + if (__wine_init_unix_lib( hinst, reason, NULL, &resolv_funcs )) + ERR( "No libresolv support, expect problems\n" ); + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + /****************************************************************************** * DnsAcquireContextHandle_A [DNSAPI.@] * diff --git a/dlls/dnsapi/name.c b/dlls/dnsapi/name.c index 9404200e443..4f4ba507cac 100644 --- a/dlls/dnsapi/name.c +++ b/dlls/dnsapi/name.c @@ -3,7 +3,7 @@ * * Copyright (C) 2006 Matthew Kehrer * Copyright (C) 2006 Hans Leidekker - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -19,30 +19,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "config.h" -#include "wine/debug.h" -#include "wine/unicode.h" - #include <stdarg.h> -#include <sys/types.h> - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_NAMESER_H -# include <arpa/nameser.h> -# undef NOERROR -#endif -#ifdef HAVE_RESOLV_H -# include <resolv.h> -#endif - #include "windef.h" #include "winbase.h" #include "winerror.h" #include "winnls.h" #include "windns.h"
+#include "wine/debug.h" +#include "wine/unicode.h" #include "dnsapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(dnsapi); @@ -81,7 +66,7 @@ BOOL WINAPI DnsNameCompare_W( PCWSTR name1, PCWSTR name2 )
if (!name1 && !name2) return TRUE; if (!name1 || !name2) return FALSE; - + p = name1 + lstrlenW( name1 ) - 1; q = name2 + lstrlenW( name2 ) - 1;
diff --git a/dlls/dnsapi/query.c b/dlls/dnsapi/query.c index 3bef65e9731..a7ae77148be 100644 --- a/dlls/dnsapi/query.c +++ b/dlls/dnsapi/query.c @@ -2,7 +2,7 @@ * DNS support * * Copyright (C) 2006 Hans Leidekker - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -18,28 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "config.h" -#include "wine/port.h" -#include "wine/debug.h" - #include <stdarg.h> -#include <string.h> -#include <stdio.h> -#include <sys/types.h> - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_NAMESER_H -# include <arpa/nameser.h> -#endif -#ifdef HAVE_RESOLV_H -# include <resolv.h> -#endif -#ifdef HAVE_NETDB_H -# include <netdb.h> -#endif - #include "windef.h" #include "winbase.h" #include "winerror.h" @@ -47,438 +26,11 @@ #include "windns.h" #include "nb30.h"
+#include "wine/debug.h" #include "dnsapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
-#ifdef HAVE_RESOLV - -/* 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 initialise_resolver( void ) -{ - if ((_res.options & RES_INIT) == 0) - res_init(); -} - -static const char *section_to_str( 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: - { - static char tmp[11]; - FIXME( "unknown section: 0x%02x\n", section ); - sprintf( tmp, "0x%02x", section ); - return tmp; - } - } -} - -static unsigned long map_options( DWORD options ) -{ - unsigned long ret = 0; - - if (options == DNS_QUERY_STANDARD) - return RES_DEFAULT; - - if (options & DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE) - ret |= RES_IGNTC; - if (options & DNS_QUERY_USE_TCP_ONLY) - ret |= RES_USEVC; - if (options & DNS_QUERY_NO_RECURSION) - ret &= ~RES_RECURSE; - if (options & DNS_QUERY_NO_LOCAL_NAME) - ret &= ~RES_DNSRCH; - if (options & DNS_QUERY_NO_HOSTS_FILE) - ret |= RES_NOALIASES; - if (options & DNS_QUERY_TREAT_AS_FQDN) - ret &= ~RES_DEFNAMES; - - if (options & DNS_QUERY_DONT_RESET_TTL_VALUES) - FIXME( "option DNS_QUERY_DONT_RESET_TTL_VALUES not implemented\n" ); - if (options & DNS_QUERY_RESERVED) - FIXME( "option DNS_QUERY_RESERVED not implemented\n" ); - if (options & DNS_QUERY_WIRE_ONLY) - FIXME( "option DNS_QUERY_WIRE_ONLY not implemented\n" ); - if (options & DNS_QUERY_NO_WIRE_QUERY) - FIXME( "option DNS_QUERY_NO_WIRE_QUERY not implemented\n" ); - if (options & DNS_QUERY_BYPASS_CACHE) - FIXME( "option DNS_QUERY_BYPASS_CACHE not implemented\n" ); - if (options & DNS_QUERY_RETURN_MESSAGE) - FIXME( "option DNS_QUERY_RETURN_MESSAGE not implemented\n" ); - - if (options & DNS_QUERY_NO_NETBT) - TRACE( "netbios query disabled\n" ); - - 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) - { - case NO_DATA: - case HOST_NOT_FOUND: return DNS_ERROR_RCODE_NAME_ERROR; - case TRY_AGAIN: return DNS_ERROR_RCODE_SERVER_FAILURE; - case NO_RECOVERY: return DNS_ERROR_RCODE_REFUSED; -#ifdef NETDB_INTERNAL - case NETDB_INTERNAL: return DNS_ERROR_RCODE; -#endif - default: - FIXME( "unmapped error code: %d\n", error ); - return DNS_ERROR_RCODE_NOT_IMPLEMENTED; - } -} - -static char *dname_from_msg( ns_msg msg, const unsigned char *pos ) -{ - int len; - 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) ); - - len = strlen( dname ); - str = heap_alloc( len + 1 ); - if (str) strcpy( str, dname ); - return str; -} - -static char *str_from_rdata( const unsigned char *rdata ) -{ - char *str; - unsigned int len = rdata[0]; - - str = heap_alloc( len + 1 ); - if (str) - { - 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", type_to_str( rr->type ) ); - break; - } - default: - break; - } - return size; -} - -static DNS_STATUS copy_rdata( ns_msg msg, const ns_rr *rr, DNS_RECORDA *r, WORD *dlen ) -{ - 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; - - 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) - { - heap_free( 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; - - 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) - { - heap_free( 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) heap_free( 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", type_to_str( rr->type ) ); - return DNS_ERROR_RCODE_NOT_IMPLEMENTED; - } - - return ret; -} - -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 = heap_alloc_zero( get_record_size( &rr ) ))) - return ERROR_NOT_ENOUGH_MEMORY; - - record->pName = strdup_u( rr.name ); - if (!record->pName) - { - heap_free( 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 ))) - { - heap_free( record->pName ); - heap_free( record ); - return ret; - } - record->wDataLength = dlen; - *recp = record; - - TRACE( "found %s record in %s section\n", - type_to_str( rr.type ), section_to_str( section ) ); - return ERROR_SUCCESS; -} - #define DEFAULT_TTL 1200
static DNS_STATUS do_query_netbios( PCSTR name, DNS_RECORDA **recp ) @@ -510,7 +62,7 @@ static DNS_STATUS do_query_netbios( PCSTR name, DNS_RECORDA **recp ) header = (FIND_NAME_HEADER *)ncb.ncb_buffer; buffer = (FIND_NAME_BUFFER *)((char *)header + sizeof(FIND_NAME_HEADER));
- for (i = 0; i < header->node_count; i++) + for (i = 0; i < header->node_count; i++) { record = heap_alloc_zero( sizeof(DNS_RECORDA) ); if (!record) @@ -551,107 +103,6 @@ exit: return status; }
-/* res_init() must have been called before calling these three functions. - */ -static DNS_STATUS set_serverlist( const IP4_ARRAY *addrs ) -{ - int i; - - if (!addrs || !addrs->AddrCount) return ERROR_SUCCESS; - if (addrs->AddrCount > MAXNS) - { - WARN( "too many servers: %d only using the first: %d\n", - addrs->AddrCount, MAXNS ); - _res.nscount = MAXNS; - } - else _res.nscount = addrs->AddrCount; - - for (i = 0; i < _res.nscount; i++) - _res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i]; - - return ERROR_SUCCESS; -} - -static DNS_STATUS get_serverlist( PIP4_ARRAY addrs, PDWORD len ) -{ - unsigned int size; - int i; - - size = FIELD_OFFSET(IP4_ARRAY, AddrArray[_res.nscount]); - if (!addrs || *len < size) - { - *len = size; - return ERROR_INSUFFICIENT_BUFFER; - } - - addrs->AddrCount = _res.nscount; - - for (i = 0; i < _res.nscount; i++) - addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr; - - return ERROR_SUCCESS; -} - -#define DNS_MAX_PACKET_SIZE 4096 -static DNS_STATUS do_query( PCSTR name, WORD type, DWORD options, PDNS_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 ); - - len = res_query( name, ns_c_in, type, answer, sizeof(answer) ); - if (len < 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) - DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList ); - else - *result = (DNS_RECORDA *)rrset.pFirstRR; - - return ret; -} - -#endif /* HAVE_RESOLV */ - static const char *debugstr_query_request(const DNS_QUERY_REQUEST *req) { if (!req) @@ -693,7 +144,7 @@ DNS_STATUS WINAPI DnsQuery_A( PCSTR name, WORD type, DWORD options, PVOID server nameW = strdup_aw( name ); if (!nameW) return ERROR_NOT_ENOUGH_MEMORY;
- status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved ); + status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved );
if (status == ERROR_SUCCESS) { @@ -716,7 +167,6 @@ 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; -#ifdef HAVE_RESOLV
TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), type_to_str( type ), options, servers, result, reserved ); @@ -724,12 +174,9 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser if (!name || !result) return ERROR_INVALID_PARAMETER;
- initialise_resolver(); - _res.options |= map_options( options ); - - if ((ret = set_serverlist( servers ))) return ret; + if ((ret = resolv_funcs->set_serverlist( servers ))) return ret;
- ret = do_query( name, type, options, result ); + ret = resolv_funcs->query( name, type, options, result );
if (ret == DNS_ERROR_RCODE_NAME_ERROR && type == DNS_TYPE_A && !(options & DNS_QUERY_NO_NETBT)) @@ -738,7 +185,6 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser ret = do_query_netbios( name, result ); }
-#endif return ret; }
@@ -762,7 +208,7 @@ DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID serve nameU = strdup_wu( name ); if (!nameU) return ERROR_NOT_ENOUGH_MEMORY;
- status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved ); + status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved );
if (status == ERROR_SUCCESS) { @@ -777,8 +223,7 @@ DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID serve return status; }
-static DNS_STATUS get_hostname_a( COMPUTER_NAME_FORMAT format, - PSTR buffer, PDWORD len ) +static DNS_STATUS get_hostname_a( COMPUTER_NAME_FORMAT format, PSTR buffer, PDWORD len ) { char name[256]; DWORD size = ARRAY_SIZE(name); @@ -796,8 +241,7 @@ static DNS_STATUS get_hostname_a( COMPUTER_NAME_FORMAT format, return ERROR_SUCCESS; }
-static DNS_STATUS get_hostname_w( COMPUTER_NAME_FORMAT format, - PWSTR buffer, PDWORD len ) +static DNS_STATUS get_hostname_w( COMPUTER_NAME_FORMAT format, PWSTR buffer, PDWORD len ) { WCHAR name[256]; DWORD size = ARRAY_SIZE(name); @@ -833,14 +277,8 @@ DNS_STATUS WINAPI DnsQueryConfig( DNS_CONFIG_TYPE config, DWORD flag, PCWSTR ada { case DnsConfigDnsServerList: { -#ifdef HAVE_RESOLV - initialise_resolver(); - ret = get_serverlist( buffer, len ); - break; -#else - WARN( "compiled without resolver support\n" ); + ret = resolv_funcs->get_serverlist( buffer, len ); break; -#endif } case DnsConfigHostName_A: case DnsConfigHostName_UTF8: diff --git a/dlls/dnsapi/record.c b/dlls/dnsapi/record.c index 51d9e8fd2d7..4697438df57 100644 --- a/dlls/dnsapi/record.c +++ b/dlls/dnsapi/record.c @@ -2,7 +2,7 @@ * DNS support * * Copyright (C) 2006 Hans Leidekker - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -18,31 +18,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "config.h" -#include "wine/port.h" -#include "wine/debug.h" -#include "wine/unicode.h" - #include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <sys/types.h> - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_NAMESER_H -# include <arpa/nameser.h> -#endif -#ifdef HAVE_RESOLV_H -# include <resolv.h> -#endif - #include "windef.h" #include "winbase.h" #include "winnls.h" #include "windns.h"
+#include "wine/debug.h" +#include "wine/unicode.h" #include "dnsapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(dnsapi); @@ -158,10 +141,8 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) r1->Data.SOA.dwExpire != r2->Data.SOA.dwExpire || r1->Data.SOA.dwDefaultTtl != r2->Data.SOA.dwDefaultTtl) return FALSE; - if (strcmpX( r1->Data.SOA.pNamePrimaryServer, - r2->Data.SOA.pNamePrimaryServer, wide ) || - strcmpX( r1->Data.SOA.pNameAdministrator, - r2->Data.SOA.pNameAdministrator, wide )) + if (strcmpX( r1->Data.SOA.pNamePrimaryServer, r2->Data.SOA.pNamePrimaryServer, wide ) || + strcmpX( r1->Data.SOA.pNameAdministrator, r2->Data.SOA.pNameAdministrator, wide )) return FALSE; break; } @@ -174,17 +155,14 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) case DNS_TYPE_MG: case DNS_TYPE_MR: { - if (strcmpX( r1->Data.PTR.pNameHost, - r2->Data.PTR.pNameHost, wide )) return FALSE; + if (strcmpX( r1->Data.PTR.pNameHost, r2->Data.PTR.pNameHost, wide )) return FALSE; break; } case DNS_TYPE_MINFO: case DNS_TYPE_RP: { - if (strcmpX( r1->Data.MINFO.pNameMailbox, - r2->Data.MINFO.pNameMailbox, wide ) || - strcmpX( r1->Data.MINFO.pNameErrorsMailbox, - r2->Data.MINFO.pNameErrorsMailbox, wide )) + if (strcmpX( r1->Data.MINFO.pNameMailbox, r2->Data.MINFO.pNameMailbox, wide ) || + strcmpX( r1->Data.MINFO.pNameErrorsMailbox, r2->Data.MINFO.pNameErrorsMailbox, wide )) return FALSE; break; } @@ -194,8 +172,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) { if (r1->Data.MX.wPreference != r2->Data.MX.wPreference) return FALSE; - if (strcmpX( r1->Data.MX.pNameExchange, - r2->Data.MX.pNameExchange, wide )) + if (strcmpX( r1->Data.MX.pNameExchange, r2->Data.MX.pNameExchange, wide )) return FALSE; break; } @@ -208,8 +185,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) return FALSE; for (i = 0; i < r1->Data.TXT.dwStringCount; i++) { - if (strcmpX( r1->Data.TXT.pStringArray[i], - r2->Data.TXT.pStringArray[i], wide )) + if (strcmpX( r1->Data.TXT.pStringArray[i], r2->Data.TXT.pStringArray[i], wide )) return FALSE; } break; @@ -255,8 +231,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) } case DNS_TYPE_SIG: { - if (strcmpX( r1->Data.SIG.pNameSigner, - r2->Data.SIG.pNameSigner, wide )) + if (strcmpX( r1->Data.SIG.pNameSigner, r2->Data.SIG.pNameSigner, wide )) return FALSE; if (r1->Data.SIG.wTypeCovered != r2->Data.SIG.wTypeCovered || r1->Data.SIG.chAlgorithm != r2->Data.SIG.chAlgorithm || @@ -284,8 +259,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) } case DNS_TYPE_NXT: { - if (strcmpX( r1->Data.NXT.pNameNext, - r2->Data.NXT.pNameNext, wide )) return FALSE; + if (strcmpX( r1->Data.NXT.pNameNext, r2->Data.NXT.pNameNext, wide )) return FALSE; if (r1->Data.NXT.wNumTypes != r2->Data.NXT.wNumTypes) return FALSE; if (memcmp( r1->Data.NXT.wTypes, r2->Data.NXT.wTypes, r1->wDataLength - sizeof(DNS_NXT_DATAA) + sizeof(WORD) )) @@ -294,8 +268,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) } case DNS_TYPE_SRV: { - if (strcmpX( r1->Data.SRV.pNameTarget, - r2->Data.SRV.pNameTarget, wide )) return FALSE; + if (strcmpX( r1->Data.SRV.pNameTarget, r2->Data.SRV.pNameTarget, wide )) return FALSE; if (r1->Data.SRV.wPriority != r2->Data.SRV.wPriority || r1->Data.SRV.wWeight != r2->Data.SRV.wWeight || r1->Data.SRV.wPort != r2->Data.SRV.wPort) @@ -304,8 +277,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) } case DNS_TYPE_TKEY: { - if (strcmpX( r1->Data.TKEY.pNameAlgorithm, - r2->Data.TKEY.pNameAlgorithm, wide )) + if (strcmpX( r1->Data.TKEY.pNameAlgorithm, r2->Data.TKEY.pNameAlgorithm, wide )) return FALSE; if (r1->Data.TKEY.dwCreateTime != r2->Data.TKEY.dwCreateTime || r1->Data.TKEY.dwExpireTime != r2->Data.TKEY.dwExpireTime || @@ -326,8 +298,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) } case DNS_TYPE_TSIG: { - if (strcmpX( r1->Data.TSIG.pNameAlgorithm, - r2->Data.TSIG.pNameAlgorithm, wide )) + if (strcmpX( r1->Data.TSIG.pNameAlgorithm, r2->Data.TSIG.pNameAlgorithm, wide )) return FALSE; if (r1->Data.TSIG.i64CreateTime != r2->Data.TSIG.i64CreateTime || r1->Data.TSIG.wFudgeTime != r2->Data.TSIG.wFudgeTime || @@ -364,8 +335,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) r1->Data.WINSR.dwLookupTimeout != r2->Data.WINSR.dwLookupTimeout || r1->Data.WINSR.dwCacheTimeout != r2->Data.WINSR.dwCacheTimeout) return FALSE; - if (strcmpX( r1->Data.WINSR.pNameResultDomain, - r2->Data.WINSR.pNameResultDomain, wide )) + if (strcmpX( r1->Data.WINSR.pNameResultDomain, r2->Data.WINSR.pNameResultDomain, wide )) return FALSE; break; } @@ -748,7 +718,7 @@ BOOL WINAPI DnsRecordSetCompare( PDNS_RECORD set1, PDNS_RECORD set2,
DNS_RRSET_TERMINATE( rr1 ); DNS_RRSET_TERMINATE( rr2 ); - + if (diff1) *diff1 = rr1.pFirstRR; else DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList );
@@ -763,7 +733,7 @@ error:
DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList ); DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList ); - + return FALSE; }