2 * Copyright 2020 Dmitry Timoshkov
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/test.h"
32 #define NS_MAXDNAME 1025
34 static void test_DnsQuery(void)
36 WCHAR domain
[MAX_PATH
];
37 WCHAR name
[NS_MAXDNAME
];
39 DNS_RECORDW
*rec
, *ptr
;
44 status
= DnsQuery_W(L
"winehq.org", DNS_TYPE_A
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
45 if (status
== ERROR_TIMEOUT
)
47 skip("query timed out\n");
50 ok(status
== ERROR_SUCCESS
, "got %ld\n", status
);
51 DnsRecordListFree(rec
, DnsFreeRecordList
);
53 /* Show that DNS_TYPE_A returns CNAMEs too */
55 wcscpy(domain
, L
"test.winehq.org"); /* should be a CNAME */
56 status
= DnsQuery_W(domain
, DNS_TYPE_A
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
57 if (status
== ERROR_TIMEOUT
)
59 skip("query timed out\n");
62 ok(status
== ERROR_SUCCESS
, "got %ld\n", status
);
63 type
= DNS_TYPE_CNAME
; /* CNAMEs come first */
64 for (ptr
= rec
; ptr
; ptr
= ptr
->pNext
)
66 ok(!wcscmp(domain
, ptr
->pName
), "expected record name %s, got %s\n", wine_dbgstr_w(domain
), wine_dbgstr_w(ptr
->pName
));
67 ok(type
== ptr
->wType
, "expected record type %d, got %d\n", type
, ptr
->wType
);
68 if (ptr
->wType
== DNS_TYPE_CNAME
)
70 /* CNAME chains are bad practice so assume A for the remainder */
72 wcscpy(domain
, L
"winehq.org");
73 ok(!wcscmp(domain
, ptr
->Data
.CNAME
.pNameHost
), "expected CNAME target %s, got %s\n", wine_dbgstr_w(domain
), wine_dbgstr_w(ptr
->Data
.CNAME
.pNameHost
));
76 DnsRecordListFree(rec
, DnsFreeRecordList
);
78 /* But DNS_TYPE_CNAME does not return A records! */
80 wcscpy(domain
, L
"test.winehq.org");
81 status
= DnsQuery_W(L
"test.winehq.org", DNS_TYPE_CNAME
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
82 if (status
== ERROR_TIMEOUT
)
84 skip("query timed out\n");
87 ok(status
== ERROR_SUCCESS
, "got %ld\n", status
);
89 ok(!wcscmp(domain
, ptr
->pName
), "expected record name %s, got %s\n", wine_dbgstr_w(domain
), wine_dbgstr_w(ptr
->pName
));
90 ok(DNS_TYPE_CNAME
== ptr
->wType
, "expected record type %d, got %d\n", DNS_TYPE_CNAME
, ptr
->wType
);
91 if (ptr
->wType
== DNS_TYPE_CNAME
)
93 wcscpy(domain
, L
"winehq.org");
94 ok(!wcscmp(domain
, ptr
->Data
.CNAME
.pNameHost
), "expected CNAME target %s, got %s\n", wine_dbgstr_w(domain
), wine_dbgstr_w(ptr
->Data
.CNAME
.pNameHost
));
96 ok(ptr
->pNext
== NULL
, "unexpected CNAME chain\n");
97 DnsRecordListFree(rec
, DnsFreeRecordList
);
99 status
= DnsQuery_W(L
"", DNS_TYPE_SRV
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
100 ok(status
== DNS_ERROR_RCODE_NAME_ERROR
|| status
== DNS_INFO_NO_RECORDS
|| status
== ERROR_INVALID_NAME
/* XP */,
101 "got %ld\n", status
);
103 wcscpy(domain
, L
"_ldap._tcp.deadbeef");
104 status
= DnsQuery_W(domain
, DNS_TYPE_SRV
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
105 ok(status
== DNS_ERROR_RCODE_NAME_ERROR
|| status
== DNS_INFO_NO_RECORDS
|| status
== ERROR_INVALID_NAME
/* XP */,
106 "got %ld\n", status
);
108 wcscpy(domain
, L
"_ldap._tcp.dc._msdcs.");
109 size
= ARRAY_SIZE(domain
) - wcslen(domain
);
110 ret
= GetComputerNameExW(ComputerNameDnsDomain
, domain
+ wcslen(domain
), &size
);
111 ok(ret
, "GetComputerNameEx error %lu\n", GetLastError());
114 skip("computer is not in a domain\n");
118 status
= DnsQuery_W(domain
, DNS_TYPE_SRV
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
119 trace("DnsQuery_W(%s) => %ld\n", wine_dbgstr_w(domain
), status
);
120 if (status
!= ERROR_SUCCESS
)
122 skip("domain %s doesn't have an SRV entry\n", wine_dbgstr_w(domain
));
126 trace("target %s, port %d\n", wine_dbgstr_w(rec
->Data
.Srv
.pNameTarget
), rec
->Data
.Srv
.wPort
);
128 lstrcpynW(name
, rec
->Data
.Srv
.pNameTarget
, ARRAY_SIZE(name
));
129 DnsRecordListFree(rec
, DnsFreeRecordList
);
132 status
= DnsQuery_W(name
, DNS_TYPE_A
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
133 ok(status
== ERROR_SUCCESS
|| status
== DNS_ERROR_RCODE_NAME_ERROR
, "DnsQuery_W(%s) => %ld\n",
134 wine_dbgstr_w(name
), status
);
135 if (status
== ERROR_SUCCESS
)
138 WCHAR buf
[IP4_ADDRESS_STRING_LENGTH
];
140 addr
.sin_family
= AF_INET
;
142 addr
.sin_addr
.s_addr
= rec
->Data
.A
.IpAddress
;
144 ret
= WSAAddressToStringW((SOCKADDR
*)&addr
, sizeof(addr
), NULL
, buf
, &size
);
145 ok(!ret
, "WSAAddressToStringW error %lu\n", ret
);
146 trace("WSAAddressToStringW => %s\n", wine_dbgstr_w(buf
));
148 DnsRecordListFree(rec
, DnsFreeRecordList
);
152 status
= DnsQuery_W(name
, DNS_TYPE_AAAA
, DNS_QUERY_STANDARD
, NULL
, &rec
, NULL
);
153 ok(status
== ERROR_SUCCESS
|| status
== DNS_ERROR_RCODE_NAME_ERROR
, "DnsQuery_W(%s) => %ld\n",
154 wine_dbgstr_w(name
), status
);
155 if (status
== ERROR_SUCCESS
)
158 WCHAR buf
[IP6_ADDRESS_STRING_LENGTH
];
160 addr
.sin6_family
= AF_INET6
;
162 addr
.sin6_scope_id
= 0;
163 memcpy(addr
.sin6_addr
.s6_addr
, &rec
->Data
.AAAA
.Ip6Address
, sizeof(rec
->Data
.AAAA
.Ip6Address
));
165 ret
= WSAAddressToStringW((SOCKADDR
*)&addr
, sizeof(addr
), NULL
, buf
, &size
);
166 ok(!ret
, "WSAAddressToStringW error %lu\n", ret
);
167 trace("WSAAddressToStringW => %s\n", wine_dbgstr_w(buf
));
169 DnsRecordListFree(rec
, DnsFreeRecordList
);
173 static IP_ADAPTER_ADDRESSES
*get_adapters(void)
175 ULONG err
, size
= 1024;
176 IP_ADAPTER_ADDRESSES
*ret
= malloc( size
);
179 err
= GetAdaptersAddresses( AF_UNSPEC
, GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
|
180 GAA_FLAG_SKIP_FRIENDLY_NAME
,
182 if (err
!= ERROR_BUFFER_OVERFLOW
) break;
183 ret
= realloc( ret
, size
);
185 if (err
== ERROR_SUCCESS
) return ret
;
190 static void test_DnsQueryConfig( void )
193 DWORD size
, i
, ipv6_count
;
194 WCHAR name
[MAX_ADAPTER_NAME_LENGTH
+ 1];
195 IP_ADAPTER_ADDRESSES
*adapters
, *ptr
;
196 DNS_ADDR_ARRAY
*ipv4
, *ipv6
, *unspec
;
197 IP4_ARRAY
*ip4_array
;
199 if (!(adapters
= get_adapters())) return;
201 for (ptr
= adapters
; ptr
; ptr
= ptr
->Next
)
203 MultiByteToWideChar( CP_ACP
, 0, ptr
->AdapterName
, -1, name
, ARRAY_SIZE(name
) );
204 if (ptr
->IfType
== IF_TYPE_SOFTWARE_LOOPBACK
) continue;
207 err
= DnsQueryConfig( DnsConfigDnsServersIpv4
, 0, name
, NULL
, NULL
, &size
);
209 ipv4
= malloc( size
);
211 err
= DnsQueryConfig( DnsConfigDnsServersIpv4
, 0, name
, NULL
, ipv4
, &size
);
212 ok( err
== ERROR_MORE_DATA
, "got %ld\n", err
);
214 err
= DnsQueryConfig( DnsConfigDnsServersIpv4
, 0, name
, NULL
, ipv4
, &size
);
215 ok( !err
, "got %ld\n", err
);
217 ok( ipv4
->AddrCount
== ipv4
->MaxCount
, "got %lu vs %lu\n", ipv4
->AddrCount
, ipv4
->MaxCount
);
218 ok( !ipv4
->Tag
, "got %#lx\n", ipv4
->Tag
);
219 ok( !ipv4
->Family
, "got %d\n", ipv4
->Family
);
220 ok( !ipv4
->WordReserved
, "got %#x\n", ipv4
->WordReserved
);
221 ok( !ipv4
->Flags
, "got %#lx\n", ipv4
->Flags
);
222 ok( !ipv4
->MatchFlag
, "got %#lx\n", ipv4
->MatchFlag
);
223 ok( !ipv4
->Reserved1
, "got %#lx\n", ipv4
->Reserved1
);
224 ok( !ipv4
->Reserved2
, "got %#lx\n", ipv4
->Reserved2
);
227 err
= DnsQueryConfig( DnsConfigDnsServerList
, 0, name
, NULL
, NULL
, &size
);
228 ok( !err
, "got %ld\n", err
);
229 ip4_array
= malloc( size
);
230 err
= DnsQueryConfig( DnsConfigDnsServerList
, 0, name
, NULL
, ip4_array
, &size
);
231 ok( !err
, "got %ld\n", err
);
233 ok( ipv4
->AddrCount
== ip4_array
->AddrCount
, "got %lu vs %lu\n", ipv4
->AddrCount
, ip4_array
->AddrCount
);
235 for (i
= 0; i
< ipv4
->AddrCount
; i
++)
237 SOCKADDR_IN
*sa
= (SOCKADDR_IN
*)ipv4
->AddrArray
[i
].MaxSa
;
239 ok( sa
->sin_family
== AF_INET
, "got %d\n", sa
->sin_family
);
240 ok( sa
->sin_addr
.s_addr
== ip4_array
->AddrArray
[i
], "got %#lx vs %#lx\n",
241 sa
->sin_addr
.s_addr
, ip4_array
->AddrArray
[i
] );
242 ok( ipv4
->AddrArray
[i
].Data
.DnsAddrUserDword
[0] == sizeof(*sa
), "got %lu\n",
243 ipv4
->AddrArray
[i
].Data
.DnsAddrUserDword
[0] );
247 err
= DnsQueryConfig( DnsConfigDnsServersIpv6
, 0, name
, NULL
, NULL
, &size
);
248 ok( !err
|| err
== DNS_ERROR_NO_DNS_SERVERS
, "got %ld\n", err
);
253 ipv6
= malloc( size
);
254 err
= DnsQueryConfig( DnsConfigDnsServersIpv6
, 0, name
, NULL
, ipv6
, &size
);
255 ok( !err
, "got %ld\n", err
);
256 ipv6_count
= ipv6
->AddrCount
;
260 err
= DnsQueryConfig( DnsConfigDnsServersUnspec
, 0, name
, NULL
, NULL
, &size
);
261 ok( !err
, "got %ld\n", err
);
262 unspec
= malloc( size
);
263 err
= DnsQueryConfig( DnsConfigDnsServersUnspec
, 0, name
, NULL
, unspec
, &size
);
264 ok( !err
, "got %ld\n", err
);
266 ok( unspec
->AddrCount
== ipv4
->AddrCount
+ ipv6_count
, "got %lu vs %lu + %lu\n",
267 unspec
->AddrCount
, ipv4
->AddrCount
, ipv6_count
);
282 WSAStartup(MAKEWORD(2, 2), &data
);
285 test_DnsQueryConfig();