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 37 : static void debug_dsdcinfo_flags(int lvl, uint32_t flags)
53 : {
54 37 : DEBUG(lvl,("debug_dsdcinfo_flags: 0x%08x\n\t", flags));
55 :
56 37 : if (flags & DS_FORCE_REDISCOVERY)
57 31 : DEBUGADD(lvl,("DS_FORCE_REDISCOVERY "));
58 37 : if (flags & 0x000000002)
59 0 : DEBUGADD(lvl,("0x00000002 "));
60 37 : if (flags & 0x000000004)
61 0 : DEBUGADD(lvl,("0x00000004 "));
62 37 : if (flags & 0x000000008)
63 0 : DEBUGADD(lvl,("0x00000008 "));
64 37 : if (flags & DS_DIRECTORY_SERVICE_REQUIRED)
65 30 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_REQUIRED "));
66 37 : if (flags & DS_DIRECTORY_SERVICE_PREFERRED)
67 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_PREFERRED "));
68 37 : if (flags & DS_GC_SERVER_REQUIRED)
69 0 : DEBUGADD(lvl,("DS_GC_SERVER_REQUIRED "));
70 37 : if (flags & DS_PDC_REQUIRED)
71 0 : DEBUGADD(lvl,("DS_PDC_REQUIRED "));
72 37 : if (flags & DS_BACKGROUND_ONLY)
73 0 : DEBUGADD(lvl,("DS_BACKGROUND_ONLY "));
74 37 : if (flags & DS_IP_REQUIRED)
75 0 : DEBUGADD(lvl,("DS_IP_REQUIRED "));
76 37 : if (flags & DS_KDC_REQUIRED)
77 0 : DEBUGADD(lvl,("DS_KDC_REQUIRED "));
78 37 : if (flags & DS_TIMESERV_REQUIRED)
79 0 : DEBUGADD(lvl,("DS_TIMESERV_REQUIRED "));
80 37 : if (flags & DS_WRITABLE_REQUIRED)
81 30 : DEBUGADD(lvl,("DS_WRITABLE_REQUIRED "));
82 37 : if (flags & DS_GOOD_TIMESERV_PREFERRED)
83 0 : DEBUGADD(lvl,("DS_GOOD_TIMESERV_PREFERRED "));
84 37 : if (flags & DS_AVOID_SELF)
85 0 : DEBUGADD(lvl,("DS_AVOID_SELF "));
86 37 : if (flags & DS_ONLY_LDAP_NEEDED)
87 0 : DEBUGADD(lvl,("DS_ONLY_LDAP_NEEDED "));
88 37 : if (flags & DS_IS_FLAT_NAME)
89 1 : DEBUGADD(lvl,("DS_IS_FLAT_NAME "));
90 37 : if (flags & DS_IS_DNS_NAME)
91 27 : DEBUGADD(lvl,("DS_IS_DNS_NAME "));
92 37 : if (flags & DS_TRY_NEXTCLOSEST_SITE)
93 0 : DEBUGADD(lvl,("DS_TRY_NEXTCLOSEST_SITE "));
94 37 : if (flags & DS_DIRECTORY_SERVICE_6_REQUIRED)
95 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_6_REQUIRED "));
96 37 : if (flags & DS_WEB_SERVICE_REQUIRED)
97 0 : DEBUGADD(lvl,("DS_WEB_SERVICE_REQUIRED "));
98 37 : if (flags & DS_DIRECTORY_SERVICE_8_REQUIRED)
99 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_8_REQUIRED "));
100 37 : if (flags & DS_DIRECTORY_SERVICE_9_REQUIRED)
101 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_9_REQUIRED "));
102 37 : if (flags & DS_DIRECTORY_SERVICE_10_REQUIRED)
103 0 : DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_10_REQUIRED "));
104 37 : if (flags & 0x01000000)
105 0 : DEBUGADD(lvl,("0x01000000 "));
106 37 : if (flags & 0x02000000)
107 0 : DEBUGADD(lvl,("0x02000000 "));
108 37 : if (flags & 0x04000000)
109 0 : DEBUGADD(lvl,("0x04000000 "));
110 37 : if (flags & 0x08000000)
111 0 : DEBUGADD(lvl,("0x08000000 "));
112 37 : if (flags & 0x10000000)
113 0 : DEBUGADD(lvl,("0x10000000 "));
114 37 : if (flags & 0x20000000)
115 0 : DEBUGADD(lvl,("0x20000000 "));
116 37 : if (flags & DS_RETURN_DNS_NAME)
117 37 : DEBUGADD(lvl,("DS_RETURN_DNS_NAME "));
118 37 : if (flags & DS_RETURN_FLAT_NAME)
119 0 : DEBUGADD(lvl,("DS_RETURN_FLAT_NAME "));
120 37 : if (flags)
121 37 : DEBUGADD(lvl,("\n"));
122 37 : }
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 51 : 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 51 : bool ret = false;
167 :
168 51 : key = dsgetdcname_cache_key(mem_ctx, domain_name);
169 51 : if (!key) {
170 0 : return NT_STATUS_NO_MEMORY;
171 : }
172 :
173 51 : expire_time = time(NULL) + DSGETDCNAME_CACHE_TTL;
174 :
175 51 : ret = gencache_set_data_blob(key, blob, expire_time);
176 :
177 51 : return ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
178 : }
179 :
180 : /****************************************************************
181 : ****************************************************************/
182 :
183 26 : 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 26 : print_sockaddr(addr, sizeof(addr), &sa->u.ss);
195 :
196 : /* FIXME */
197 26 : r->sockaddr_size = 0x10; /* the w32 winsock addr size */
198 26 : r->sockaddr.sockaddr_family = 2; /* AF_INET */
199 26 : r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
200 :
201 26 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
202 : (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX);
203 26 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
204 0 : return ndr_map_error2ntstatus(ndr_err);
205 : }
206 :
207 26 : if (r->domain_name) {
208 26 : status = dsgetdcname_cache_store(mem_ctx, r->domain_name,
209 : blob);
210 26 : if (!NT_STATUS_IS_OK(status)) {
211 0 : goto done;
212 : }
213 26 : if (r->client_site) {
214 25 : sitename_store(r->domain_name, r->client_site);
215 : }
216 : }
217 26 : if (r->dns_domain) {
218 25 : status = dsgetdcname_cache_store(mem_ctx, r->dns_domain, blob);
219 25 : if (!NT_STATUS_IS_OK(status)) {
220 0 : goto done;
221 : }
222 25 : if (r->client_site) {
223 25 : sitename_store(r->dns_domain, r->client_site);
224 : }
225 : }
226 :
227 26 : status = NT_STATUS_OK;
228 :
229 26 : done:
230 26 : data_blob_free(&blob);
231 :
232 26 : return status;
233 : }
234 :
235 : /****************************************************************
236 : ****************************************************************/
237 :
238 25 : static uint32_t get_cldap_reply_server_flags(struct netlogon_samlogon_response *r,
239 : uint32_t nt_version)
240 : {
241 25 : 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 25 : case 4:
253 : case 5:
254 : case 6:
255 : case 7:
256 25 : 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 6 : 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 6 : key = dsgetdcname_cache_key(mem_ctx, domain_name);
302 6 : if (!key) {
303 0 : return NT_STATUS_NO_MEMORY;
304 : }
305 :
306 6 : if (!gencache_get_data_blob(key, NULL, &blob, NULL, NULL)) {
307 1 : return NT_STATUS_NOT_FOUND;
308 : }
309 :
310 5 : info = talloc_zero(mem_ctx, struct netr_DsRGetDCNameInfo);
311 5 : if (!info) {
312 0 : data_blob_free(&blob);
313 0 : return NT_STATUS_NO_MEMORY;
314 : }
315 :
316 5 : 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 5 : data_blob_free(&blob);
320 5 : 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 5 : status = make_dc_info_from_cldap_reply(mem_ctx, flags, NULL,
326 : &r, &info);
327 5 : if (!NT_STATUS_IS_OK(status)) {
328 0 : return status;
329 : }
330 :
331 5 : if (DEBUGLEVEL >= 10) {
332 0 : NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, info);
333 : }
334 :
335 : /* check flags */
336 5 : 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 5 : 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 5 : *info_p = info;
347 :
348 5 : return NT_STATUS_OK;
349 : }
350 :
351 : /****************************************************************
352 : ****************************************************************/
353 :
354 6 : 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 6 : status = dsgetdcname_cache_fetch(mem_ctx, domain_name, domain_guid,
365 : flags, info);
366 6 : 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 6 : if (flags & DS_BACKGROUND_ONLY) {
374 0 : return status;
375 : }
376 :
377 6 : 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 6 : return status;
393 : }
394 :
395 : /****************************************************************
396 : ****************************************************************/
397 :
398 37 : static bool check_allowed_required_flags(uint32_t flags,
399 : const char *site_name)
400 : {
401 37 : uint32_t return_type = flags & (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME);
402 37 : uint32_t offered_type = flags & (DS_IS_FLAT_NAME|DS_IS_DNS_NAME);
403 37 : 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 37 : debug_dsdcinfo_flags(10, flags);
409 :
410 37 : if ((flags & DS_TRY_NEXTCLOSEST_SITE) && site_name) {
411 0 : return false;
412 : }
413 :
414 37 : if (return_type == (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME)) {
415 0 : return false;
416 : }
417 :
418 37 : if (offered_type == (DS_IS_DNS_NAME|DS_IS_FLAT_NAME)) {
419 0 : return false;
420 : }
421 :
422 37 : 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 37 : return true;
433 : }
434 :
435 : /****************************************************************
436 : ****************************************************************/
437 :
438 4 : 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 4 : enum nbt_name_type name_type = NBT_NAME_LOGON;
446 4 : struct samba_sockaddr *salist = NULL;
447 : size_t i;
448 4 : struct ip_service_name *dclist = NULL;
449 4 : size_t count = 0;
450 : static const char *resolve_order[] = { "lmhosts", "wins", "bcast", NULL };
451 :
452 4 : if (flags & DS_PDC_REQUIRED) {
453 0 : name_type = NBT_NAME_PDC;
454 : }
455 :
456 4 : status = internal_resolve_name(mem_ctx,
457 : domain_name,
458 : name_type,
459 : NULL,
460 : &salist,
461 : &count,
462 : resolve_order);
463 4 : 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 4 : dclist = talloc_zero_array(mem_ctx, struct ip_service_name, count);
469 4 : if (!dclist) {
470 0 : TALLOC_FREE(salist);
471 0 : return NT_STATUS_NO_MEMORY;
472 : }
473 :
474 8 : for (i=0; i<count; i++) {
475 : char addr[INET6_ADDRSTRLEN];
476 4 : struct ip_service_name *r = &dclist[i];
477 :
478 4 : print_sockaddr(addr, sizeof(addr),
479 4 : &salist[i].u.ss);
480 :
481 4 : r->sa = salist[i];
482 4 : r->hostname = talloc_strdup(mem_ctx, addr);
483 4 : 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 4 : TALLOC_FREE(salist);
492 :
493 4 : *returned_dclist = dclist;
494 4 : *returned_count = count;
495 :
496 4 : return NT_STATUS_OK;
497 : }
498 :
499 : /****************************************************************
500 : ****************************************************************/
501 :
502 30 : 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 30 : struct dns_rr_srv *dcs = NULL;
513 30 : size_t numdcs = 0;
514 30 : struct ip_service_name *dclist = NULL;
515 30 : size_t ret_count = 0;
516 30 : char *query = NULL;
517 :
518 30 : if (flags & DS_PDC_REQUIRED) {
519 0 : query = ads_dns_query_string_pdc(mem_ctx, domain_name);
520 30 : } else if (flags & DS_GC_SERVER_REQUIRED) {
521 0 : query = ads_dns_query_string_gcs(mem_ctx, domain_name);
522 30 : } else if (flags & DS_KDC_REQUIRED) {
523 0 : query = ads_dns_query_string_kdcs(mem_ctx, domain_name);
524 30 : } else if (flags & DS_DIRECTORY_SERVICE_REQUIRED) {
525 29 : 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 30 : if (query == NULL) {
534 0 : return NT_STATUS_NO_MEMORY;
535 : }
536 :
537 30 : status = ads_dns_query_srv(
538 : mem_ctx,
539 : lp_get_async_dns_timeout(),
540 : site_name,
541 : query,
542 : &dcs,
543 : &numdcs);
544 30 : TALLOC_FREE(query);
545 30 : if (!NT_STATUS_IS_OK(status)) {
546 3 : return status;
547 : }
548 :
549 27 : if (numdcs == 0) {
550 2 : TALLOC_FREE(dcs);
551 2 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
552 : }
553 :
554 : /* Check for integer wrap. */
555 25 : 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 25 : dclist = talloc_zero_array(mem_ctx,
566 : struct ip_service_name,
567 : numdcs * 2);
568 25 : 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 25 : ret_count = 0;
578 50 : for (i = 0; i < numdcs; i++) {
579 : size_t j;
580 25 : bool have_v4_addr = false;
581 25 : bool have_v6_addr = false;
582 :
583 25 : 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 50 : for (j = 0; j < dcs[i].num_ips; j++) {
597 65 : if ((dcs[i].ss_s[j].ss_family == AF_INET && !have_v4_addr) ||
598 40 : (dcs[i].ss_s[j].ss_family == AF_INET6 && !have_v6_addr)) {
599 : bool ok;
600 100 : dclist[ret_count].hostname =
601 80 : talloc_strdup(dclist, dcs[i].hostname);
602 50 : ok = sockaddr_storage_to_samba_sockaddr(
603 50 : &dclist[ret_count].sa,
604 50 : &dcs[i].ss_s[j]);
605 50 : if (!ok) {
606 0 : TALLOC_FREE(dcs);
607 0 : TALLOC_FREE(dclist);
608 0 : return NT_STATUS_INVALID_PARAMETER;
609 : }
610 50 : ret_count++;
611 50 : if (dcs[i].ss_s[j].ss_family == AF_INET) {
612 25 : have_v4_addr = true;
613 : } else {
614 25 : have_v6_addr = true;
615 : }
616 50 : if (have_v4_addr && have_v6_addr) {
617 25 : break;
618 : }
619 : }
620 : }
621 : }
622 :
623 25 : TALLOC_FREE(dcs);
624 :
625 25 : if (ret_count == 0) {
626 0 : TALLOC_FREE(dclist);
627 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
628 : }
629 :
630 25 : *returned_dclist = dclist;
631 25 : *return_count = ret_count;
632 25 : return NT_STATUS_OK;
633 : }
634 :
635 : /****************************************************************
636 : ****************************************************************/
637 :
638 34 : 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 34 : info = talloc_zero(mem_ctx, struct netr_DsRGetDCNameInfo);
653 34 : NT_STATUS_HAVE_NO_MEMORY(info);
654 :
655 34 : if (dc_unc) {
656 34 : if (!(dc_unc[0] == '\\' && dc_unc[1] == '\\')) {
657 32 : 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 34 : NT_STATUS_HAVE_NO_MEMORY(info->dc_unc);
663 : }
664 :
665 34 : if (dc_address) {
666 34 : if (!(dc_address[0] == '\\' && dc_address[1] == '\\')) {
667 34 : 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 34 : NT_STATUS_HAVE_NO_MEMORY(info->dc_address);
673 : }
674 :
675 34 : info->dc_address_type = dc_address_type;
676 :
677 34 : if (domain_guid) {
678 34 : info->domain_guid = *domain_guid;
679 : }
680 :
681 34 : if (domain_name) {
682 34 : info->domain_name = talloc_strdup(mem_ctx, domain_name);
683 34 : NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
684 : }
685 :
686 34 : if (forest_name && *forest_name) {
687 29 : info->forest_name = talloc_strdup(mem_ctx, forest_name);
688 29 : NT_STATUS_HAVE_NO_MEMORY(info->forest_name);
689 29 : flags |= DS_DNS_FOREST_ROOT;
690 : }
691 :
692 34 : info->dc_flags = flags;
693 :
694 34 : if (dc_site_name) {
695 30 : info->dc_site_name = talloc_strdup(mem_ctx, dc_site_name);
696 30 : NT_STATUS_HAVE_NO_MEMORY(info->dc_site_name);
697 : }
698 :
699 34 : if (client_site_name) {
700 30 : info->client_site_name = talloc_strdup(mem_ctx,
701 : client_site_name);
702 30 : NT_STATUS_HAVE_NO_MEMORY(info->client_site_name);
703 : }
704 :
705 34 : *info_out = info;
706 :
707 34 : return NT_STATUS_OK;
708 : }
709 :
710 : /****************************************************************
711 : ****************************************************************/
712 :
713 34 : 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 34 : 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 52 : if (dns_dc_name && dns_domain_name &&
735 47 : *dns_dc_name && *dns_domain_name) {
736 29 : *hostname_p = dns_dc_name;
737 29 : *domain_p = dns_domain_name;
738 29 : *dc_flags |= DS_DNS_DOMAIN | DS_DNS_CONTROLLER;
739 29 : break;
740 : }
741 9 : if (dc_name && domain_name &&
742 9 : *dc_name && *domain_name) {
743 5 : *hostname_p = dc_name;
744 5 : *domain_p = domain_name;
745 5 : break;
746 : }
747 : }
748 34 : }
749 :
750 : /****************************************************************
751 : ****************************************************************/
752 :
753 34 : 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 34 : const char *dc_hostname = NULL;
761 34 : const char *dc_domain_name = NULL;
762 34 : const char *dc_address = NULL;
763 34 : const char *dc_forest = NULL;
764 34 : uint32_t dc_address_type = 0;
765 34 : uint32_t dc_flags = 0;
766 34 : struct GUID *dc_domain_guid = NULL;
767 34 : const char *dc_server_site = NULL;
768 34 : const char *dc_client_site = NULL;
769 :
770 : char addr[INET6_ADDRSTRLEN];
771 :
772 34 : 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 5 : if (r->sockaddr.pdc_ip) {
778 5 : dc_address = r->sockaddr.pdc_ip;
779 5 : 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 34 : 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 34 : dc_flags |= r->server_type;
796 34 : dc_forest = r->forest;
797 34 : dc_domain_guid = &r->domain_uuid;
798 34 : dc_server_site = r->server_site;
799 34 : dc_client_site = r->client_site;
800 :
801 34 : 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 25 : 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 25 : size_t i = 0;
851 25 : bool valid_dc = false;
852 25 : struct netlogon_samlogon_response *r = NULL;
853 25 : uint32_t nt_version = NETLOGON_NT_VERSION_5 |
854 : NETLOGON_NT_VERSION_5EX;
855 25 : uint32_t ret_flags = 0;
856 : NTSTATUS status;
857 :
858 25 : nt_version |= map_ds_flags_to_nt_version(flags);
859 :
860 25 : for (i=0; i<num_dcs; i++) {
861 : char addr[INET6_ADDRSTRLEN];
862 :
863 25 : print_sockaddr(addr, sizeof(addr), &dclist[i].sa.u.ss);
864 :
865 25 : DEBUG(10,("LDAP ping to %s (%s)\n", dclist[i].hostname, addr));
866 :
867 25 : if (ads_cldap_netlogon(mem_ctx, &dclist[i].sa.u.ss,
868 : domain_name,
869 : nt_version,
870 : &r))
871 : {
872 25 : nt_version = r->ntver;
873 25 : ret_flags = get_cldap_reply_server_flags(r, nt_version);
874 :
875 25 : if (check_cldap_reply_required_flags(ret_flags, flags)) {
876 25 : valid_dc = true;
877 25 : break;
878 : }
879 : }
880 :
881 0 : continue;
882 : }
883 :
884 25 : if (!valid_dc) {
885 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
886 : }
887 :
888 25 : status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].sa,
889 25 : &r->data.nt5_ex, info);
890 25 : if (NT_STATUS_IS_OK(status)) {
891 25 : return store_cldap_reply(mem_ctx, flags, &dclist[i].sa,
892 25 : nt_version, &r->data.nt5_ex);
893 : }
894 :
895 0 : return status;
896 : }
897 :
898 : /****************************************************************
899 : ****************************************************************/
900 :
901 : /****************************************************************
902 : ****************************************************************/
903 :
904 4 : 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 4 : {
912 4 : enum nbt_name_type name_type = NBT_NAME_LOGON;
913 : NTSTATUS status;
914 : size_t i;
915 4 : const char *dc_name = NULL;
916 : fstring tmp_dc_name;
917 4 : struct netlogon_samlogon_response *r = NULL;
918 4 : bool store_cache = false;
919 4 : uint32_t nt_version = NETLOGON_NT_VERSION_1 |
920 : NETLOGON_NT_VERSION_5 |
921 : NETLOGON_NT_VERSION_5EX_WITH_IP;
922 4 : size_t len = strlen(lp_netbios_name());
923 4 : char my_acct_name[len+2];
924 :
925 4 : if (msg_ctx == NULL) {
926 0 : return NT_STATUS_INVALID_PARAMETER;
927 : }
928 :
929 4 : if (flags & DS_PDC_REQUIRED) {
930 0 : name_type = NBT_NAME_PDC;
931 : }
932 :
933 4 : nt_version |= map_ds_flags_to_nt_version(flags);
934 :
935 4 : snprintf(my_acct_name,
936 : sizeof(my_acct_name),
937 : "%s$",
938 : lp_netbios_name());
939 :
940 4 : DEBUG(10,("process_dc_netbios\n"));
941 :
942 7 : for (i=0; i<num_dcs; i++) {
943 : uint16_t val;
944 :
945 4 : generate_random_buffer((uint8_t *)&val, 2);
946 :
947 4 : 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 4 : 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 2 : goto make_reply;
957 : }
958 :
959 3 : if (name_status_find(domain_name,
960 : name_type,
961 : NBT_NAME_SERVER,
962 3 : &dclist[i].sa.u.ss,
963 : tmp_dc_name))
964 : {
965 : struct NETLOGON_SAM_LOGON_RESPONSE_NT40 logon1;
966 :
967 3 : r = talloc_zero(mem_ctx, struct netlogon_samlogon_response);
968 3 : NT_STATUS_HAVE_NO_MEMORY(r);
969 :
970 3 : ZERO_STRUCT(logon1);
971 :
972 3 : nt_version = NETLOGON_NT_VERSION_1;
973 :
974 3 : logon1.nt_version = nt_version;
975 3 : logon1.pdc_name = tmp_dc_name;
976 3 : logon1.domain_name = talloc_strdup_upper(mem_ctx, domain_name);
977 3 : NT_STATUS_HAVE_NO_MEMORY(logon1.domain_name);
978 :
979 3 : r->data.nt4 = logon1;
980 3 : r->ntver = nt_version;
981 :
982 3 : map_netlogon_samlogon_response(r);
983 :
984 3 : namecache_store(tmp_dc_name,
985 : NBT_NAME_SERVER,
986 : 1,
987 3 : &dclist[i].sa);
988 :
989 3 : goto make_reply;
990 : }
991 : }
992 :
993 0 : return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
994 :
995 4 : make_reply:
996 :
997 4 : status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].sa,
998 4 : &r->data.nt5_ex, info);
999 4 : 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 3 : return status;
1005 : }
1006 :
1007 : /****************************************************************
1008 : ****************************************************************/
1009 :
1010 31 : 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 31 : struct ip_service_name *dclist = NULL;
1020 31 : size_t num_dcs = 0;
1021 :
1022 31 : DEBUG(10,("dsgetdcname_rediscover\n"));
1023 :
1024 31 : if (flags & DS_IS_FLAT_NAME) {
1025 :
1026 1 : if (lp_disable_netbios()) {
1027 0 : return NT_STATUS_NOT_SUPPORTED;
1028 : }
1029 :
1030 1 : status = discover_dc_netbios(mem_ctx, domain_name, flags,
1031 : &dclist, &num_dcs);
1032 1 : NT_STATUS_NOT_OK_RETURN(status);
1033 :
1034 1 : return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags,
1035 : dclist, num_dcs, info);
1036 : }
1037 :
1038 30 : if (flags & DS_IS_DNS_NAME) {
1039 :
1040 27 : status = discover_dc_dns(mem_ctx, domain_name, domain_guid,
1041 : flags, site_name, &dclist, &num_dcs);
1042 27 : NT_STATUS_NOT_OK_RETURN(status);
1043 :
1044 25 : 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 35 : static bool is_closest_site(struct netr_DsRGetDCNameInfo *info)
1073 : {
1074 35 : if (info->dc_flags & DS_SERVER_CLOSEST) {
1075 29 : return true;
1076 : }
1077 :
1078 6 : if (!info->client_site_name) {
1079 5 : 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 37 : 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 37 : struct netr_DsRGetDCNameInfo *myinfo = NULL;
1107 37 : bool first = true;
1108 37 : struct netr_DsRGetDCNameInfo *first_info = NULL;
1109 :
1110 37 : 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 37 : *info = NULL;
1117 :
1118 37 : 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 37 : if (flags & DS_FORCE_REDISCOVERY) {
1124 31 : goto rediscover;
1125 : }
1126 :
1127 6 : status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
1128 : flags, site_name, &myinfo);
1129 6 : if (NT_STATUS_IS_OK(status)) {
1130 6 : *info = myinfo;
1131 6 : goto done;
1132 : }
1133 :
1134 0 : if (flags & DS_BACKGROUND_ONLY) {
1135 0 : goto done;
1136 : }
1137 :
1138 0 : rediscover:
1139 31 : status = dsgetdcname_rediscover(mem_ctx, msg_ctx, domain_name,
1140 : domain_guid, flags, site_name,
1141 : &myinfo);
1142 :
1143 37 : done:
1144 37 : if (!NT_STATUS_IS_OK(status)) {
1145 2 : if (!first) {
1146 0 : *info = first_info;
1147 0 : return NT_STATUS_OK;
1148 : }
1149 2 : return status;
1150 : }
1151 :
1152 35 : if (!first) {
1153 0 : TALLOC_FREE(first_info);
1154 35 : } 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 35 : *info = myinfo;
1163 35 : return NT_STATUS_OK;
1164 : }
1165 :
1166 : /********************************************************************
1167 : dsgetdcname.
1168 :
1169 : This will be the only public function here.
1170 : ********************************************************************/
1171 :
1172 36 : 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 36 : const char *query_site = NULL;
1182 36 : char *ptr_to_free = NULL;
1183 36 : bool retry_query_with_null = false;
1184 :
1185 36 : if ((site_name == NULL) || (site_name[0] == '\0')) {
1186 36 : ptr_to_free = sitename_fetch(mem_ctx, domain_name);
1187 36 : if (ptr_to_free != NULL) {
1188 30 : retry_query_with_null = true;
1189 : }
1190 36 : query_site = ptr_to_free;
1191 : } else {
1192 0 : query_site = site_name;
1193 : }
1194 :
1195 36 : status = dsgetdcname_internal(mem_ctx,
1196 : msg_ctx,
1197 : domain_name,
1198 : domain_guid,
1199 : query_site,
1200 : flags,
1201 : info);
1202 :
1203 36 : TALLOC_FREE(ptr_to_free);
1204 :
1205 36 : if (!NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1206 35 : return status;
1207 : }
1208 :
1209 : /* Should we try again with site_name == NULL ? */
1210 1 : if (retry_query_with_null) {
1211 1 : status = dsgetdcname_internal(mem_ctx,
1212 : msg_ctx,
1213 : domain_name,
1214 : domain_guid,
1215 : NULL,
1216 : flags,
1217 : info);
1218 : }
1219 :
1220 1 : 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 : }
|