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/cli_wbint.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
= rpccli_wbint_DsGetDcName_send(
71 state
, ev
, child
->rpccli
,
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
= rpccli_wbint_DsGetDcName_recv(subreq
, state
, &result
);
92 if (!NT_STATUS_IS_OK(status
)) {
93 tevent_req_nterror(req
, status
);
96 if (!NT_STATUS_IS_OK(result
)) {
97 tevent_req_nterror(req
, result
);
100 tevent_req_done(req
);
103 NTSTATUS
winbindd_dsgetdcname_recv(struct tevent_req
*req
,
104 struct winbindd_response
*response
)
106 struct winbindd_dsgetdcname_state
*state
= tevent_req_data(
107 req
, struct winbindd_dsgetdcname_state
);
111 if (tevent_req_is_nterror(req
, &status
)) {
112 DEBUG(5, ("dsgetdcname failed: %s\n", nt_errstr(status
)));
116 guid_str
= GUID_string(talloc_tos(), &state
->dc_info
->domain_guid
);
117 if (guid_str
== NULL
) {
118 return NT_STATUS_NO_MEMORY
;
121 fstrcpy(response
->data
.dsgetdcname
.dc_unc
,
122 state
->dc_info
->dc_unc
);
123 fstrcpy(response
->data
.dsgetdcname
.dc_address
,
124 state
->dc_info
->dc_address
);
125 response
->data
.dsgetdcname
.dc_address_type
=
126 state
->dc_info
->dc_address_type
;
127 fstrcpy(response
->data
.dsgetdcname
.domain_guid
, guid_str
);
128 TALLOC_FREE(guid_str
);
129 fstrcpy(response
->data
.dsgetdcname
.domain_name
,
130 state
->dc_info
->domain_name
);
131 fstrcpy(response
->data
.dsgetdcname
.forest_name
,
132 state
->dc_info
->forest_name
);
133 response
->data
.dsgetdcname
.dc_flags
= state
->dc_info
->dc_flags
;
134 fstrcpy(response
->data
.dsgetdcname
.dc_site_name
,
135 state
->dc_info
->dc_site_name
);
136 fstrcpy(response
->data
.dsgetdcname
.client_site_name
,
137 state
->dc_info
->client_site_name
);
142 static uint32_t get_dsgetdc_flags(uint32_t wbc_flags
)
144 struct wbc_flag_map
{
145 uint32_t wbc_dc_flag
;
146 uint32_t ds_dc_flags
;
147 } lookup_dc_flags
[] = {
148 { WBC_LOOKUP_DC_FORCE_REDISCOVERY
,
149 DS_FORCE_REDISCOVERY
},
150 { WBC_LOOKUP_DC_DS_REQUIRED
,
151 DS_DIRECTORY_SERVICE_REQUIRED
},
152 { WBC_LOOKUP_DC_DS_PREFERRED
,
153 DS_DIRECTORY_SERVICE_PREFERRED
},
154 { WBC_LOOKUP_DC_GC_SERVER_REQUIRED
,
155 DS_GC_SERVER_REQUIRED
},
156 { WBC_LOOKUP_DC_PDC_REQUIRED
,
158 { WBC_LOOKUP_DC_BACKGROUND_ONLY
,
159 DS_BACKGROUND_ONLY
},
160 { WBC_LOOKUP_DC_IP_REQUIRED
,
162 { WBC_LOOKUP_DC_KDC_REQUIRED
,
164 { WBC_LOOKUP_DC_TIMESERV_REQUIRED
,
165 DS_TIMESERV_REQUIRED
},
166 { WBC_LOOKUP_DC_WRITABLE_REQUIRED
,
167 DS_WRITABLE_REQUIRED
},
168 { WBC_LOOKUP_DC_GOOD_TIMESERV_PREFERRED
,
169 DS_GOOD_TIMESERV_PREFERRED
},
170 { WBC_LOOKUP_DC_AVOID_SELF
,
172 { WBC_LOOKUP_DC_ONLY_LDAP_NEEDED
,
173 DS_ONLY_LDAP_NEEDED
},
174 { WBC_LOOKUP_DC_IS_FLAT_NAME
,
176 { WBC_LOOKUP_DC_IS_DNS_NAME
,
178 { WBC_LOOKUP_DC_TRY_NEXTCLOSEST_SITE
,
179 DS_TRY_NEXTCLOSEST_SITE
},
180 { WBC_LOOKUP_DC_DS_6_REQUIRED
,
181 DS_DIRECTORY_SERVICE_6_REQUIRED
},
182 { WBC_LOOKUP_DC_RETURN_DNS_NAME
,
183 DS_RETURN_DNS_NAME
},
184 { WBC_LOOKUP_DC_RETURN_FLAT_NAME
,
185 DS_RETURN_FLAT_NAME
}
188 uint32_t ds_flags
= 0;
191 for (i
=0; i
<ARRAY_SIZE(lookup_dc_flags
); i
++) {
192 if (wbc_flags
& lookup_dc_flags
[i
].wbc_dc_flag
) {
193 ds_flags
|= lookup_dc_flags
[i
].ds_dc_flags
;