2 Unix SMB/CIFS implementation.
3 async implementation of WINBINDD_DSGETDCNAME
4 Copyright (C) Volker Lendecke 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "librpc/gen_ndr/ndr_wbint_c.h"
24 struct winbindd_dsgetdcname_state
{
26 struct netr_DsRGetDCNameInfo
*dc_info
;
29 static uint32_t get_dsgetdc_flags(uint32_t wbc_flags
);
30 static void winbindd_dsgetdcname_done(struct tevent_req
*subreq
);
32 struct tevent_req
*winbindd_dsgetdcname_send(TALLOC_CTX
*mem_ctx
,
33 struct tevent_context
*ev
,
34 struct winbindd_cli_state
*cli
,
35 struct winbindd_request
*request
)
37 struct tevent_req
*req
, *subreq
;
38 struct winbindd_child
*child
;
39 struct winbindd_dsgetdcname_state
*state
;
40 struct GUID
*guid_ptr
= NULL
;
41 uint32_t ds_flags
= 0;
44 req
= tevent_req_create(mem_ctx
, &state
,
45 struct winbindd_dsgetdcname_state
);
50 request
->data
.dsgetdcname
.domain_name
51 [sizeof(request
->data
.dsgetdcname
.domain_name
)-1] = '\0';
52 request
->data
.dsgetdcname
.site_name
53 [sizeof(request
->data
.dsgetdcname
.site_name
)-1] = '\0';
54 request
->data
.dsgetdcname
.domain_guid
55 [sizeof(request
->data
.dsgetdcname
.domain_guid
)-1] = '\0';
57 DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)cli
->pid
,
58 request
->data
.dsgetdcname
.domain_name
));
60 ds_flags
= get_dsgetdc_flags(request
->flags
);
62 status
= GUID_from_string(request
->data
.dsgetdcname
.domain_guid
,
64 if (NT_STATUS_IS_OK(status
) && !GUID_all_zero(&state
->guid
)) {
65 guid_ptr
= &state
->guid
;
68 child
= locator_child();
70 subreq
= dcerpc_wbint_DsGetDcName_send(
71 state
, ev
, child
->binding_handle
,
72 request
->data
.dsgetdcname
.domain_name
, guid_ptr
,
73 request
->data
.dsgetdcname
.site_name
,
74 ds_flags
, &state
->dc_info
);
75 if (tevent_req_nomem(subreq
, req
)) {
76 return tevent_req_post(req
, ev
);
78 tevent_req_set_callback(subreq
, winbindd_dsgetdcname_done
, req
);
82 static void winbindd_dsgetdcname_done(struct tevent_req
*subreq
)
84 struct tevent_req
*req
= tevent_req_callback_data(
85 subreq
, struct tevent_req
);
86 struct winbindd_dsgetdcname_state
*state
= tevent_req_data(
87 req
, struct winbindd_dsgetdcname_state
);
88 NTSTATUS status
, result
;
90 status
= dcerpc_wbint_DsGetDcName_recv(subreq
, state
, &result
);
92 if (any_nt_status_not_ok(status
, result
, &status
)) {
93 tevent_req_nterror(req
, status
);
99 NTSTATUS
winbindd_dsgetdcname_recv(struct tevent_req
*req
,
100 struct winbindd_response
*response
)
102 struct winbindd_dsgetdcname_state
*state
= tevent_req_data(
103 req
, struct winbindd_dsgetdcname_state
);
107 if (tevent_req_is_nterror(req
, &status
)) {
108 DEBUG(5, ("dsgetdcname failed: %s\n", nt_errstr(status
)));
112 guid_str
= GUID_string(talloc_tos(), &state
->dc_info
->domain_guid
);
113 if (guid_str
== NULL
) {
114 return NT_STATUS_NO_MEMORY
;
117 fstrcpy(response
->data
.dsgetdcname
.dc_unc
,
118 state
->dc_info
->dc_unc
);
119 fstrcpy(response
->data
.dsgetdcname
.dc_address
,
120 state
->dc_info
->dc_address
);
121 response
->data
.dsgetdcname
.dc_address_type
=
122 state
->dc_info
->dc_address_type
;
123 fstrcpy(response
->data
.dsgetdcname
.domain_guid
, guid_str
);
124 TALLOC_FREE(guid_str
);
125 fstrcpy(response
->data
.dsgetdcname
.domain_name
,
126 state
->dc_info
->domain_name
);
127 fstrcpy(response
->data
.dsgetdcname
.forest_name
,
128 state
->dc_info
->forest_name
);
129 response
->data
.dsgetdcname
.dc_flags
= state
->dc_info
->dc_flags
;
130 fstrcpy(response
->data
.dsgetdcname
.dc_site_name
,
131 state
->dc_info
->dc_site_name
);
132 fstrcpy(response
->data
.dsgetdcname
.client_site_name
,
133 state
->dc_info
->client_site_name
);
138 static uint32_t get_dsgetdc_flags(uint32_t wbc_flags
)
140 struct wbc_flag_map
{
141 uint32_t wbc_dc_flag
;
142 uint32_t ds_dc_flags
;
143 } lookup_dc_flags
[] = {
144 { WBC_LOOKUP_DC_FORCE_REDISCOVERY
,
145 DS_FORCE_REDISCOVERY
},
146 { WBC_LOOKUP_DC_DS_REQUIRED
,
147 DS_DIRECTORY_SERVICE_REQUIRED
},
148 { WBC_LOOKUP_DC_DS_PREFERRED
,
149 DS_DIRECTORY_SERVICE_PREFERRED
},
150 { WBC_LOOKUP_DC_GC_SERVER_REQUIRED
,
151 DS_GC_SERVER_REQUIRED
},
152 { WBC_LOOKUP_DC_PDC_REQUIRED
,
154 { WBC_LOOKUP_DC_BACKGROUND_ONLY
,
155 DS_BACKGROUND_ONLY
},
156 { WBC_LOOKUP_DC_IP_REQUIRED
,
158 { WBC_LOOKUP_DC_KDC_REQUIRED
,
160 { WBC_LOOKUP_DC_TIMESERV_REQUIRED
,
161 DS_TIMESERV_REQUIRED
},
162 { WBC_LOOKUP_DC_WRITABLE_REQUIRED
,
163 DS_WRITABLE_REQUIRED
},
164 { WBC_LOOKUP_DC_GOOD_TIMESERV_PREFERRED
,
165 DS_GOOD_TIMESERV_PREFERRED
},
166 { WBC_LOOKUP_DC_AVOID_SELF
,
168 { WBC_LOOKUP_DC_ONLY_LDAP_NEEDED
,
169 DS_ONLY_LDAP_NEEDED
},
170 { WBC_LOOKUP_DC_IS_FLAT_NAME
,
172 { WBC_LOOKUP_DC_IS_DNS_NAME
,
174 { WBC_LOOKUP_DC_TRY_NEXTCLOSEST_SITE
,
175 DS_TRY_NEXTCLOSEST_SITE
},
176 { WBC_LOOKUP_DC_DS_6_REQUIRED
,
177 DS_DIRECTORY_SERVICE_6_REQUIRED
},
178 { WBC_LOOKUP_DC_RETURN_DNS_NAME
,
179 DS_RETURN_DNS_NAME
},
180 { WBC_LOOKUP_DC_RETURN_FLAT_NAME
,
181 DS_RETURN_FLAT_NAME
}
184 uint32_t ds_flags
= 0;
187 for (i
=0; i
<ARRAY_SIZE(lookup_dc_flags
); i
++) {
188 if (wbc_flags
& lookup_dc_flags
[i
].wbc_dc_flag
) {
189 ds_flags
|= lookup_dc_flags
[i
].ds_dc_flags
;