Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : dsgetdcname
5 :
6 : Copyright (C) Gerald Carter 2006
7 : Copyright (C) Guenther Deschner 2007-2008
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "libsmb/dsgetdcname.h"
25 : #include "libsmb/namequery.h"
26 : #include "libads/sitename_cache.h"
27 : #include "../librpc/gen_ndr/ndr_netlogon.h"
28 : #include "libads/cldap.h"
29 : #include "lib/addns/dnsquery_srv.h"
30 : #include "libsmb/clidgram.h"
31 : #include "lib/gencache.h"
32 : #include "lib/util/util_net.h"
33 :
34 : /* 15 minutes */
35 : #define DSGETDCNAME_CACHE_TTL 60*15
36 :
37 : struct ip_service_name {
38 : struct samba_sockaddr sa;
39 : const char *hostname;
40 : };
41 :
42 : static NTSTATUS make_dc_info_from_cldap_reply(
43 : TALLOC_CTX *mem_ctx,
44 : uint32_t flags,
45 : const struct samba_sockaddr *sa,
46 : struct NETLOGON_SAM_LOGON_RESPONSE_EX *r,
47 : struct netr_DsRGetDCNameInfo **info);
48 :
49 : /****************************************************************
50 : ****************************************************************/
51 :
52 41 : static void debug_dsdcinfo_flags(int lvl, uint32_t flags)
53 : {
54 41 : DEBUG(lvl,("debug_dsdcinfo_flags: 0x%08x\n\t", flags));
55 :
56 41 : if (flags & DS_FORCE_REDISCOVERY)
57 33 : DEBUGADD(lvl,("DS_FORCE_REDISCOVERY "));
58 41 : if (flags & 0x000000002)
59 0 : DEBUGADD(lvl,("0x00000002 "));
60 41 : if (flags & 0x000000004)
61 0 : DEBUGADD(lvl,("0x00000004 "));
62 41 : if (flags & 0x000000008)
63 0 : DEBUGADD(lvl,("0x00000008 "));
64 41 : if (flags & DS_DIRECTORY_SERVICE_REQUIRED)
65 32 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_REQUIRED "));
66 41 : if (flags & DS_DIRECTORY_SERVICE_PREFERRED)
67 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_PREFERRED "));
68 41 : if (flags & DS_GC_SERVER_REQUIRED)
69 0 : DEBUGADD(lvl,("DS_GC_SERVER_REQUIRED "));
70 41 : if (flags & DS_PDC_REQUIRED)
71 0 : DEBUGADD(lvl,("DS_PDC_REQUIRED "));
72 41 : if (flags & DS_BACKGROUND_ONLY)
73 0 : DEBUGADD(lvl,("DS_BACKGROUND_ONLY "));
74 41 : if (flags & DS_IP_REQUIRED)
75 0 : DEBUGADD(lvl,("DS_IP_REQUIRED "));
76 41 : if (flags & DS_KDC_REQUIRED)
77 0 : DEBUGADD(lvl,("DS_KDC_REQUIRED "));
78 41 : if (flags & DS_TIMESERV_REQUIRED)
79 0 : DEBUGADD(lvl,("DS_TIMESERV_REQUIRED "));
80 41 : if (flags & DS_WRITABLE_REQUIRED)
81 32 : DEBUGADD(lvl,("DS_WRITABLE_REQUIRED "));
82 41 : if (flags & DS_GOOD_TIMESERV_PREFERRED)
83 0 : DEBUGADD(lvl,("DS_GOOD_TIMESERV_PREFERRED "));
84 41 : if (flags & DS_AVOID_SELF)
85 0 : DEBUGADD(lvl,("DS_AVOID_SELF "));
86 41 : if (flags & DS_ONLY_LDAP_NEEDED)
87 0 : DEBUGADD(lvl,("DS_ONLY_LDAP_NEEDED "));
88 41 : if (flags & DS_IS_FLAT_NAME)
89 2 : DEBUGADD(lvl,("DS_IS_FLAT_NAME "));
90 41 : if (flags & DS_IS_DNS_NAME)
91 28 : DEBUGADD(lvl,("DS_IS_DNS_NAME "));
92 41 : if (flags & DS_TRY_NEXTCLOSEST_SITE)
93 0 : DEBUGADD(lvl,("DS_TRY_NEXTCLOSEST_SITE "));
94 41 : if (flags & DS_DIRECTORY_SERVICE_6_REQUIRED)
95 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_6_REQUIRED "));
96 41 : if (flags & DS_WEB_SERVICE_REQUIRED)
97 0 : DEBUGADD(lvl,("DS_WEB_SERVICE_REQUIRED "));
98 41 : if (flags & DS_DIRECTORY_SERVICE_8_REQUIRED)
99 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_8_REQUIRED "));
100 41 : if (flags & DS_DIRECTORY_SERVICE_9_REQUIRED)
101 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_9_REQUIRED "));
102 41 : if (flags & DS_DIRECTORY_SERVICE_10_REQUIRED)
103 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_10_REQUIRED "));
104 41 : if (flags & 0x01000000)
105 0 : DEBUGADD(lvl,("0x01000000 "));
106 41 : if (flags & 0x02000000)
107 0 : DEBUGADD(lvl,("0x02000000 "));
108 41 : if (flags & 0x04000000)
109 0 : DEBUGADD(lvl,("0x04000000 "));
110 41 : if (flags & 0x08000000)
111 0 : DEBUGADD(lvl,("0x08000000 "));
112 41 : if (flags & 0x10000000)
113 0 : DEBUGADD(lvl,("0x10000000 "));
114 41 : if (flags & 0x20000000)
115 0 : DEBUGADD(lvl,("0x20000000 "));
116 41 : if (flags & DS_RETURN_DNS_NAME)
117 41 : DEBUGADD(lvl,("DS_RETURN_DNS_NAME "));
118 41 : if (flags & DS_RETURN_FLAT_NAME)
119 0 : DEBUGADD(lvl,("DS_RETURN_FLAT_NAME "));
120 41 : if (flags)
121 41 : DEBUGADD(lvl,("\n"));
122 41 : }
123 :
124 : /****************************************************************
125 : ****************************************************************/
126 :
127 57 : static char *dsgetdcname_cache_key(TALLOC_CTX *mem_ctx, const char *domain)
128 : {
129 57 : if (!domain) {
130 0 : return NULL;
131 : }
132 :
133 57 : return talloc_asprintf_strupper_m(mem_ctx, "DSGETDCNAME/DOMAIN/%s",
134 : domain);
135 : }
136 :
137 : /****************************************************************
138 : ****************************************************************/
139 :
140 0 : static NTSTATUS dsgetdcname_cache_delete(TALLOC_CTX *mem_ctx,
141 : const char *domain_name)
142 : {
143 : char *key;
144 :
145 0 : key = dsgetdcname_cache_key(mem_ctx, domain_name);
146 0 : if (!key) {
147 0 : return NT_STATUS_NO_MEMORY;
148 : }
149 :
150 0 : if (!gencache_del(key)) {
151 0 : return NT_STATUS_UNSUCCESSFUL;
152 : }
153 :
154 0 : return NT_STATUS_OK;
155 : }
156 :
157 : /****************************************************************
158 : ****************************************************************/
159 :
160 49 : static NTSTATUS dsgetdcname_cache_store(TALLOC_CTX *mem_ctx,
161 : const char *domain_name,
162 : DATA_BLOB blob)
163 : {
164 : time_t expire_time;
165 : char *key;
166 49 : bool ret = false;
167 :
168 49 : key = dsgetdcname_cache_key(mem_ctx, domain_name);
169 49 : if (!key) {
170 0 : return NT_STATUS_NO_MEMORY;
171 : }
172 :
173 49 : expire_time = time(NULL) + DSGETDCNAME_CACHE_TTL;
174 :
175 49 : ret = gencache_set_data_blob(key, blob, expire_time);
176 :
177 49 : return ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
178 : }
179 :
180 : /****************************************************************
181 : ****************************************************************/
182 :
183 25 : static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
184 : uint32_t flags,
185 : struct samba_sockaddr *sa,
186 : uint32_t nt_version,
187 : struct NETLOGON_SAM_LOGON_RESPONSE_EX *r)
188 : {
189 : DATA_BLOB blob;
190 : enum ndr_err_code ndr_err;
191 : NTSTATUS status;
192 : char addr[INET6_ADDRSTRLEN];
193 :
194 25 : print_sockaddr(addr, sizeof(addr), &sa->u.ss);
195 :
196 : /* FIXME */
197 25 : r->sockaddr_size = 0x10; /* the w32 winsock addr size */
198 25 : r->sockaddr.sockaddr_family = 2; /* AF_INET */
199 25 : r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
200 :
201 25 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
202 : (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX);
203 25 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
204 0 : return ndr_map_error2ntstatus(ndr_err);
205 : }
206 :
207 25 : if (r->domain_name) {
208 25 : status = dsgetdcname_cache_store(mem_ctx, r->domain_name,
209 : blob);
210 25 : if (!NT_STATUS_IS_OK(status)) {
211 0 : goto done;
212 : }
213 25 : if (r->client_site) {
214 24 : sitename_store(r->domain_name, r->client_site);
215 : }
216 : }
217 25 : if (r->dns_domain) {
218 24 : status = dsgetdcname_cache_store(mem_ctx, r->dns_domain, blob);
219 24 : if (!NT_STATUS_IS_OK(status)) {
220 0 : goto done;
221 : }
222 24 : if (r->client_site) {
223 24 : sitename_store(r->dns_domain, r->client_site);
224 : }
225 : }
226 :
227 25 : status = NT_STATUS_OK;
228 :
229 25 : done:
230 25 : data_blob_free(&blob);
231 :
232 25 : return status;
233 : }
234 :
235 : /****************************************************************
236 : ****************************************************************/
237 :
238 24 : static uint32_t get_cldap_reply_server_flags(struct netlogon_samlogon_response *r,
239 : uint32_t nt_version)
240 : {
241 24 : switch (nt_version & 0x0000001f) {
242 0 : case 0:
243 : case 1:
244 : case 16:
245 : case 17:
246 0 : return 0;
247 0 : case 2:
248 : case 3:
249 : case 18:
250 : case 19:
251 0 : return r->data.nt5.server_type;
252 24 : case 4:
253 : case 5:
254 : case 6:
255 : case 7:
256 24 : return r->data.nt5_ex.server_type;
257 0 : case 8:
258 : case 9:
259 : case 10:
260 : case 11:
261 : case 12:
262 : case 13:
263 : case 14:
264 : case 15:
265 0 : return r->data.nt5_ex.server_type;
266 0 : case 20:
267 : case 21:
268 : case 22:
269 : case 23:
270 : case 24:
271 : case 25:
272 : case 26:
273 : case 27:
274 : case 28:
275 0 : return r->data.nt5_ex.server_type;
276 0 : case 29:
277 : case 30:
278 : case 31:
279 0 : return r->data.nt5_ex.server_type;
280 0 : default:
281 0 : return 0;
282 : }
283 : }
284 :
285 : /****************************************************************
286 : ****************************************************************/
287 :
288 8 : static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
289 : const char *domain_name,
290 : const struct GUID *domain_guid,
291 : uint32_t flags,
292 : struct netr_DsRGetDCNameInfo **info_p)
293 : {
294 : char *key;
295 : DATA_BLOB blob;
296 : enum ndr_err_code ndr_err;
297 : struct netr_DsRGetDCNameInfo *info;
298 : struct NETLOGON_SAM_LOGON_RESPONSE_EX r;
299 : NTSTATUS status;
300 :
301 8 : key = dsgetdcname_cache_key(mem_ctx, domain_name);
302 8 : if (!key) {
303 0 : return NT_STATUS_NO_MEMORY;
304 : }
305 :
306 8 : if (!gencache_get_data_blob(key, NULL, &blob, NULL, NULL)) {
307 1 : return NT_STATUS_NOT_FOUND;
308 : }
309 :
310 7 : info = talloc_zero(mem_ctx, struct netr_DsRGetDCNameInfo);
311 7 : if (!info) {
312 0 : data_blob_free(&blob);
313 0 : return NT_STATUS_NO_MEMORY;
314 : }
315 :
316 7 : ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
317 : (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX);
318 :
319 7 : data_blob_free(&blob);
320 7 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
321 0 : dsgetdcname_cache_delete(mem_ctx, domain_name);
322 0 : return ndr_map_error2ntstatus(ndr_err);
323 : }
324 :
325 7 : status = make_dc_info_from_cldap_reply(mem_ctx, flags, NULL,
326 : &r, &info);
327 7 : if (!NT_STATUS_IS_OK(status)) {
328 0 : return status;
329 : }
330 :
331 7 : if (DEBUGLEVEL >= 10) {
332 0 : NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, info);
333 : }
334 :
335 : /* check flags */
336 7 : if (!check_cldap_reply_required_flags(info->dc_flags, flags)) {
337 0 : DEBUG(10,("invalid flags\n"));
338 0 : return NT_STATUS_INVALID_PARAMETER;
339 : }
340 :
341 7 : if ((flags & DS_IP_REQUIRED) &&
342 0 : (info->dc_address_type != DS_ADDRESS_TYPE_INET)) {
343 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
344 : }
345 :
346 7 : *info_p = info;
347 :
348 7 : return NT_STATUS_OK;
349 : }
350 :
351 : /****************************************************************
352 : ****************************************************************/
353 :
354 8 : static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx,
355 : struct messaging_context *msg_ctx,
356 : const char *domain_name,
357 : const struct GUID *domain_guid,
358 : uint32_t flags,
359 : const char *site_name,
360 : struct netr_DsRGetDCNameInfo **info)
361 : {
362 : NTSTATUS status;
363 :
364 8 : status = dsgetdcname_cache_fetch(mem_ctx, domain_name, domain_guid,
365 : flags, info);
366 8 : if (!NT_STATUS_IS_OK(status)
367 1 : && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
368 0 : DEBUG(10,("dsgetdcname_cached: cache fetch failed with: %s\n",
369 : nt_errstr(status)));
370 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
371 : }
372 :
373 8 : if (flags & DS_BACKGROUND_ONLY) {
374 0 : return status;
375 : }
376 :
377 8 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
378 : struct netr_DsRGetDCNameInfo *dc_info;
379 :
380 1 : status = dsgetdcname(mem_ctx, msg_ctx, domain_name,
381 : domain_guid, site_name,
382 : flags | DS_FORCE_REDISCOVERY,
383 : &dc_info);
384 :
385 1 : if (!NT_STATUS_IS_OK(status)) {
386 0 : return status;
387 : }
388 :
389 1 : *info = dc_info;
390 : }
391 :
392 8 : return status;
393 : }
394 :
395 : /****************************************************************
396 : ****************************************************************/
397 :
398 41 : static bool check_allowed_required_flags(uint32_t flags,
399 : const char *site_name)
400 : {
401 41 : uint32_t return_type = flags & (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME);
402 41 : uint32_t offered_type = flags & (DS_IS_FLAT_NAME|DS_IS_DNS_NAME);
403 41 : uint32_t query_type = flags & (DS_BACKGROUND_ONLY|DS_FORCE_REDISCOVERY);
404 :
405 : /* FIXME: check for DSGETDC_VALID_FLAGS and check for excluse bits
406 : * (DS_PDC_REQUIRED, DS_KDC_REQUIRED, DS_GC_SERVER_REQUIRED) */
407 :
408 41 : debug_dsdcinfo_flags(10, flags);
409 :
410 41 : if ((flags & DS_TRY_NEXTCLOSEST_SITE) && site_name) {
411 0 : return false;
412 : }
413 :
414 41 : if (return_type == (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME)) {
415 0 : return false;
416 : }
417 :
418 41 : if (offered_type == (DS_IS_DNS_NAME|DS_IS_FLAT_NAME)) {
419 0 : return false;
420 : }
421 :
422 41 : if (query_type == (DS_BACKGROUND_ONLY|DS_FORCE_REDISCOVERY)) {
423 0 : return false;
424 : }
425 :
426 : #if 0
427 : if ((flags & DS_RETURN_DNS_NAME) && (!(flags & DS_IP_REQUIRED))) {
428 : printf("gd: here5 \n");
429 : return false;
430 : }
431 : #endif
432 41 : return true;
433 : }
434 :
435 : /****************************************************************
436 : ****************************************************************/
437 :
438 5 : static NTSTATUS discover_dc_netbios(TALLOC_CTX *mem_ctx,
439 : const char *domain_name,
440 : uint32_t flags,
441 : struct ip_service_name **returned_dclist,
442 : size_t *returned_count)
443 : {
444 : NTSTATUS status;
445 5 : enum nbt_name_type name_type = NBT_NAME_LOGON;
446 5 : struct samba_sockaddr *salist = NULL;
447 : size_t i;
448 5 : struct ip_service_name *dclist = NULL;
449 5 : size_t count = 0;
450 : static const char *resolve_order[] = { "lmhosts", "wins", "bcast", NULL };
451 :
452 5 : if (flags & DS_PDC_REQUIRED) {
453 0 : name_type = NBT_NAME_PDC;
454 : }
455 :
456 5 : status = internal_resolve_name(mem_ctx,
457 : domain_name,
458 : name_type,
459 : NULL,
460 : &salist,
461 : &count,
462 : resolve_order);
463 5 : if (!NT_STATUS_IS_OK(status)) {
464 0 : DEBUG(10,("discover_dc_netbios: failed to find DC\n"));
465 0 : return status;
466 : }
467 :
468 5 : dclist = talloc_zero_array(mem_ctx, struct ip_service_name, count);
469 5 : if (!dclist) {
470 0 : TALLOC_FREE(salist);
471 0 : return NT_STATUS_NO_MEMORY;
472 : }
473 :
474 10 : for (i=0; i<count; i++) {
475 : char addr[INET6_ADDRSTRLEN];
476 5 : struct ip_service_name *r = &dclist[i];
477 :
478 5 : print_sockaddr(addr, sizeof(addr),
479 5 : &salist[i].u.ss);
480 :
481 5 : r->sa = salist[i];
482 5 : r->hostname = talloc_strdup(mem_ctx, addr);
483 5 : if (!r->hostname) {
484 0 : TALLOC_FREE(salist);
485 0 : TALLOC_FREE(dclist);
486 0 : return NT_STATUS_NO_MEMORY;
487 : }
488 :
489 : }
490 :
491 5 : TALLOC_FREE(salist);
492 :
493 5 : *returned_dclist = dclist;
494 5 : *returned_count = count;
495 :
496 5 : return NT_STATUS_OK;
497 : }
498 :
499 : /****************************************************************
500 : ****************************************************************/
501 :
502 31 : static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
503 : const char *domain_name,
504 : const struct GUID *domain_guid,
505 : uint32_t flags,
506 : const char *site_name,
507 : struct ip_service_name **returned_dclist,
508 : size_t *return_count)
509 : {
510 : size_t i;
511 : NTSTATUS status;
512 31 : struct dns_rr_srv *dcs = NULL;
513 31 : size_t numdcs = 0;
514 31 : struct ip_service_name *dclist = NULL;
515 31 : size_t ret_count = 0;
516 31 : char *query = NULL;
517 :
518 31 : if (flags & DS_PDC_REQUIRED) {
519 0 : query = ads_dns_query_string_pdc(mem_ctx, domain_name);
520 31 : } else if (flags & DS_GC_SERVER_REQUIRED) {
521 0 : query = ads_dns_query_string_gcs(mem_ctx, domain_name);
522 31 : } else if (flags & DS_KDC_REQUIRED) {
523 0 : query = ads_dns_query_string_kdcs(mem_ctx, domain_name);
524 31 : } else if (flags & DS_DIRECTORY_SERVICE_REQUIRED) {
525 30 : query = ads_dns_query_string_dcs(mem_ctx, domain_name);
526 1 : } else if (domain_guid) {
527 0 : query = ads_dns_query_string_dcs_guid(
528 : mem_ctx, domain_guid, domain_name);
529 : } else {
530 1 : query = ads_dns_query_string_dcs(mem_ctx, domain_name);
531 : }
532 :
533 31 : if (query == NULL) {
534 0 : return NT_STATUS_NO_MEMORY;
535 : }
536 :
537 31 : status = ads_dns_query_srv(
538 : mem_ctx,
539 : lp_get_async_dns_timeout(),
540 : site_name,
541 : query,
542 : &dcs,
543 : &numdcs);
544 31 : TALLOC_FREE(query);
545 31 : if (!NT_STATUS_IS_OK(status)) {
546 3 : return status;
547 : }
548 :
549 28 : if (numdcs == 0) {
550 4 : TALLOC_FREE(dcs);
551 4 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
552 : }
553 :
554 : /* Check for integer wrap. */
555 24 : if (numdcs + numdcs < numdcs) {
556 0 : TALLOC_FREE(dcs);
557 0 : return NT_STATUS_INVALID_PARAMETER;
558 : }
559 :
560 : /*
561 : * We're only returning up to 2 addresses per
562 : * DC name, so just allocate size numdcs x 2.
563 : */
564 :
565 24 : dclist = talloc_zero_array(mem_ctx,
566 : struct ip_service_name,
567 : numdcs * 2);
568 24 : if (!dclist) {
569 0 : TALLOC_FREE(dcs);
570 0 : return NT_STATUS_NO_MEMORY;
571 : }
572 :
573 : /*
574 : * First, copy the SRV record replies that
575 : * have IP addresses returned with them.
576 : */
577 24 : ret_count = 0;
578 48 : for (i = 0; i < numdcs; i++) {
579 : size_t j;
580 24 : bool have_v4_addr = false;
581 24 : bool have_v6_addr = false;
582 :
583 24 : if (dcs[i].num_ips == 0) {
584 0 : continue;
585 : }
586 :
587 : /*
588 : * Pick up to 1 address from each address
589 : * family (IPv4, IPv6).
590 : *
591 : * This is different from the previous
592 : * code which picked a 'next ip' address
593 : * each time, incrementing an index.
594 : * Too complex to maintain :-(.
595 : */
596 48 : for (j = 0; j < dcs[i].num_ips; j++) {
597 48 : if ((dcs[i].ss_s[j].ss_family == AF_INET && !have_v4_addr) ||
598 24 : (dcs[i].ss_s[j].ss_family == AF_INET6 && !have_v6_addr)) {
599 : bool ok;
600 96 : dclist[ret_count].hostname =
601 48 : talloc_strdup(dclist, dcs[i].hostname);
602 48 : ok = sockaddr_storage_to_samba_sockaddr(
603 48 : &dclist[ret_count].sa,
604 48 : &dcs[i].ss_s[j]);
605 48 : if (!ok) {
606 0 : TALLOC_FREE(dcs);
607 0 : TALLOC_FREE(dclist);
608 0 : return NT_STATUS_INVALID_PARAMETER;
609 : }
610 48 : ret_count++;
611 48 : if (dcs[i].ss_s[j].ss_family == AF_INET) {
612 24 : have_v4_addr = true;
613 : } else {
614 24 : have_v6_addr = true;
615 : }
616 48 : if (have_v4_addr && have_v6_addr) {
617 24 : break;
618 : }
619 : }
620 : }
621 : }
622 :
623 24 : TALLOC_FREE(dcs);
624 :
625 24 : if (ret_count == 0) {
626 0 : TALLOC_FREE(dclist);
627 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
628 : }
629 :
630 24 : *returned_dclist = dclist;
631 24 : *return_count = ret_count;
632 24 : return NT_STATUS_OK;
633 : }
634 :
635 : /****************************************************************
636 : ****************************************************************/
637 :
638 36 : static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx,
639 : const char *dc_unc,
640 : const char *dc_address,
641 : uint32_t dc_address_type,
642 : const struct GUID *domain_guid,
643 : const char *domain_name,
644 : const char *forest_name,
645 : uint32_t flags,
646 : const char *dc_site_name,
647 : const char *client_site_name,
648 : struct netr_DsRGetDCNameInfo **info_out)
649 : {
650 : struct netr_DsRGetDCNameInfo *info;
651 :
652 36 : info = talloc_zero(mem_ctx, struct netr_DsRGetDCNameInfo);
653 36 : NT_STATUS_HAVE_NO_MEMORY(info);
654 :
655 36 : if (dc_unc) {
656 36 : if (!(dc_unc[0] == '\\' && dc_unc[1] == '\\')) {
657 34 : info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
658 : dc_unc);
659 : } else {
660 2 : info->dc_unc = talloc_strdup(mem_ctx, dc_unc);
661 : }
662 36 : NT_STATUS_HAVE_NO_MEMORY(info->dc_unc);
663 : }
664 :
665 36 : if (dc_address) {
666 36 : if (!(dc_address[0] == '\\' && dc_address[1] == '\\')) {
667 36 : info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
668 : dc_address);
669 : } else {
670 0 : info->dc_address = talloc_strdup(mem_ctx, dc_address);
671 : }
672 36 : NT_STATUS_HAVE_NO_MEMORY(info->dc_address);
673 : }
674 :
675 36 : info->dc_address_type = dc_address_type;
676 :
677 36 : if (domain_guid) {
678 36 : info->domain_guid = *domain_guid;
679 : }
680 :
681 36 : if (domain_name) {
682 36 : info->domain_name = talloc_strdup(mem_ctx, domain_name);
683 36 : NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
684 : }
685 :
686 36 : if (forest_name && *forest_name) {
687 30 : info->forest_name = talloc_strdup(mem_ctx, forest_name);
688 30 : NT_STATUS_HAVE_NO_MEMORY(info->forest_name);
689 30 : flags |= DS_DNS_FOREST_ROOT;
690 : }
691 :
692 36 : info->dc_flags = flags;
693 :
694 36 : if (dc_site_name) {
695 31 : info->dc_site_name = talloc_strdup(mem_ctx, dc_site_name);
696 31 : NT_STATUS_HAVE_NO_MEMORY(info->dc_site_name);
697 : }
698 :
699 36 : if (client_site_name) {
700 31 : info->client_site_name = talloc_strdup(mem_ctx,
701 : client_site_name);
702 31 : NT_STATUS_HAVE_NO_MEMORY(info->client_site_name);
703 : }
704 :
705 36 : *info_out = info;
706 :
707 36 : return NT_STATUS_OK;
708 : }
709 :
710 : /****************************************************************
711 : ****************************************************************/
712 :
713 36 : static void map_dc_and_domain_names(uint32_t flags,
714 : const char *dc_name,
715 : const char *domain_name,
716 : const char *dns_dc_name,
717 : const char *dns_domain_name,
718 : uint32_t *dc_flags,
719 : const char **hostname_p,
720 : const char **domain_p)
721 : {
722 36 : switch (flags & 0xf0000000) {
723 0 : case DS_RETURN_FLAT_NAME:
724 0 : if (dc_name && domain_name &&
725 0 : *dc_name && *domain_name) {
726 0 : *hostname_p = dc_name;
727 0 : *domain_p = domain_name;
728 0 : break;
729 : }
730 :
731 : FALL_THROUGH;
732 : case DS_RETURN_DNS_NAME:
733 : default:
734 36 : if (dns_dc_name && dns_domain_name &&
735 31 : *dns_dc_name && *dns_domain_name) {
736 30 : *hostname_p = dns_dc_name;
737 30 : *domain_p = dns_domain_name;
738 30 : *dc_flags |= DS_DNS_DOMAIN | DS_DNS_CONTROLLER;
739 30 : break;
740 : }
741 6 : if (dc_name && domain_name &&
742 6 : *dc_name && *domain_name) {
743 6 : *hostname_p = dc_name;
744 6 : *domain_p = domain_name;
745 6 : break;
746 : }
747 : }
748 36 : }
749 :
750 : /****************************************************************
751 : ****************************************************************/
752 :
753 36 : static NTSTATUS make_dc_info_from_cldap_reply(
754 : TALLOC_CTX *mem_ctx,
755 : uint32_t flags,
756 : const struct samba_sockaddr *sa,
757 : struct NETLOGON_SAM_LOGON_RESPONSE_EX *r,
758 : struct netr_DsRGetDCNameInfo **info)
759 : {
760 36 : const char *dc_hostname = NULL;
761 36 : const char *dc_domain_name = NULL;
762 36 : const char *dc_address = NULL;
763 36 : const char *dc_forest = NULL;
764 36 : uint32_t dc_address_type = 0;
765 36 : uint32_t dc_flags = 0;
766 36 : struct GUID *dc_domain_guid = NULL;
767 36 : const char *dc_server_site = NULL;
768 36 : const char *dc_client_site = NULL;
769 :
770 : char addr[INET6_ADDRSTRLEN];
771 :
772 36 : if (sa != NULL) {
773 29 : print_sockaddr(addr, sizeof(addr), &sa->u.ss);
774 29 : dc_address = addr;
775 29 : dc_address_type = DS_ADDRESS_TYPE_INET;
776 : } else {
777 7 : if (r->sockaddr.pdc_ip) {
778 7 : dc_address = r->sockaddr.pdc_ip;
779 7 : dc_address_type = DS_ADDRESS_TYPE_INET;
780 : } else {
781 0 : dc_address = r->pdc_name;
782 0 : dc_address_type = DS_ADDRESS_TYPE_NETBIOS;
783 : }
784 : }
785 :
786 36 : map_dc_and_domain_names(flags,
787 : r->pdc_name,
788 : r->domain_name,
789 : r->pdc_dns_name,
790 : r->dns_domain,
791 : &dc_flags,
792 : &dc_hostname,
793 : &dc_domain_name);
794 :
795 36 : dc_flags |= r->server_type;
796 36 : dc_forest = r->forest;
797 36 : dc_domain_guid = &r->domain_uuid;
798 36 : dc_server_site = r->server_site;
799 36 : dc_client_site = r->client_site;
800 :
801 36 : return make_domain_controller_info(mem_ctx,
802 : dc_hostname,
803 : dc_address,
804 : dc_address_type,
805 : dc_domain_guid,
806 : dc_domain_name,
807 : dc_forest,
808 : dc_flags,
809 : dc_server_site,
810 : dc_client_site,
811 : info);
812 : }
813 :
814 : /****************************************************************
815 : ****************************************************************/
816 :
817 29 : static uint32_t map_ds_flags_to_nt_version(uint32_t flags)
818 : {
819 29 : uint32_t nt_version = 0;
820 :
821 29 : if (flags & DS_PDC_REQUIRED) {
822 0 : nt_version |= NETLOGON_NT_VERSION_PDC;
823 : }
824 :
825 29 : if (flags & DS_GC_SERVER_REQUIRED) {
826 0 : nt_version |= NETLOGON_NT_VERSION_GC;
827 : }
828 :
829 29 : if (flags & DS_TRY_NEXTCLOSEST_SITE) {
830 0 : nt_version |= NETLOGON_NT_VERSION_WITH_CLOSEST_SITE;
831 : }
832 :
833 29 : if (flags & DS_IP_REQUIRED) {
834 0 : nt_version |= NETLOGON_NT_VERSION_IP;
835 : }
836 :
837 29 : return nt_version;
838 : }
839 :
840 : /****************************************************************
841 : ****************************************************************/
842 :
843 24 : static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
844 : const char *domain_name,
845 : uint32_t flags,
846 : struct ip_service_name *dclist,
847 : size_t num_dcs,
848 : struct netr_DsRGetDCNameInfo **info)
849 : {
850 24 : size_t i = 0;
851 24 : bool valid_dc = false;
852 24 : struct netlogon_samlogon_response *r = NULL;
853 24 : uint32_t nt_version = NETLOGON_NT_VERSION_5 |
854 : NETLOGON_NT_VERSION_5EX;
855 24 : uint32_t ret_flags = 0;
856 : NTSTATUS status;
857 :
858 24 : nt_version |= map_ds_flags_to_nt_version(flags);
859 :
860 24 : for (i=0; i<num_dcs; i++) {
861 : char addr[INET6_ADDRSTRLEN];
862 :
863 24 : print_sockaddr(addr, sizeof(addr), &dclist[i].sa.u.ss);
864 :
865 24 : DEBUG(10,("LDAP ping to %s (%s)\n", dclist[i].hostname, addr));
866 :
867 24 : if (ads_cldap_netlogon(mem_ctx, &dclist[i].sa.u.ss,
868 : domain_name,
869 : nt_version,
870 : &r))
871 : {
872 24 : nt_version = r->ntver;
873 24 : ret_flags = get_cldap_reply_server_flags(r, nt_version);
874 :
875 24 : if (check_cldap_reply_required_flags(ret_flags, flags)) {
876 24 : valid_dc = true;
877 24 : break;
878 : }
879 : }
880 :
881 0 : continue;
882 : }
883 :
884 24 : if (!valid_dc) {
885 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
886 : }
887 :
888 24 : status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].sa,
889 24 : &r->data.nt5_ex, info);
890 24 : if (NT_STATUS_IS_OK(status)) {
891 24 : return store_cldap_reply(mem_ctx, flags, &dclist[i].sa,
892 24 : nt_version, &r->data.nt5_ex);
893 : }
894 :
895 0 : return status;
896 : }
897 :
898 : /****************************************************************
899 : ****************************************************************/
900 :
901 : /****************************************************************
902 : ****************************************************************/
903 :
904 5 : static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
905 : struct messaging_context *msg_ctx,
906 : const char *domain_name,
907 : uint32_t flags,
908 : struct ip_service_name *dclist,
909 : size_t num_dcs,
910 : struct netr_DsRGetDCNameInfo **info)
911 5 : {
912 5 : enum nbt_name_type name_type = NBT_NAME_LOGON;
913 : NTSTATUS status;
914 : size_t i;
915 5 : const char *dc_name = NULL;
916 : fstring tmp_dc_name;
917 5 : struct netlogon_samlogon_response *r = NULL;
918 5 : bool store_cache = false;
919 5 : uint32_t nt_version = NETLOGON_NT_VERSION_1 |
920 : NETLOGON_NT_VERSION_5 |
921 : NETLOGON_NT_VERSION_5EX_WITH_IP;
922 5 : size_t len = strlen(lp_netbios_name());
923 5 : char my_acct_name[len+2];
924 :
925 5 : if (msg_ctx == NULL) {
926 0 : return NT_STATUS_INVALID_PARAMETER;
927 : }
928 :
929 5 : if (flags & DS_PDC_REQUIRED) {
930 0 : name_type = NBT_NAME_PDC;
931 : }
932 :
933 5 : nt_version |= map_ds_flags_to_nt_version(flags);
934 :
935 5 : snprintf(my_acct_name,
936 : sizeof(my_acct_name),
937 : "%s$",
938 : lp_netbios_name());
939 :
940 5 : DEBUG(10,("process_dc_netbios\n"));
941 :
942 5 : for (i=0; i<num_dcs; i++) {
943 : uint16_t val;
944 :
945 5 : generate_random_buffer((uint8_t *)&val, 2);
946 :
947 5 : status = nbt_getdc(msg_ctx, 10, &dclist[i].sa.u.ss, domain_name,
948 : NULL, my_acct_name, ACB_WSTRUST, nt_version,
949 : mem_ctx, &nt_version, &dc_name, &r);
950 5 : if (NT_STATUS_IS_OK(status)) {
951 1 : store_cache = true;
952 1 : namecache_store(dc_name,
953 : NBT_NAME_SERVER,
954 : 1,
955 1 : &dclist[i].sa);
956 5 : goto make_reply;
957 : }
958 :
959 4 : if (name_status_find(domain_name,
960 : name_type,
961 : NBT_NAME_SERVER,
962 4 : &dclist[i].sa.u.ss,
963 : tmp_dc_name))
964 : {
965 : struct NETLOGON_SAM_LOGON_RESPONSE_NT40 logon1;
966 :
967 4 : r = talloc_zero(mem_ctx, struct netlogon_samlogon_response);
968 4 : NT_STATUS_HAVE_NO_MEMORY(r);
969 :
970 4 : ZERO_STRUCT(logon1);
971 :
972 4 : nt_version = NETLOGON_NT_VERSION_1;
973 :
974 4 : logon1.nt_version = nt_version;
975 4 : logon1.pdc_name = tmp_dc_name;
976 4 : logon1.domain_name = talloc_strdup_upper(mem_ctx, domain_name);
977 4 : NT_STATUS_HAVE_NO_MEMORY(logon1.domain_name);
978 :
979 4 : r->data.nt4 = logon1;
980 4 : r->ntver = nt_version;
981 :
982 4 : map_netlogon_samlogon_response(r);
983 :
984 4 : namecache_store(tmp_dc_name,
985 : NBT_NAME_SERVER,
986 : 1,
987 4 : &dclist[i].sa);
988 :
989 4 : goto make_reply;
990 : }
991 : }
992 :
993 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
994 :
995 5 : make_reply:
996 :
997 5 : status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].sa,
998 5 : &r->data.nt5_ex, info);
999 5 : if (NT_STATUS_IS_OK(status) && store_cache) {
1000 1 : return store_cldap_reply(mem_ctx, flags, &dclist[i].sa,
1001 1 : nt_version, &r->data.nt5_ex);
1002 : }
1003 :
1004 4 : return status;
1005 : }
1006 :
1007 : /****************************************************************
1008 : ****************************************************************/
1009 :
1010 33 : static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
1011 : struct messaging_context *msg_ctx,
1012 : const char *domain_name,
1013 : const struct GUID *domain_guid,
1014 : uint32_t flags,
1015 : const char *site_name,
1016 : struct netr_DsRGetDCNameInfo **info)
1017 : {
1018 : NTSTATUS status;
1019 33 : struct ip_service_name *dclist = NULL;
1020 33 : size_t num_dcs = 0;
1021 :
1022 33 : DEBUG(10,("dsgetdcname_rediscover\n"));
1023 :
1024 33 : if (flags & DS_IS_FLAT_NAME) {
1025 :
1026 2 : if (lp_disable_netbios()) {
1027 0 : return NT_STATUS_NOT_SUPPORTED;
1028 : }
1029 :
1030 2 : status = discover_dc_netbios(mem_ctx, domain_name, flags,
1031 : &dclist, &num_dcs);
1032 2 : NT_STATUS_NOT_OK_RETURN(status);
1033 :
1034 2 : return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags,
1035 : dclist, num_dcs, info);
1036 : }
1037 :
1038 31 : if (flags & DS_IS_DNS_NAME) {
1039 :
1040 28 : status = discover_dc_dns(mem_ctx, domain_name, domain_guid,
1041 : flags, site_name, &dclist, &num_dcs);
1042 28 : NT_STATUS_NOT_OK_RETURN(status);
1043 :
1044 24 : return process_dc_dns(mem_ctx, domain_name, flags,
1045 : dclist, num_dcs, info);
1046 : }
1047 :
1048 3 : status = discover_dc_dns(mem_ctx, domain_name, domain_guid, flags,
1049 : site_name, &dclist, &num_dcs);
1050 :
1051 3 : if (NT_STATUS_IS_OK(status) && num_dcs != 0) {
1052 :
1053 0 : status = process_dc_dns(mem_ctx, domain_name, flags, dclist,
1054 : num_dcs, info);
1055 0 : if (NT_STATUS_IS_OK(status)) {
1056 0 : return status;
1057 : }
1058 : }
1059 :
1060 3 : if (lp_disable_netbios()) {
1061 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1062 : }
1063 :
1064 3 : status = discover_dc_netbios(mem_ctx, domain_name, flags, &dclist,
1065 : &num_dcs);
1066 3 : NT_STATUS_NOT_OK_RETURN(status);
1067 :
1068 3 : return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags, dclist,
1069 : num_dcs, info);
1070 : }
1071 :
1072 37 : static bool is_closest_site(struct netr_DsRGetDCNameInfo *info)
1073 : {
1074 37 : if (info->dc_flags & DS_SERVER_CLOSEST) {
1075 30 : return true;
1076 : }
1077 :
1078 7 : if (!info->client_site_name) {
1079 6 : return true;
1080 : }
1081 :
1082 1 : if (!info->dc_site_name) {
1083 0 : return false;
1084 : }
1085 :
1086 1 : if (strcmp(info->client_site_name, info->dc_site_name) == 0) {
1087 1 : return true;
1088 : }
1089 :
1090 0 : return false;
1091 : }
1092 :
1093 : /********************************************************************
1094 : Internal dsgetdcname.
1095 : ********************************************************************/
1096 :
1097 41 : static NTSTATUS dsgetdcname_internal(TALLOC_CTX *mem_ctx,
1098 : struct messaging_context *msg_ctx,
1099 : const char *domain_name,
1100 : const struct GUID *domain_guid,
1101 : const char *site_name,
1102 : uint32_t flags,
1103 : struct netr_DsRGetDCNameInfo **info)
1104 : {
1105 : NTSTATUS status;
1106 41 : struct netr_DsRGetDCNameInfo *myinfo = NULL;
1107 41 : bool first = true;
1108 41 : struct netr_DsRGetDCNameInfo *first_info = NULL;
1109 :
1110 41 : DEBUG(10,("dsgetdcname_internal: domain_name: %s, "
1111 : "domain_guid: %s, site_name: %s, flags: 0x%08x\n",
1112 : domain_name,
1113 : domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)",
1114 : site_name ? site_name : "(null)", flags));
1115 :
1116 41 : *info = NULL;
1117 :
1118 41 : if (!check_allowed_required_flags(flags, site_name)) {
1119 0 : DEBUG(0,("invalid flags specified\n"));
1120 0 : return NT_STATUS_INVALID_PARAMETER;
1121 : }
1122 :
1123 41 : if (flags & DS_FORCE_REDISCOVERY) {
1124 33 : goto rediscover;
1125 : }
1126 :
1127 8 : status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
1128 : flags, site_name, &myinfo);
1129 8 : if (NT_STATUS_IS_OK(status)) {
1130 8 : *info = myinfo;
1131 8 : goto done;
1132 : }
1133 :
1134 0 : if (flags & DS_BACKGROUND_ONLY) {
1135 0 : goto done;
1136 : }
1137 :
1138 0 : rediscover:
1139 33 : status = dsgetdcname_rediscover(mem_ctx, msg_ctx, domain_name,
1140 : domain_guid, flags, site_name,
1141 : &myinfo);
1142 :
1143 41 : done:
1144 41 : if (!NT_STATUS_IS_OK(status)) {
1145 4 : if (!first) {
1146 0 : *info = first_info;
1147 0 : return NT_STATUS_OK;
1148 : }
1149 4 : return status;
1150 : }
1151 :
1152 37 : if (!first) {
1153 0 : TALLOC_FREE(first_info);
1154 37 : } else if (!is_closest_site(myinfo)) {
1155 0 : first = false;
1156 0 : first_info = myinfo;
1157 : /* TODO: may use the next_closest_site here */
1158 0 : site_name = myinfo->client_site_name;
1159 0 : goto rediscover;
1160 : }
1161 :
1162 37 : *info = myinfo;
1163 37 : return NT_STATUS_OK;
1164 : }
1165 :
1166 : /********************************************************************
1167 : dsgetdcname.
1168 :
1169 : This will be the only public function here.
1170 : ********************************************************************/
1171 :
1172 39 : NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
1173 : struct messaging_context *msg_ctx,
1174 : const char *domain_name,
1175 : const struct GUID *domain_guid,
1176 : const char *site_name,
1177 : uint32_t flags,
1178 : struct netr_DsRGetDCNameInfo **info)
1179 : {
1180 : NTSTATUS status;
1181 39 : const char *query_site = NULL;
1182 39 : char *ptr_to_free = NULL;
1183 39 : bool retry_query_with_null = false;
1184 :
1185 39 : if ((site_name == NULL) || (site_name[0] == '\0')) {
1186 39 : ptr_to_free = sitename_fetch(mem_ctx, domain_name);
1187 39 : if (ptr_to_free != NULL) {
1188 33 : retry_query_with_null = true;
1189 : }
1190 39 : query_site = ptr_to_free;
1191 : } else {
1192 0 : query_site = site_name;
1193 : }
1194 :
1195 39 : status = dsgetdcname_internal(mem_ctx,
1196 : msg_ctx,
1197 : domain_name,
1198 : domain_guid,
1199 : query_site,
1200 : flags,
1201 : info);
1202 :
1203 39 : TALLOC_FREE(ptr_to_free);
1204 :
1205 39 : if (!NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1206 37 : return status;
1207 : }
1208 :
1209 : /* Should we try again with site_name == NULL ? */
1210 2 : if (retry_query_with_null) {
1211 2 : status = dsgetdcname_internal(mem_ctx,
1212 : msg_ctx,
1213 : domain_name,
1214 : domain_guid,
1215 : NULL,
1216 : flags,
1217 : info);
1218 : }
1219 :
1220 2 : return status;
1221 : }
1222 :
1223 0 : NTSTATUS dsgetonedcname(TALLOC_CTX *mem_ctx,
1224 : struct messaging_context *msg_ctx,
1225 : const char *domain_name,
1226 : const char *dcname,
1227 : uint32_t flags,
1228 : struct netr_DsRGetDCNameInfo **info)
1229 : {
1230 : NTSTATUS status;
1231 : struct sockaddr_storage *addrs;
1232 : unsigned int num_addrs, i;
1233 0 : const char *hostname = strip_hostname(dcname);
1234 :
1235 0 : status = resolve_name_list(mem_ctx, hostname, 0x20,
1236 : &addrs, &num_addrs);
1237 0 : if (!NT_STATUS_IS_OK(status)) {
1238 0 : return status;
1239 : }
1240 :
1241 0 : for (i = 0; i < num_addrs; i++) {
1242 :
1243 : bool ok;
1244 : struct ip_service_name dclist;
1245 :
1246 0 : dclist.hostname = hostname;
1247 0 : ok = sockaddr_storage_to_samba_sockaddr(&dclist.sa, &addrs[i]);
1248 0 : if (!ok) {
1249 0 : TALLOC_FREE(addrs);
1250 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1251 : }
1252 :
1253 0 : status = process_dc_dns(mem_ctx, domain_name, flags,
1254 : &dclist, 1, info);
1255 0 : if (NT_STATUS_IS_OK(status)) {
1256 0 : TALLOC_FREE(addrs);
1257 0 : return NT_STATUS_OK;
1258 : }
1259 :
1260 0 : if (lp_disable_netbios()) {
1261 0 : continue;
1262 : }
1263 :
1264 0 : status = process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags,
1265 : &dclist, 1, info);
1266 0 : if (NT_STATUS_IS_OK(status)) {
1267 0 : TALLOC_FREE(addrs);
1268 0 : return NT_STATUS_OK;
1269 : }
1270 : }
1271 :
1272 0 : TALLOC_FREE(addrs);
1273 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1274 : }
|