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_winbind_c.h"
23 #include "lib/util/string_wrappers.h"
25 struct winbindd_dsgetdcname_state
{
27 struct netr_DsRGetDCNameInfo
*dc_info
;
30 static uint32_t get_dsgetdc_flags(uint32_t wbc_flags
);
31 static void winbindd_dsgetdcname_done(struct tevent_req
*subreq
);
33 struct tevent_req
*winbindd_dsgetdcname_send(TALLOC_CTX
*mem_ctx
,
34 struct tevent_context
*ev
,
35 struct winbindd_cli_state
*cli
,
36 struct winbindd_request
*request
)
38 struct tevent_req
*req
, *subreq
;
39 struct dcerpc_binding_handle
*child_binding_handle
= NULL
;
40 struct winbindd_dsgetdcname_state
*state
;
41 struct GUID
*guid_ptr
= NULL
;
42 uint32_t ds_flags
= 0;
45 req
= tevent_req_create(mem_ctx
, &state
,
46 struct winbindd_dsgetdcname_state
);
51 request
->data
.dsgetdcname
.domain_name
52 [sizeof(request
->data
.dsgetdcname
.domain_name
)-1] = '\0';
53 request
->data
.dsgetdcname
.site_name
54 [sizeof(request
->data
.dsgetdcname
.site_name
)-1] = '\0';
55 request
->data
.dsgetdcname
.domain_guid
56 [sizeof(request
->data
.dsgetdcname
.domain_guid
)-1] = '\0';
58 DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)cli
->pid
,
59 request
->data
.dsgetdcname
.domain_name
));
61 ds_flags
= get_dsgetdc_flags(request
->data
.dsgetdcname
.flags
);
63 status
= GUID_from_string(request
->data
.dsgetdcname
.domain_guid
,
65 if (NT_STATUS_IS_OK(status
) && !GUID_all_zero(&state
->guid
)) {
66 guid_ptr
= &state
->guid
;
69 child_binding_handle
= locator_child_handle();
71 subreq
= dcerpc_wbint_DsGetDcName_send(
72 state
, ev
, child_binding_handle
,
73 request
->data
.dsgetdcname
.domain_name
, guid_ptr
,
74 request
->data
.dsgetdcname
.site_name
,
75 ds_flags
, &state
->dc_info
);
76 if (tevent_req_nomem(subreq
, req
)) {
77 return tevent_req_post(req
, ev
);
79 tevent_req_set_callback(subreq
, winbindd_dsgetdcname_done
, req
);
83 static void winbindd_dsgetdcname_done(struct tevent_req
*subreq
)
85 struct tevent_req
*req
= tevent_req_callback_data(
86 subreq
, struct tevent_req
);
87 struct winbindd_dsgetdcname_state
*state
= tevent_req_data(
88 req
, struct winbindd_dsgetdcname_state
);
89 NTSTATUS status
, result
;
91 status
= dcerpc_wbint_DsGetDcName_recv(subreq
, state
, &result
);
93 if (any_nt_status_not_ok(status
, result
, &status
)) {
94 tevent_req_nterror(req
, status
);
100 NTSTATUS
winbindd_dsgetdcname_recv(struct tevent_req
*req
,
101 struct winbindd_response
*response
)
103 struct winbindd_dsgetdcname_state
*state
= tevent_req_data(
104 req
, struct winbindd_dsgetdcname_state
);
105 struct GUID_txt_buf guid_str_buf
;
109 if (tevent_req_is_nterror(req
, &status
)) {
110 DEBUG(5, ("dsgetdcname failed: %s\n", nt_errstr(status
)));
115 fstrcpy(response
->data
.dsgetdcname
.dc_unc
,
116 state
->dc_info
->dc_unc
);
117 fstrcpy(response
->data
.dsgetdcname
.dc_address
,
118 state
->dc_info
->dc_address
);
119 response
->data
.dsgetdcname
.dc_address_type
=
120 state
->dc_info
->dc_address_type
;
122 guid_str
= GUID_buf_string(&state
->dc_info
->domain_guid
,
124 fstrcpy(response
->data
.dsgetdcname
.domain_guid
, guid_str
);
126 fstrcpy(response
->data
.dsgetdcname
.domain_name
,
127 state
->dc_info
->domain_name
);
128 fstrcpy(response
->data
.dsgetdcname
.forest_name
,
129 state
->dc_info
->forest_name
);
130 response
->data
.dsgetdcname
.dc_flags
= state
->dc_info
->dc_flags
;
131 fstrcpy(response
->data
.dsgetdcname
.dc_site_name
,
132 state
->dc_info
->dc_site_name
);
133 fstrcpy(response
->data
.dsgetdcname
.client_site_name
,
134 state
->dc_info
->client_site_name
);
139 static uint32_t get_dsgetdc_flags(uint32_t wbc_flags
)
141 struct wbc_flag_map
{
142 uint32_t wbc_dc_flag
;
143 uint32_t ds_dc_flags
;
144 } lookup_dc_flags
[] = {
145 { WBC_LOOKUP_DC_FORCE_REDISCOVERY
,
146 DS_FORCE_REDISCOVERY
},
147 { WBC_LOOKUP_DC_DS_REQUIRED
,
148 DS_DIRECTORY_SERVICE_REQUIRED
},
149 { WBC_LOOKUP_DC_DS_PREFERRED
,
150 DS_DIRECTORY_SERVICE_PREFERRED
},
151 { WBC_LOOKUP_DC_GC_SERVER_REQUIRED
,
152 DS_GC_SERVER_REQUIRED
},
153 { WBC_LOOKUP_DC_PDC_REQUIRED
,
155 { WBC_LOOKUP_DC_BACKGROUND_ONLY
,
156 DS_BACKGROUND_ONLY
},
157 { WBC_LOOKUP_DC_IP_REQUIRED
,
159 { WBC_LOOKUP_DC_KDC_REQUIRED
,
161 { WBC_LOOKUP_DC_TIMESERV_REQUIRED
,
162 DS_TIMESERV_REQUIRED
},
163 { WBC_LOOKUP_DC_WRITABLE_REQUIRED
,
164 DS_WRITABLE_REQUIRED
},
165 { WBC_LOOKUP_DC_GOOD_TIMESERV_PREFERRED
,
166 DS_GOOD_TIMESERV_PREFERRED
},
167 { WBC_LOOKUP_DC_AVOID_SELF
,
169 { WBC_LOOKUP_DC_ONLY_LDAP_NEEDED
,
170 DS_ONLY_LDAP_NEEDED
},
171 { WBC_LOOKUP_DC_IS_FLAT_NAME
,
173 { WBC_LOOKUP_DC_IS_DNS_NAME
,
175 { WBC_LOOKUP_DC_TRY_NEXTCLOSEST_SITE
,
176 DS_TRY_NEXTCLOSEST_SITE
},
177 { WBC_LOOKUP_DC_DS_6_REQUIRED
,
178 DS_DIRECTORY_SERVICE_6_REQUIRED
},
179 { WBC_LOOKUP_DC_RETURN_DNS_NAME
,
180 DS_RETURN_DNS_NAME
},
181 { WBC_LOOKUP_DC_RETURN_FLAT_NAME
,
182 DS_RETURN_FLAT_NAME
}
185 uint32_t ds_flags
= 0;
188 for (i
=0; i
<ARRAY_SIZE(lookup_dc_flags
); i
++) {
189 if (wbc_flags
& lookup_dc_flags
[i
].wbc_dc_flag
) {
190 ds_flags
|= lookup_dc_flags
[i
].ds_dc_flags
;