dsgetdcname: use existing messaging_context if possible.
[nivanova/samba-autobuild/.git] / source3 / libsmb / dsgetdcname.c
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
25 #define DSGETDCNAME_FMT "DSGETDCNAME/DOMAIN/%s"
26 /* 15 minutes */
27 #define DSGETDCNAME_CACHE_TTL   60*15
28
29 struct ip_service_name {
30         struct sockaddr_storage ss;
31         unsigned port;
32         const char *hostname;
33 };
34
35 static NTSTATUS make_dc_info_from_cldap_reply(TALLOC_CTX *mem_ctx,
36                                               uint32_t flags,
37                                               struct sockaddr_storage *ss,
38                                               uint32_t nt_version,
39                                               union nbt_cldap_netlogon *r,
40                                               struct netr_DsRGetDCNameInfo **info);
41
42 /****************************************************************
43 ****************************************************************/
44
45 void debug_dsdcinfo_flags(int lvl, uint32_t flags)
46 {
47         DEBUG(lvl,("debug_dsdcinfo_flags: 0x%08x\n\t", flags));
48
49         if (flags & DS_FORCE_REDISCOVERY)
50                 DEBUGADD(lvl,("DS_FORCE_REDISCOVERY "));
51         if (flags & 0x000000002)
52                 DEBUGADD(lvl,("0x00000002 "));
53         if (flags & 0x000000004)
54                 DEBUGADD(lvl,("0x00000004 "));
55         if (flags & 0x000000008)
56                 DEBUGADD(lvl,("0x00000008 "));
57         if (flags & DS_DIRECTORY_SERVICE_REQUIRED)
58                 DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_REQUIRED "));
59         if (flags & DS_DIRECTORY_SERVICE_PREFERRED)
60                 DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_PREFERRED "));
61         if (flags & DS_GC_SERVER_REQUIRED)
62                 DEBUGADD(lvl,("DS_GC_SERVER_REQUIRED "));
63         if (flags & DS_PDC_REQUIRED)
64                 DEBUGADD(lvl,("DS_PDC_REQUIRED "));
65         if (flags & DS_BACKGROUND_ONLY)
66                 DEBUGADD(lvl,("DS_BACKGROUND_ONLY "));
67         if (flags & DS_IP_REQUIRED)
68                 DEBUGADD(lvl,("DS_IP_REQUIRED "));
69         if (flags & DS_KDC_REQUIRED)
70                 DEBUGADD(lvl,("DS_KDC_REQUIRED "));
71         if (flags & DS_TIMESERV_REQUIRED)
72                 DEBUGADD(lvl,("DS_TIMESERV_REQUIRED "));
73         if (flags & DS_WRITABLE_REQUIRED)
74                 DEBUGADD(lvl,("DS_WRITABLE_REQUIRED "));
75         if (flags & DS_GOOD_TIMESERV_PREFERRED)
76                 DEBUGADD(lvl,("DS_GOOD_TIMESERV_PREFERRED "));
77         if (flags & DS_AVOID_SELF)
78                 DEBUGADD(lvl,("DS_AVOID_SELF "));
79         if (flags & DS_ONLY_LDAP_NEEDED)
80                 DEBUGADD(lvl,("DS_ONLY_LDAP_NEEDED "));
81         if (flags & DS_IS_FLAT_NAME)
82                 DEBUGADD(lvl,("DS_IS_FLAT_NAME "));
83         if (flags & DS_IS_DNS_NAME)
84                 DEBUGADD(lvl,("DS_IS_DNS_NAME "));
85         if (flags & 0x00040000)
86                 DEBUGADD(lvl,("0x00040000 "));
87         if (flags & 0x00080000)
88                 DEBUGADD(lvl,("0x00080000 "));
89         if (flags & 0x00100000)
90                 DEBUGADD(lvl,("0x00100000 "));
91         if (flags & 0x00200000)
92                 DEBUGADD(lvl,("0x00200000 "));
93         if (flags & 0x00400000)
94                 DEBUGADD(lvl,("0x00400000 "));
95         if (flags & 0x00800000)
96                 DEBUGADD(lvl,("0x00800000 "));
97         if (flags & 0x01000000)
98                 DEBUGADD(lvl,("0x01000000 "));
99         if (flags & 0x02000000)
100                 DEBUGADD(lvl,("0x02000000 "));
101         if (flags & 0x04000000)
102                 DEBUGADD(lvl,("0x04000000 "));
103         if (flags & 0x08000000)
104                 DEBUGADD(lvl,("0x08000000 "));
105         if (flags & 0x10000000)
106                 DEBUGADD(lvl,("0x10000000 "));
107         if (flags & 0x20000000)
108                 DEBUGADD(lvl,("0x20000000 "));
109         if (flags & DS_RETURN_DNS_NAME)
110                 DEBUGADD(lvl,("DS_RETURN_DNS_NAME "));
111         if (flags & DS_RETURN_FLAT_NAME)
112                 DEBUGADD(lvl,("DS_RETURN_FLAT_NAME "));
113         if (flags)
114                 DEBUGADD(lvl,("\n"));
115 }
116
117 /****************************************************************
118 ****************************************************************/
119
120 static char *dsgetdcname_cache_key(TALLOC_CTX *mem_ctx, const char *domain)
121 {
122         if (!mem_ctx || !domain) {
123                 return NULL;
124         }
125
126         return talloc_asprintf_strupper_m(mem_ctx, DSGETDCNAME_FMT, domain);
127 }
128
129 /****************************************************************
130 ****************************************************************/
131
132 static NTSTATUS dsgetdcname_cache_delete(TALLOC_CTX *mem_ctx,
133                                         const char *domain_name)
134 {
135         char *key;
136
137         if (!gencache_init()) {
138                 return NT_STATUS_INTERNAL_DB_ERROR;
139         }
140
141         key = dsgetdcname_cache_key(mem_ctx, domain_name);
142         if (!key) {
143                 return NT_STATUS_NO_MEMORY;
144         }
145
146         if (!gencache_del(key)) {
147                 return NT_STATUS_UNSUCCESSFUL;
148         }
149
150         return NT_STATUS_OK;
151 }
152
153 /****************************************************************
154 ****************************************************************/
155
156 static NTSTATUS dsgetdcname_cache_store(TALLOC_CTX *mem_ctx,
157                                         const char *domain_name,
158                                         const DATA_BLOB *blob)
159 {
160         time_t expire_time;
161         char *key;
162         bool ret = false;
163
164         if (!gencache_init()) {
165                 return NT_STATUS_INTERNAL_DB_ERROR;
166         }
167
168         key = dsgetdcname_cache_key(mem_ctx, domain_name);
169         if (!key) {
170                 return NT_STATUS_NO_MEMORY;
171         }
172
173         expire_time = time(NULL) + DSGETDCNAME_CACHE_TTL;
174
175         if (gencache_lock_entry(key) != 0) {
176                 return NT_STATUS_LOCK_NOT_GRANTED;
177         }
178
179         ret = gencache_set_data_blob(key, blob, expire_time);
180
181         gencache_unlock_entry(key);
182
183         return ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
184 }
185
186 /****************************************************************
187 ****************************************************************/
188
189 #define SET_STRING(x) \
190         talloc_strdup(mem_ctx, x); \
191         NT_STATUS_HAVE_NO_MEMORY(x);
192
193 static NTSTATUS map_logon29_from_cldap_reply(TALLOC_CTX *mem_ctx,
194                                              uint32_t flags,
195                                              struct sockaddr_storage *ss,
196                                              uint32_t nt_version,
197                                              union nbt_cldap_netlogon *r,
198                                              struct nbt_cldap_netlogon_29 *p)
199 {
200         char addr[INET6_ADDRSTRLEN];
201
202         ZERO_STRUCTP(p);
203
204         print_sockaddr(addr, sizeof(addr), ss);
205         p->dc_sock_addr_size = 0x10;
206         p->dc_sock_addr.sa_family = 2;
207         p->dc_sock_addr.pdc_ip = talloc_strdup(mem_ctx, addr);
208
209         switch (nt_version & 0x000000ff) {
210                 case 0:
211                         return NT_STATUS_INVALID_PARAMETER;
212                 case 1:
213                         p->pdc_name     = SET_STRING(r->logon1.pdc_name);
214                         p->domain       = SET_STRING(r->logon1.domain_name);
215
216                         if (flags & DS_PDC_REQUIRED) {
217                                 p->server_type = NBT_SERVER_WRITABLE |
218                                                  NBT_SERVER_PDC;
219                         }
220                         break;
221                 case 2:
222                 case 3:
223                         p->pdc_name     = SET_STRING(r->logon3.pdc_name);
224                         p->domain       = SET_STRING(r->logon3.domain_name);
225                         p->pdc_dns_name = SET_STRING(r->logon3.pdc_dns_name);
226                         p->dns_domain   = SET_STRING(r->logon3.dns_domain);
227                         p->server_type  = r->logon3.server_type;
228                         p->forest       = SET_STRING(r->logon3.forest);
229                         p->domain_uuid  = r->logon3.domain_uuid;
230
231                         break;
232                 case 4:
233                 case 5:
234                 case 6:
235                 case 7:
236                         p->pdc_name     = SET_STRING(r->logon5.pdc_name);
237                         p->domain       = SET_STRING(r->logon5.domain);
238                         p->pdc_dns_name = SET_STRING(r->logon5.pdc_dns_name);
239                         p->dns_domain   = SET_STRING(r->logon5.dns_domain);
240                         p->server_type  = r->logon5.server_type;
241                         p->forest       = SET_STRING(r->logon5.forest);
242                         p->domain_uuid  = r->logon5.domain_uuid;
243                         p->server_site  = SET_STRING(r->logon5.server_site);
244                         p->client_site  = SET_STRING(r->logon5.client_site);
245
246                         break;
247                 case 8:
248                 case 9:
249                 case 10:
250                 case 11:
251                 case 12:
252                 case 13:
253                 case 14:
254                 case 15:
255                         p->pdc_name     = SET_STRING(r->logon13.pdc_name);
256                         p->domain       = SET_STRING(r->logon13.domain);
257                         p->pdc_dns_name = SET_STRING(r->logon13.pdc_dns_name);
258                         p->dns_domain   = SET_STRING(r->logon13.dns_domain);
259                         p->server_type  = r->logon13.server_type;
260                         p->forest       = SET_STRING(r->logon13.forest);
261                         p->domain_uuid  = r->logon13.domain_uuid;
262                         p->server_site  = SET_STRING(r->logon13.server_site);
263                         p->client_site  = SET_STRING(r->logon13.client_site);
264
265                         break;
266                 default:
267                         p->pdc_name     = SET_STRING(r->logon29.pdc_name);
268                         p->domain       = SET_STRING(r->logon29.domain);
269                         p->pdc_dns_name = SET_STRING(r->logon29.pdc_dns_name);
270                         p->dns_domain   = SET_STRING(r->logon29.dns_domain);
271                         p->server_type  = r->logon29.server_type;
272                         p->forest       = SET_STRING(r->logon29.forest);
273                         p->domain_uuid  = r->logon29.domain_uuid;
274                         p->server_site  = SET_STRING(r->logon29.server_site);
275                         p->client_site  = SET_STRING(r->logon29.client_site);
276                         p->next_closest_site = SET_STRING(r->logon29.next_closest_site);
277
278                         break;
279         }
280
281         return NT_STATUS_OK;
282 }
283
284 /****************************************************************
285 ****************************************************************/
286
287 static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
288                                   uint32_t flags,
289                                   struct sockaddr_storage *ss,
290                                   uint32_t nt_version,
291                                   union nbt_cldap_netlogon *r)
292 {
293         DATA_BLOB blob;
294         enum ndr_err_code ndr_err;
295         NTSTATUS status;
296         struct nbt_cldap_netlogon_29 logon29;
297
298         status = map_logon29_from_cldap_reply(mem_ctx, flags, ss,
299                                               nt_version, r, &logon29);
300         if (!NT_STATUS_IS_OK(status)) {
301                 return status;
302         }
303
304         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &logon29,
305                        (ndr_push_flags_fn_t)ndr_push_nbt_cldap_netlogon_29);
306         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
307                 return ndr_map_error2ntstatus(ndr_err);
308         }
309
310         if (logon29.domain) {
311                 status = dsgetdcname_cache_store(mem_ctx, logon29.domain, &blob);
312                 if (!NT_STATUS_IS_OK(status)) {
313                         goto done;
314                 }
315         }
316         if (logon29.dns_domain) {
317                 status = dsgetdcname_cache_store(mem_ctx, logon29.dns_domain, &blob);
318                 if (!NT_STATUS_IS_OK(status)) {
319                         goto done;
320                 }
321         }
322
323  done:
324         data_blob_free(&blob);
325
326         return status;
327 }
328
329 /****************************************************************
330 ****************************************************************/
331
332 static NTSTATUS dsgetdcname_cache_refresh(TALLOC_CTX *mem_ctx,
333                                           struct messaging_context *msg_ctx,
334                                           const char *domain_name,
335                                           struct GUID *domain_guid,
336                                           uint32_t flags,
337                                           const char *site_name,
338                                           struct netr_DsRGetDCNameInfo *info)
339 {
340         struct netr_DsRGetDCNameInfo *dc_info;
341
342         return dsgetdcname(mem_ctx,
343                            msg_ctx,
344                            domain_name,
345                            domain_guid,
346                            site_name,
347                            flags | DS_FORCE_REDISCOVERY,
348                            &dc_info);
349 }
350
351 /****************************************************************
352 ****************************************************************/
353
354 static uint32_t get_cldap_reply_server_flags(union nbt_cldap_netlogon *r,
355                                              uint32_t nt_version)
356 {
357         switch (nt_version & 0x000000ff) {
358                 case 0:
359                 case 1:
360                         return 0;
361                 case 2:
362                 case 3:
363                         return r->logon3.server_type;
364                 case 4:
365                 case 5:
366                 case 6:
367                 case 7:
368                         return r->logon5.server_type;
369                 case 8:
370                 case 9:
371                 case 10:
372                 case 11:
373                 case 12:
374                 case 13:
375                 case 14:
376                 case 15:
377                         return r->logon13.server_type;
378                 default:
379                         return r->logon29.server_type;
380         }
381 }
382
383 /****************************************************************
384 ****************************************************************/
385
386 #define RETURN_ON_FALSE(x) if (!x) return false;
387
388 static bool check_cldap_reply_required_flags(uint32_t ret_flags,
389                                              uint32_t req_flags)
390 {
391         if (ret_flags == 0) {
392                 return true;
393         }
394
395         if (req_flags & DS_PDC_REQUIRED)
396                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_PDC);
397
398         if (req_flags & DS_GC_SERVER_REQUIRED)
399                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_GC);
400
401         if (req_flags & DS_ONLY_LDAP_NEEDED)
402                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_LDAP);
403
404         if ((req_flags & DS_DIRECTORY_SERVICE_REQUIRED) ||
405             (req_flags & DS_DIRECTORY_SERVICE_PREFERRED))
406                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_DS);
407
408         if (req_flags & DS_KDC_REQUIRED)
409                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_KDC);
410
411         if (req_flags & DS_TIMESERV_REQUIRED)
412                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_TIMESERV);
413
414         if (req_flags & DS_WRITABLE_REQUIRED)
415                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_WRITABLE);
416
417         return true;
418 }
419
420 /****************************************************************
421 ****************************************************************/
422
423 static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
424                                         const char *domain_name,
425                                         struct GUID *domain_guid,
426                                         uint32_t flags,
427                                         const char *site_name,
428                                         struct netr_DsRGetDCNameInfo **info_p,
429                                         bool *expired)
430 {
431         char *key;
432         DATA_BLOB blob;
433         enum ndr_err_code ndr_err;
434         struct netr_DsRGetDCNameInfo *info;
435         union nbt_cldap_netlogon p;
436         struct nbt_cldap_netlogon_29 r;
437         NTSTATUS status;
438
439         if (!gencache_init()) {
440                 return NT_STATUS_INTERNAL_DB_ERROR;
441         }
442
443         key = dsgetdcname_cache_key(mem_ctx, domain_name);
444         if (!key) {
445                 return NT_STATUS_NO_MEMORY;
446         }
447
448         if (!gencache_get_data_blob(key, &blob, expired)) {
449                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
450         }
451
452         info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
453         if (!info) {
454                 return NT_STATUS_NO_MEMORY;
455         }
456
457         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
458                       (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon_29);
459
460         data_blob_free(&blob);
461         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
462                 dsgetdcname_cache_delete(mem_ctx, domain_name);
463                 return ndr_map_error2ntstatus(ndr_err);
464         }
465
466         p.logon29 = r;
467
468         status = make_dc_info_from_cldap_reply(mem_ctx, flags, NULL,
469                                                NETLOGON_VERSION_WITH_CLOSEST_SITE,
470                                                &p, &info);
471         if (!NT_STATUS_IS_OK(status)) {
472                 return status;
473         }
474
475         if (DEBUGLEVEL >= 10) {
476                 NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, info);
477         }
478
479         /* check flags */
480         if (!check_cldap_reply_required_flags(info->dc_flags, flags)) {
481                 DEBUG(10,("invalid flags\n"));
482                 return NT_STATUS_INVALID_PARAMETER;
483         }
484
485         if ((flags & DS_IP_REQUIRED) &&
486             (info->dc_address_type != DS_ADDRESS_TYPE_INET)) {
487                 return NT_STATUS_INVALID_PARAMETER_MIX;
488         }
489
490         *info_p = info;
491
492         return NT_STATUS_OK;
493 }
494
495 /****************************************************************
496 ****************************************************************/
497
498 static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx,
499                                    struct messaging_context *msg_ctx,
500                                    const char *domain_name,
501                                    struct GUID *domain_guid,
502                                    uint32_t flags,
503                                    const char *site_name,
504                                    struct netr_DsRGetDCNameInfo **info)
505 {
506         NTSTATUS status;
507         bool expired = false;
508
509         status = dsgetdcname_cache_fetch(mem_ctx, domain_name, domain_guid,
510                                          flags, site_name, info, &expired);
511         if (!NT_STATUS_IS_OK(status)) {
512                 DEBUG(10,("dsgetdcname_cached: cache fetch failed with: %s\n",
513                         nt_errstr(status)));
514                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
515         }
516
517         if (flags & DS_BACKGROUND_ONLY) {
518                 return status;
519         }
520
521         if (expired) {
522                 status = dsgetdcname_cache_refresh(mem_ctx, msg_ctx,
523                                                    domain_name,
524                                                    domain_guid, flags,
525                                                    site_name, *info);
526                 if (!NT_STATUS_IS_OK(status)) {
527                         return status;
528                 }
529         }
530
531         return status;
532 }
533
534 /****************************************************************
535 ****************************************************************/
536
537 static bool check_allowed_required_flags(uint32_t flags)
538 {
539         uint32_t return_type = flags & (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME);
540         uint32_t offered_type = flags & (DS_IS_FLAT_NAME|DS_IS_DNS_NAME);
541         uint32_t query_type = flags & (DS_BACKGROUND_ONLY|DS_FORCE_REDISCOVERY);
542
543         /* FIXME: check for DSGETDC_VALID_FLAGS and check for excluse bits
544          * (DS_PDC_REQUIRED, DS_KDC_REQUIRED, DS_GC_SERVER_REQUIRED) */
545
546         debug_dsdcinfo_flags(10, flags);
547
548         if (return_type == (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME)) {
549                 return false;
550         }
551
552         if (offered_type == (DS_IS_DNS_NAME|DS_IS_FLAT_NAME)) {
553                 return false;
554         }
555
556         if (query_type == (DS_BACKGROUND_ONLY|DS_FORCE_REDISCOVERY)) {
557                 return false;
558         }
559
560 #if 0
561         if ((flags & DS_RETURN_DNS_NAME) && (!(flags & DS_IP_REQUIRED))) {
562                 printf("gd: here5 \n");
563                 return false;
564         }
565 #endif
566         return true;
567 }
568
569 /****************************************************************
570 ****************************************************************/
571
572 static NTSTATUS discover_dc_netbios(TALLOC_CTX *mem_ctx,
573                                     const char *domain_name,
574                                     uint32_t flags,
575                                     struct ip_service_name **returned_dclist,
576                                     int *returned_count)
577 {
578         NTSTATUS status;
579         enum nbt_name_type name_type = NBT_NAME_LOGON;
580         struct ip_service *iplist;
581         int i;
582         struct ip_service_name *dclist = NULL;
583         int count;
584
585         *returned_dclist = NULL;
586         *returned_count = 0;
587
588         if (lp_disable_netbios()) {
589                 return NT_STATUS_NOT_SUPPORTED;
590         }
591
592         if (flags & DS_PDC_REQUIRED) {
593                 name_type = NBT_NAME_PDC;
594         }
595
596         status = internal_resolve_name(domain_name, name_type, NULL,
597                                        &iplist, &count,
598                                        "lmhosts wins bcast");
599         if (!NT_STATUS_IS_OK(status)) {
600                 DEBUG(10,("discover_dc_netbios: failed to find DC\n"));
601                 return status;
602         }
603
604         dclist = TALLOC_ZERO_ARRAY(mem_ctx, struct ip_service_name, count);
605         if (!dclist) {
606                 return NT_STATUS_NO_MEMORY;
607         }
608
609         for (i=0; i<count; i++) {
610
611                 char addr[INET6_ADDRSTRLEN];
612                 struct ip_service_name *r = &dclist[i];
613
614                 print_sockaddr(addr, sizeof(addr),
615                                &iplist[i].ss);
616
617                 r->ss   = iplist[i].ss;
618                 r->port = iplist[i].port;
619                 r->hostname = talloc_strdup(mem_ctx, addr);
620                 if (!r->hostname) {
621                         return NT_STATUS_NO_MEMORY;
622                 }
623
624         }
625
626         *returned_dclist = dclist;
627         *returned_count = count;
628
629         return NT_STATUS_OK;
630 }
631
632 /****************************************************************
633 ****************************************************************/
634
635 static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
636                                 const char *domain_name,
637                                 struct GUID *domain_guid,
638                                 uint32_t flags,
639                                 const char *site_name,
640                                 struct ip_service_name **returned_dclist,
641                                 int *return_count)
642 {
643         int i, j;
644         NTSTATUS status;
645         struct dns_rr_srv *dcs = NULL;
646         int numdcs = 0;
647         int numaddrs = 0;
648         struct ip_service_name *dclist = NULL;
649         int count = 0;
650
651         if (flags & DS_PDC_REQUIRED) {
652                 status = ads_dns_query_pdc(mem_ctx, domain_name,
653                                            &dcs, &numdcs);
654         } else if (flags & DS_GC_SERVER_REQUIRED) {
655                 status = ads_dns_query_gcs(mem_ctx, domain_name, site_name,
656                                            &dcs, &numdcs);
657         } else if (flags & DS_KDC_REQUIRED) {
658                 status = ads_dns_query_kdcs(mem_ctx, domain_name, site_name,
659                                             &dcs, &numdcs);
660         } else if (flags & DS_DIRECTORY_SERVICE_REQUIRED) {
661                 status = ads_dns_query_dcs(mem_ctx, domain_name, site_name,
662                                            &dcs, &numdcs);
663         } else if (domain_guid) {
664                 status = ads_dns_query_dcs_guid(mem_ctx, domain_name,
665                                                 domain_guid, &dcs, &numdcs);
666         } else {
667                 status = ads_dns_query_dcs(mem_ctx, domain_name, site_name,
668                                            &dcs, &numdcs);
669         }
670
671         if (!NT_STATUS_IS_OK(status)) {
672                 return status;
673         }
674
675         if (numdcs == 0) {
676                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
677         }
678
679         for (i=0;i<numdcs;i++) {
680                 numaddrs += MAX(dcs[i].num_ips,1);
681         }
682
683         dclist = TALLOC_ZERO_ARRAY(mem_ctx,
684                                    struct ip_service_name,
685                                    numaddrs);
686         if (!dclist) {
687                 return NT_STATUS_NO_MEMORY;
688         }
689
690         /* now unroll the list of IP addresses */
691
692         *return_count = 0;
693         i = 0;
694         j = 0;
695
696         while ((i < numdcs) && (count < numaddrs)) {
697
698                 struct ip_service_name *r = &dclist[count];
699
700                 r->port = dcs[count].port;
701                 r->hostname = dcs[count].hostname;
702
703                 /* If we don't have an IP list for a name, lookup it up */
704
705                 if (!dcs[i].ss_s) {
706                         interpret_string_addr(&r->ss, dcs[i].hostname, 0);
707                         i++;
708                         j = 0;
709                 } else {
710                         /* use the IP addresses from the SRV sresponse */
711
712                         if (j >= dcs[i].num_ips) {
713                                 i++;
714                                 j = 0;
715                                 continue;
716                         }
717
718                         r->ss = dcs[i].ss_s[j];
719                         j++;
720                 }
721
722                 /* make sure it is a valid IP.  I considered checking the
723                  * negative connection cache, but this is the wrong place for
724                  * it.  Maybe only as a hac.  After think about it, if all of
725                  * the IP addresses retuend from DNS are dead, what hope does a
726                  * netbios name lookup have?  The standard reason for falling
727                  * back to netbios lookups is that our DNS server doesn't know
728                  * anything about the DC's   -- jerry */
729
730                 if (!is_zero_addr(&r->ss)) {
731                         count++;
732                         continue;
733                 }
734         }
735
736         *returned_dclist = dclist;
737         *return_count = count;
738
739         if (count > 0) {
740                 return NT_STATUS_OK;
741         }
742
743         return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
744 }
745
746 /****************************************************************
747 ****************************************************************/
748
749 static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx,
750                                             const char *dc_unc,
751                                             const char *dc_address,
752                                             uint32_t dc_address_type,
753                                             const struct GUID *domain_guid,
754                                             const char *domain_name,
755                                             const char *forest_name,
756                                             uint32_t flags,
757                                             const char *dc_site_name,
758                                             const char *client_site_name,
759                                             struct netr_DsRGetDCNameInfo **info_out)
760 {
761         struct netr_DsRGetDCNameInfo *info;
762
763         info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
764         NT_STATUS_HAVE_NO_MEMORY(info);
765
766         if (dc_unc) {
767                 info->dc_unc = talloc_strdup(mem_ctx, dc_unc);
768                 NT_STATUS_HAVE_NO_MEMORY(info->dc_unc);
769         }
770
771         if (dc_address) {
772                 if (!(dc_address[0] == '\\' && dc_address[1] == '\\')) {
773                         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
774                                                            dc_address);
775                 } else {
776                         info->dc_address = talloc_strdup(mem_ctx, dc_address);
777                 }
778                 NT_STATUS_HAVE_NO_MEMORY(info->dc_address);
779         }
780
781         info->dc_address_type = dc_address_type;
782
783         if (domain_guid) {
784                 info->domain_guid = *domain_guid;
785         }
786
787         if (domain_name) {
788                 info->domain_name = talloc_strdup(mem_ctx, domain_name);
789                 NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
790         }
791
792         if (forest_name && *forest_name) {
793                 info->forest_name = talloc_strdup(mem_ctx, forest_name);
794                 NT_STATUS_HAVE_NO_MEMORY(info->forest_name);
795                 flags |= DS_DNS_FOREST;
796         }
797
798         info->dc_flags = flags;
799
800         if (dc_site_name) {
801                 info->dc_site_name = talloc_strdup(mem_ctx, dc_site_name);
802                 NT_STATUS_HAVE_NO_MEMORY(info->dc_site_name);
803         }
804
805         if (client_site_name) {
806                 info->client_site_name = talloc_strdup(mem_ctx,
807                                                        client_site_name);
808                 NT_STATUS_HAVE_NO_MEMORY(info->client_site_name);
809         }
810
811         *info_out = info;
812
813         return NT_STATUS_OK;
814 }
815
816 /****************************************************************
817 ****************************************************************/
818
819 static void map_dc_and_domain_names(uint32_t flags,
820                                     const char *dc_name,
821                                     const char *domain_name,
822                                     const char *dns_dc_name,
823                                     const char *dns_domain_name,
824                                     uint32_t *dc_flags,
825                                     const char **hostname_p,
826                                     const char **domain_p)
827 {
828         switch (flags & 0xf0000000) {
829                 case DS_RETURN_FLAT_NAME:
830                         if (dc_name && domain_name &&
831                             *dc_name && *domain_name) {
832                                 *hostname_p = dc_name;
833                                 *domain_p = domain_name;
834                                 break;
835                         }
836                 case DS_RETURN_DNS_NAME:
837                 default:
838                         if (dns_dc_name && dns_domain_name &&
839                             *dns_dc_name && *dns_domain_name) {
840                                 *hostname_p = dns_dc_name;
841                                 *domain_p = dns_domain_name;
842                                 *dc_flags |= DS_DNS_DOMAIN | DS_DNS_CONTROLLER;
843                                 break;
844                         }
845                         if (dc_name && domain_name &&
846                             *dc_name && *domain_name) {
847                                 *hostname_p = dc_name;
848                                 *domain_p = domain_name;
849                                 break;
850                         }
851         }
852 }
853
854 /****************************************************************
855 ****************************************************************/
856
857 static NTSTATUS make_dc_info_from_cldap_reply(TALLOC_CTX *mem_ctx,
858                                               uint32_t flags,
859                                               struct sockaddr_storage *ss,
860                                               uint32_t nt_version,
861                                               union nbt_cldap_netlogon *r,
862                                               struct netr_DsRGetDCNameInfo **info)
863 {
864         const char *dc_hostname, *dc_domain_name;
865         const char *dc_address = NULL;
866         const char *dc_forest = NULL;
867         uint32_t dc_address_type = 0;
868         uint32_t dc_flags = 0;
869         struct GUID *dc_domain_guid = NULL;
870         const char *dc_server_site = NULL;
871         const char *dc_client_site = NULL;
872
873         char addr[INET6_ADDRSTRLEN];
874
875         if (ss) {
876                 print_sockaddr(addr, sizeof(addr), ss);
877                 dc_address = addr;
878                 dc_address_type = DS_ADDRESS_TYPE_INET;
879         }
880
881         switch (nt_version & 0x000000ff) {
882                 case 0:
883                         return NT_STATUS_INVALID_PARAMETER;
884                 case 1:
885                         if (!ss) {
886                                 dc_address      = r->logon1.pdc_name;
887                                 dc_address_type = DS_ADDRESS_TYPE_NETBIOS;
888                         }
889
890                         map_dc_and_domain_names(flags,
891                                                 r->logon1.pdc_name,
892                                                 r->logon1.domain_name,
893                                                 NULL,
894                                                 NULL,
895                                                 &dc_flags,
896                                                 &dc_hostname,
897                                                 &dc_domain_name);
898
899                         if (flags & DS_PDC_REQUIRED) {
900                                 dc_flags = NBT_SERVER_WRITABLE | NBT_SERVER_PDC;
901                         }
902                         break;
903                 case 2:
904                 case 3:
905                         if (!ss) {
906                                 dc_address      = r->logon3.pdc_ip;
907                                 dc_address_type = DS_ADDRESS_TYPE_INET;
908                         }
909
910                         map_dc_and_domain_names(flags,
911                                                 r->logon3.pdc_name,
912                                                 r->logon3.domain_name,
913                                                 r->logon3.pdc_dns_name,
914                                                 r->logon3.dns_domain,
915                                                 &dc_flags,
916                                                 &dc_hostname,
917                                                 &dc_domain_name);
918
919                         dc_flags        |= r->logon3.server_type;
920                         dc_forest       = r->logon3.forest;
921                         dc_domain_guid  = &r->logon3.domain_uuid;
922
923                         break;
924                 case 4:
925                 case 5:
926                 case 6:
927                 case 7:
928                         if (!ss) {
929                                 dc_address      = r->logon5.pdc_name;
930                                 dc_address_type = DS_ADDRESS_TYPE_NETBIOS;
931                         }
932
933                         map_dc_and_domain_names(flags,
934                                                 r->logon5.pdc_name,
935                                                 r->logon5.domain,
936                                                 r->logon5.pdc_dns_name,
937                                                 r->logon5.dns_domain,
938                                                 &dc_flags,
939                                                 &dc_hostname,
940                                                 &dc_domain_name);
941
942                         dc_flags        |= r->logon5.server_type;
943                         dc_forest       = r->logon5.forest;
944                         dc_domain_guid  = &r->logon5.domain_uuid;
945                         dc_server_site  = r->logon5.server_site;
946                         dc_client_site  = r->logon5.client_site;
947
948                         break;
949                 case 8:
950                 case 9:
951                 case 10:
952                 case 11:
953                 case 12:
954                 case 13:
955                 case 14:
956                 case 15:
957                         if (!ss) {
958                                 dc_address      = r->logon13.dc_sock_addr.pdc_ip;
959                                 dc_address_type = DS_ADDRESS_TYPE_INET;
960                         }
961
962                         map_dc_and_domain_names(flags,
963                                                 r->logon13.pdc_name,
964                                                 r->logon13.domain,
965                                                 r->logon13.pdc_dns_name,
966                                                 r->logon13.dns_domain,
967                                                 &dc_flags,
968                                                 &dc_hostname,
969                                                 &dc_domain_name);
970
971                         dc_flags        |= r->logon13.server_type;
972                         dc_forest       = r->logon13.forest;
973                         dc_domain_guid  = &r->logon13.domain_uuid;
974                         dc_server_site  = r->logon13.server_site;
975                         dc_client_site  = r->logon13.client_site;
976
977                         break;
978                 default:
979                         if (!ss) {
980                                 dc_address      = r->logon29.dc_sock_addr.pdc_ip;
981                                 dc_address_type = DS_ADDRESS_TYPE_INET;
982                         }
983
984                         map_dc_and_domain_names(flags,
985                                                 r->logon29.pdc_name,
986                                                 r->logon29.domain,
987                                                 r->logon29.pdc_dns_name,
988                                                 r->logon29.dns_domain,
989                                                 &dc_flags,
990                                                 &dc_hostname,
991                                                 &dc_domain_name);
992
993                         dc_flags        |= r->logon29.server_type;
994                         dc_forest       = r->logon29.forest;
995                         dc_domain_guid  = &r->logon29.domain_uuid;
996                         dc_server_site  = r->logon29.server_site;
997                         dc_client_site  = r->logon29.client_site;
998
999                         break;
1000         }
1001
1002         return make_domain_controller_info(mem_ctx,
1003                                            dc_hostname,
1004                                            dc_address,
1005                                            dc_address_type,
1006                                            dc_domain_guid,
1007                                            dc_domain_name,
1008                                            dc_forest,
1009                                            dc_flags,
1010                                            dc_server_site,
1011                                            dc_client_site,
1012                                            info);
1013 }
1014
1015 /****************************************************************
1016 ****************************************************************/
1017
1018 static uint32_t map_ds_flags_to_nt_version(uint32_t flags)
1019 {
1020         uint32_t nt_version = 0;
1021
1022         if (flags & DS_PDC_REQUIRED) {
1023                 nt_version |= NETLOGON_VERSION_PDC;
1024         }
1025
1026         if (flags & DS_GC_SERVER_REQUIRED) {
1027                 nt_version |= NETLOGON_VERSION_GC;
1028         }
1029
1030         if (flags & DS_TRY_NEXTCLOSEST_SITE) {
1031                 nt_version |= NETLOGON_VERSION_WITH_CLOSEST_SITE;
1032         }
1033
1034         if (flags & DS_IP_REQUIRED) {
1035                 nt_version |= NETLOGON_VERSION_IP;
1036         }
1037
1038         return nt_version;
1039 }
1040
1041 /****************************************************************
1042 ****************************************************************/
1043
1044 static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
1045                                const char *domain_name,
1046                                uint32_t flags,
1047                                struct ip_service_name *dclist,
1048                                int num_dcs,
1049                                struct netr_DsRGetDCNameInfo **info)
1050 {
1051         int i = 0;
1052         bool valid_dc = false;
1053         union nbt_cldap_netlogon *r = NULL;
1054         uint32_t nt_version = NETLOGON_VERSION_5 |
1055                               NETLOGON_VERSION_5EX;
1056         uint32_t ret_flags = 0;
1057         NTSTATUS status;
1058
1059         nt_version |= map_ds_flags_to_nt_version(flags);
1060
1061         for (i=0; i<num_dcs; i++) {
1062
1063                 DEBUG(10,("LDAP ping to %s\n", dclist[i].hostname));
1064
1065                 if (ads_cldap_netlogon(mem_ctx, dclist[i].hostname,
1066                                         domain_name,
1067                                         &nt_version,
1068                                         &r))
1069                 {
1070                         ret_flags = get_cldap_reply_server_flags(r, nt_version);
1071
1072                         if (check_cldap_reply_required_flags(ret_flags, flags)) {
1073                                 valid_dc = true;
1074                                 break;
1075                         }
1076                 }
1077
1078                 continue;
1079         }
1080
1081         if (!valid_dc) {
1082                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1083         }
1084
1085         status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].ss,
1086                                                nt_version, r, info);
1087         if (NT_STATUS_IS_OK(status)) {
1088                 return store_cldap_reply(mem_ctx, flags, &dclist[i].ss,
1089                                          nt_version, r);
1090         }
1091
1092         return status;
1093 }
1094
1095 /****************************************************************
1096 ****************************************************************/
1097
1098 static struct event_context *ev_context(void)
1099 {
1100         static struct event_context *ctx;
1101
1102         if (!ctx && !(ctx = event_context_init(NULL))) {
1103                 smb_panic("Could not init event context");
1104         }
1105         return ctx;
1106 }
1107
1108 /****************************************************************
1109 ****************************************************************/
1110
1111 static struct messaging_context *msg_context(TALLOC_CTX *mem_ctx)
1112 {
1113         static struct messaging_context *ctx;
1114
1115         if (!ctx && !(ctx = messaging_init(mem_ctx, server_id_self(),
1116                                            ev_context()))) {
1117                 smb_panic("Could not init messaging context");
1118         }
1119         return ctx;
1120 }
1121
1122 /****************************************************************
1123 ****************************************************************/
1124
1125 static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
1126                                    struct messaging_context *msg_ctx,
1127                                    const char *domain_name,
1128                                    uint32_t flags,
1129                                    struct ip_service_name *dclist,
1130                                    int num_dcs,
1131                                    struct netr_DsRGetDCNameInfo **info)
1132 {
1133         struct sockaddr_storage ss;
1134         struct ip_service ip_list;
1135         enum nbt_name_type name_type = NBT_NAME_LOGON;
1136         NTSTATUS status;
1137         int i;
1138         const char *dc_name = NULL;
1139         fstring tmp_dc_name;
1140         union nbt_cldap_netlogon *r = NULL;
1141         uint32_t nt_version = NETLOGON_VERSION_1 |
1142                               NETLOGON_VERSION_5 |
1143                               NETLOGON_VERSION_5EX_WITH_IP;
1144
1145         if (!msg_ctx) {
1146                 msg_ctx = msg_context(mem_ctx);
1147         }
1148
1149         if (flags & DS_PDC_REQUIRED) {
1150                 name_type = NBT_NAME_PDC;
1151         }
1152
1153         nt_version |= map_ds_flags_to_nt_version(flags);
1154
1155         DEBUG(10,("process_dc_netbios\n"));
1156
1157         for (i=0; i<num_dcs; i++) {
1158
1159                 ip_list.ss = dclist[i].ss;
1160                 ip_list.port = 0;
1161
1162                 if (!interpret_string_addr(&ss, dclist[i].hostname, AI_NUMERICHOST)) {
1163                         return NT_STATUS_UNSUCCESSFUL;
1164                 }
1165
1166                 if (send_getdc_request(mem_ctx, msg_ctx,
1167                                        &dclist[i].ss, domain_name,
1168                                        NULL, nt_version))
1169                 {
1170                         int k;
1171                         smb_msleep(300);
1172                         for (k=0; k<5; k++) {
1173                                 if (receive_getdc_response(mem_ctx,
1174                                                            &dclist[i].ss,
1175                                                            domain_name,
1176                                                            &nt_version,
1177                                                            &dc_name,
1178                                                            &r)) {
1179                                         namecache_store(dc_name, NBT_NAME_SERVER, 1, &ip_list);
1180                                         goto make_reply;
1181                                 }
1182                                 smb_msleep(1500);
1183                         }
1184                 }
1185
1186                 if (name_status_find(domain_name,
1187                                      name_type,
1188                                      NBT_NAME_SERVER,
1189                                      &dclist[i].ss,
1190                                      tmp_dc_name))
1191                 {
1192                         struct nbt_cldap_netlogon_1 logon1;
1193
1194                         r = TALLOC_ZERO_P(mem_ctx, union nbt_cldap_netlogon);
1195                         NT_STATUS_HAVE_NO_MEMORY(r);
1196
1197                         ZERO_STRUCT(logon1);
1198
1199                         nt_version = NETLOGON_VERSION_1;
1200
1201                         logon1.nt_version = nt_version;
1202                         logon1.pdc_name = tmp_dc_name;
1203                         logon1.domain_name = talloc_strdup_upper(mem_ctx, domain_name);
1204                         NT_STATUS_HAVE_NO_MEMORY(logon1.domain_name);
1205
1206                         r->logon1 = logon1;
1207
1208                         namecache_store(tmp_dc_name, NBT_NAME_SERVER, 1, &ip_list);
1209
1210                         goto make_reply;
1211                 }
1212         }
1213
1214         return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1215
1216  make_reply:
1217
1218         status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].ss,
1219                                                nt_version, r, info);
1220         if (NT_STATUS_IS_OK(status)) {
1221                 return store_cldap_reply(mem_ctx, flags, &dclist[i].ss,
1222                                          nt_version, r);
1223         }
1224
1225         return status;
1226 }
1227
1228 /****************************************************************
1229 ****************************************************************/
1230
1231 static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
1232                                        struct messaging_context *msg_ctx,
1233                                        const char *domain_name,
1234                                        struct GUID *domain_guid,
1235                                        uint32_t flags,
1236                                        const char *site_name,
1237                                        struct netr_DsRGetDCNameInfo **info)
1238 {
1239         NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1240         struct ip_service_name *dclist = NULL;
1241         int num_dcs;
1242
1243         DEBUG(10,("dsgetdcname_rediscover\n"));
1244
1245         if (flags & DS_IS_FLAT_NAME) {
1246
1247                 status = discover_dc_netbios(mem_ctx, domain_name, flags,
1248                                              &dclist, &num_dcs);
1249                 NT_STATUS_NOT_OK_RETURN(status);
1250
1251                 return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags,
1252                                           dclist, num_dcs, info);
1253         }
1254
1255         if (flags & DS_IS_DNS_NAME) {
1256
1257                 status = discover_dc_dns(mem_ctx, domain_name, domain_guid,
1258                                          flags, site_name, &dclist, &num_dcs);
1259                 NT_STATUS_NOT_OK_RETURN(status);
1260
1261                 return process_dc_dns(mem_ctx, domain_name, flags,
1262                                       dclist, num_dcs, info);
1263         }
1264
1265         status = discover_dc_dns(mem_ctx, domain_name, domain_guid, flags,
1266                                  site_name, &dclist, &num_dcs);
1267
1268         if (NT_STATUS_IS_OK(status) && num_dcs != 0) {
1269
1270                 status = process_dc_dns(mem_ctx, domain_name, flags, dclist,
1271                                         num_dcs, info);
1272                 if (NT_STATUS_IS_OK(status)) {
1273                         return status;
1274                 }
1275         }
1276
1277         status = discover_dc_netbios(mem_ctx, domain_name, flags, &dclist,
1278                                      &num_dcs);
1279         NT_STATUS_NOT_OK_RETURN(status);
1280
1281         return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags, dclist,
1282                                   num_dcs, info);
1283 }
1284
1285 /********************************************************************
1286  dsgetdcname.
1287
1288  This will be the only public function here.
1289 ********************************************************************/
1290
1291 NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
1292                      struct messaging_context *msg_ctx,
1293                      const char *domain_name,
1294                      struct GUID *domain_guid,
1295                      const char *site_name,
1296                      uint32_t flags,
1297                      struct netr_DsRGetDCNameInfo **info)
1298 {
1299         NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1300         struct netr_DsRGetDCNameInfo *myinfo = NULL;
1301
1302         DEBUG(10,("dsgetdcname: domain_name: %s, "
1303                   "domain_guid: %s, site_name: %s, flags: 0x%08x\n",
1304                   domain_name,
1305                   domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)",
1306                   site_name, flags));
1307
1308         *info = NULL;
1309
1310         if (!check_allowed_required_flags(flags)) {
1311                 DEBUG(0,("invalid flags specified\n"));
1312                 return NT_STATUS_INVALID_PARAMETER;
1313         }
1314
1315         if (flags & DS_FORCE_REDISCOVERY) {
1316                 goto rediscover;
1317         }
1318
1319         status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
1320                                     flags, site_name, &myinfo);
1321         if (NT_STATUS_IS_OK(status)) {
1322                 *info = myinfo;
1323                 return status;
1324         }
1325
1326         if (flags & DS_BACKGROUND_ONLY) {
1327                 return status;
1328         }
1329
1330  rediscover:
1331         status = dsgetdcname_rediscover(mem_ctx, msg_ctx, domain_name,
1332                                         domain_guid, flags, site_name,
1333                                         &myinfo);
1334
1335         if (NT_STATUS_IS_OK(status)) {
1336                 *info = myinfo;
1337         }
1338
1339         return status;
1340 }