libwbclient: Separate out the async functions
[Samba/kamenim.git] / nsswitch / libwbclient / wbc_util_async.c
blobeb7fb040cebda9b2f3641c9c758087b30ee7e4df
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client API
6 Copyright (C) 2009,2010 Kai Blin <kai@samba.org>
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 3 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /* Required Headers */
24 #include "replace.h"
25 #include "libwbclient.h"
27 struct wbc_ping_state {
28 struct winbindd_request req;
31 static void wbcPing_done(struct tevent_req *subreq);
33 /** @brief Ping winbind to see if the service is up and running
35 * @param mem_ctx talloc context to allocate the request from
36 * @param ev event context to use for async operation
37 * @param wb_ctx winbind context to use
39 * @return Async request on successful dispatch of the request, NULL on error
42 struct tevent_req *wbcPing_send(TALLOC_CTX *mem_ctx,
43 struct tevent_context *ev,
44 struct wb_context *wb_ctx)
46 struct tevent_req *req, *subreq;
47 struct wbc_ping_state *state;
49 req = tevent_req_create(mem_ctx, &state, struct wbc_ping_state);
50 if (req == NULL) {
51 return NULL;
54 ZERO_STRUCT(state->req);
56 state->req.cmd = WINBINDD_PING;
57 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
58 if (tevent_req_nomem(subreq, req)) {
59 return tevent_req_post(req, ev);
62 tevent_req_set_callback(subreq, wbcPing_done, req);
63 return req;
66 static void wbcPing_done(struct tevent_req *subreq)
68 struct tevent_req *req = tevent_req_callback_data(
69 subreq, struct tevent_req);
70 struct wbc_ping_state *state = tevent_req_data(
71 req, struct wbc_ping_state);
72 struct winbindd_response *resp;
73 wbcErr wbc_status;
75 wbc_status = wb_trans_recv(subreq, state, &resp);
76 TALLOC_FREE(subreq);
77 if (!WBC_ERROR_IS_OK(wbc_status)) {
78 tevent_req_error(req, wbc_status);
79 return;
81 TALLOC_FREE(resp);
83 tevent_req_done(req);
86 /** @brief Receive ping response from winbind
88 * @param req async request sent in #wbcPing_send
90 * @return NT_STATUS_OK on success, an error status on error.
93 wbcErr wbcPing_recv(struct tevent_req *req)
95 wbcErr wbc_status;
97 if (tevent_req_is_wbcerr(req, &wbc_status)) {
98 tevent_req_received(req);
99 return wbc_status;
102 tevent_req_received(req);
103 return WBC_ERR_SUCCESS;
107 struct wbc_interface_version_state {
108 struct winbindd_request req;
109 uint32_t version;
112 static void wbcInterfaceVersion_done(struct tevent_req *subreq);
115 * @brief Request the interface version from winbind
117 * @param mem_ctx talloc context to allocate memory from
118 * @param ev tevent context to use for async requests
119 * @param wb_ctx winbind context
121 * @return tevevt_req on success, NULL on failure
124 struct tevent_req *wbcInterfaceVersion_send(TALLOC_CTX *mem_ctx,
125 struct tevent_context *ev,
126 struct wb_context *wb_ctx)
128 struct tevent_req *req, *subreq;
129 struct wbc_interface_version_state *state;
131 req = tevent_req_create(mem_ctx, &state, struct wbc_interface_version_state);
132 if (req == NULL) {
133 return NULL;
136 ZERO_STRUCT(state->req);
137 state->req.cmd = WINBINDD_INTERFACE_VERSION;
139 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
140 if (tevent_req_nomem(subreq, req)) {
141 return tevent_req_post(req, ev);
144 tevent_req_set_callback(subreq, wbcInterfaceVersion_done, req);
146 return req;
149 static void wbcInterfaceVersion_done(struct tevent_req *subreq)
151 struct tevent_req *req = tevent_req_callback_data(
152 subreq, struct tevent_req);
153 struct wbc_interface_version_state *state = tevent_req_data(
154 req, struct wbc_interface_version_state);
155 struct winbindd_response *resp;
156 wbcErr wbc_status;
158 wbc_status = wb_trans_recv(subreq, state, &resp);
159 TALLOC_FREE(subreq);
160 if (!WBC_ERROR_IS_OK(wbc_status)) {
161 tevent_req_error(req, wbc_status);
162 return;
164 state->version = resp->data.interface_version;
165 TALLOC_FREE(resp);
167 tevent_req_done(req);
171 * @brief Receive the winbind interface version
173 * @param req tevent_req containing the request
174 * @param interface_version pointer to uint32_t to hold the interface
175 * version
177 * @return #wbcErr
180 wbcErr wbcInterfaceVersion_recv(struct tevent_req *req,
181 uint32_t *interface_version)
183 struct wbc_interface_version_state *state = tevent_req_data(
184 req, struct wbc_interface_version_state);
185 wbcErr wbc_status;
187 if (tevent_req_is_wbcerr(req, &wbc_status)) {
188 tevent_req_received(req);
189 return wbc_status;
192 *interface_version = state->version;
194 tevent_req_received(req);
195 return WBC_ERR_SUCCESS;
198 struct wbc_info_state {
199 struct winbindd_request req;
200 char separator;
201 char *version_string;
204 static void wbcInfo_done(struct tevent_req *subreq);
207 * @brief Request information about the winbind service
209 * @param mem_ctx talloc context to allocate memory from
210 * @param ev tevent context to use for async requests
211 * @param wb_ctx winbind context
213 * @return tevent_req on success, NULL on failure
216 struct tevent_req *wbcInfo_send(TALLOC_CTX *mem_ctx,
217 struct tevent_context *ev,
218 struct wb_context *wb_ctx)
220 struct tevent_req *req, *subreq;
221 struct wbc_info_state *state;
223 req = tevent_req_create(mem_ctx, &state, struct wbc_info_state);
224 if (req == NULL) {
225 return NULL;
228 ZERO_STRUCT(state->req);
229 state->req.cmd = WINBINDD_INFO;
231 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
232 if (tevent_req_nomem(subreq, req)) {
233 return tevent_req_post(req, ev);
236 tevent_req_set_callback(subreq, wbcInfo_done, req);
237 return req;
240 static void wbcInfo_done(struct tevent_req *subreq)
242 struct tevent_req *req = tevent_req_callback_data(
243 subreq, struct tevent_req);
244 struct wbc_info_state *state = tevent_req_data(
245 req, struct wbc_info_state);
246 struct winbindd_response *resp;
247 wbcErr wbc_status;
249 wbc_status = wb_trans_recv(subreq, state, &resp);
250 TALLOC_FREE(subreq);
251 if (!WBC_ERROR_IS_OK(wbc_status)) {
252 tevent_req_error(req, wbc_status);
253 return;
255 state->version_string = talloc_strdup(state,
256 resp->data.info.samba_version);
257 if (tevent_req_nomem(state->version_string, subreq)) {
258 return;
260 state->separator = resp->data.info.winbind_separator;
261 TALLOC_FREE(resp);
263 tevent_req_done(req);
267 * @brief Receive information about the running winbind service
269 * @param req tevent_req containing the request
270 * @param mem_ctx talloc context to allocate memory from
271 * @param winbind_separator pointer to a char to hold the separator
272 * @param version_string pointer to a string to hold the version string
274 * @return #wbcErr
277 wbcErr wbcInfo_recv(struct tevent_req *req,
278 TALLOC_CTX *mem_ctx,
279 char *winbind_separator,
280 char **version_string)
282 struct wbc_info_state *state = tevent_req_data(
283 req, struct wbc_info_state);
284 wbcErr wbc_status;
286 if (tevent_req_is_wbcerr(req, &wbc_status)) {
287 tevent_req_received(req);
288 return wbc_status;
291 *winbind_separator = state->separator;
292 *version_string = talloc_steal(mem_ctx, state->version_string);
294 tevent_req_received(req);
295 return WBC_ERR_SUCCESS;
298 struct wbc_netbios_name_state {
299 struct winbindd_request req;
300 char *netbios_name;
303 static void wbcNetbiosName_done(struct tevent_req *subreq);
306 * @brief Request the machine's netbios name
308 * @param mem_ctx talloc context to allocate memory from
309 * @param ev tevent context to use for async requests
310 * @param wb_ctx winbind context
312 * @return tevent_req on success, NULL on failure
315 struct tevent_req *wbcNetbiosName_send(TALLOC_CTX *mem_ctx,
316 struct tevent_context *ev,
317 struct wb_context *wb_ctx)
319 struct tevent_req *req, *subreq;
320 struct wbc_netbios_name_state *state;
322 req = tevent_req_create(mem_ctx, &state, struct wbc_netbios_name_state);
323 if (req == NULL) {
324 return NULL;
327 ZERO_STRUCT(state->req);
328 state->req.cmd = WINBINDD_NETBIOS_NAME;
330 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
331 if (tevent_req_nomem(subreq, req)) {
332 return tevent_req_post(req, ev);
335 tevent_req_set_callback(subreq, wbcNetbiosName_done, req);
336 return req;
339 static void wbcNetbiosName_done(struct tevent_req *subreq)
341 struct tevent_req *req = tevent_req_callback_data(
342 subreq, struct tevent_req);
343 struct wbc_netbios_name_state *state = tevent_req_data(
344 req, struct wbc_netbios_name_state);
345 struct winbindd_response *resp;
346 wbcErr wbc_status;
348 wbc_status = wb_trans_recv(subreq, state, &resp);
349 TALLOC_FREE(subreq);
350 if (!WBC_ERROR_IS_OK(wbc_status)) {
351 tevent_req_error(req, wbc_status);
352 return;
354 state->netbios_name = talloc_strdup(state,
355 resp->data.info.samba_version);
356 if (tevent_req_nomem(state->netbios_name, subreq)) {
357 return;
359 TALLOC_FREE(resp);
361 tevent_req_done(req);
365 * @brief Receive the machine's netbios name
367 * @param req tevent_req containing the request
368 * @param mem_ctx talloc context to allocate memory from
369 * @param netbios_name pointer to a string to hold the netbios name
371 * @return #wbcErr
374 wbcErr wbcNetbiosName_recv(struct tevent_req *req,
375 TALLOC_CTX *mem_ctx,
376 char **netbios_name)
378 struct wbc_netbios_name_state *state = tevent_req_data(
379 req, struct wbc_netbios_name_state);
380 wbcErr wbc_status;
382 if (tevent_req_is_wbcerr(req, &wbc_status)) {
383 tevent_req_received(req);
384 return wbc_status;
387 *netbios_name = talloc_steal(mem_ctx, state->netbios_name);
389 tevent_req_received(req);
390 return WBC_ERR_SUCCESS;
393 struct wbc_domain_name_state {
394 struct winbindd_request req;
395 char *domain_name;
398 static void wbcDomainName_done(struct tevent_req *subreq);
401 * @brief Request the machine's domain name
403 * @param mem_ctx talloc context to allocate memory from
404 * @param ev tevent context to use for async requests
405 * @param wb_ctx winbind context
407 * @return tevent_req on success, NULL on failure
410 struct tevent_req *wbcDomainName_send(TALLOC_CTX *mem_ctx,
411 struct tevent_context *ev,
412 struct wb_context *wb_ctx)
414 struct tevent_req *req, *subreq;
415 struct wbc_domain_name_state *state;
417 req = tevent_req_create(mem_ctx, &state, struct wbc_domain_name_state);
418 if (req == NULL) {
419 return NULL;
422 ZERO_STRUCT(state->req);
423 state->req.cmd = WINBINDD_DOMAIN_NAME;
425 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
426 if (tevent_req_nomem(subreq, req)) {
427 return tevent_req_post(req, ev);
430 tevent_req_set_callback(subreq, wbcDomainName_done, req);
431 return req;
434 static void wbcDomainName_done(struct tevent_req *subreq)
436 struct tevent_req *req = tevent_req_callback_data(
437 subreq, struct tevent_req);
438 struct wbc_domain_name_state *state = tevent_req_data(
439 req, struct wbc_domain_name_state);
440 struct winbindd_response *resp;
441 wbcErr wbc_status;
443 wbc_status = wb_trans_recv(subreq, state, &resp);
444 TALLOC_FREE(subreq);
445 if (!WBC_ERROR_IS_OK(wbc_status)) {
446 tevent_req_error(req, wbc_status);
447 return;
449 state->domain_name = talloc_strdup(state, resp->data.domain_name);
450 if (tevent_req_nomem(state->domain_name, subreq)) {
451 return;
453 TALLOC_FREE(resp);
455 tevent_req_done(req);
459 * @brief Receive the machine's domain name
461 * @param req tevent_req containing the request
462 * @param mem_ctx talloc context to allocate memory from
463 * @param domain_name pointer to a string to hold the domain name
465 * @return #wbcErr
468 wbcErr wbcDomainName_recv(struct tevent_req *req,
469 TALLOC_CTX *mem_ctx,
470 char **domain_name)
472 struct wbc_domain_name_state *state = tevent_req_data(
473 req, struct wbc_domain_name_state);
474 wbcErr wbc_status;
476 if (tevent_req_is_wbcerr(req, &wbc_status)) {
477 tevent_req_received(req);
478 return wbc_status;
481 *domain_name = talloc_steal(mem_ctx, state->domain_name);
483 tevent_req_received(req);
484 return WBC_ERR_SUCCESS;
487 struct wbc_interface_details_state {
488 struct tevent_context *ev;
489 struct wb_context *wb_ctx;
490 struct wbcDomainInfo *dinfo;
491 struct wbcInterfaceDetails *details;
494 static void wbcInterfaceDetails_version(struct tevent_req *subreq);
495 static void wbcInterfaceDetails_info(struct tevent_req *subreq);
496 static void wbcInterfaceDetails_netbios_name(struct tevent_req *subreq);
497 static void wbcInterfaceDetails_domain_name(struct tevent_req *subreq);
498 static void wbcInterfaceDetails_domain_info(struct tevent_req *subreq);
501 * @brief Request some useful details about the winbind service
503 * @param mem_ctx talloc context to allocate memory from
504 * @param ev tevent context to use for async requests
505 * @param wb_ctx winbind context
507 * @return tevent_req on success, NULL on failure
510 struct tevent_req *wbcInterfaceDetails_send(TALLOC_CTX *mem_ctx,
511 struct tevent_context *ev,
512 struct wb_context *wb_ctx)
514 struct tevent_req *req, *subreq;
515 struct wbc_interface_details_state *state;
517 req = tevent_req_create(mem_ctx, &state,
518 struct wbc_interface_details_state);
519 if (req == NULL) {
520 return NULL;
523 state->ev = ev;
524 state->wb_ctx = wb_ctx;
525 state->details = talloc(state, struct wbcInterfaceDetails);
526 if (tevent_req_nomem(state->details, req)) {
527 return tevent_req_post(req, ev);
530 subreq = wbcInterfaceVersion_send(state, ev, wb_ctx);
531 if (tevent_req_nomem(subreq, req)) {
532 return tevent_req_post(req, ev);
535 tevent_req_set_callback(subreq, wbcInterfaceDetails_version, req);
536 return req;
539 static void wbcInterfaceDetails_version(struct tevent_req *subreq)
541 struct tevent_req *req = tevent_req_callback_data(
542 subreq, struct tevent_req);
543 struct wbc_interface_details_state *state = tevent_req_data(
544 req, struct wbc_interface_details_state);
545 wbcErr wbc_status;
548 wbc_status = wbcInterfaceVersion_recv(subreq,
549 &state->details->interface_version);
550 TALLOC_FREE(subreq);
551 if (!WBC_ERROR_IS_OK(wbc_status)) {
552 tevent_req_error(req, wbc_status);
553 return;
556 subreq = wbcInfo_send(state, state->ev, state->wb_ctx);
557 if (tevent_req_nomem(subreq, req)) {
558 return;
561 tevent_req_set_callback(subreq, wbcInterfaceDetails_info, req);
564 static void wbcInterfaceDetails_info(struct tevent_req *subreq)
566 struct tevent_req *req = tevent_req_callback_data(
567 subreq, struct tevent_req);
568 struct wbc_interface_details_state *state = tevent_req_data(
569 req, struct wbc_interface_details_state);
570 wbcErr wbc_status;
572 wbc_status = wbcInfo_recv(subreq, state->details,
573 &state->details->winbind_separator,
574 &state->details->winbind_version);
575 TALLOC_FREE(subreq);
576 if (!WBC_ERROR_IS_OK(wbc_status)) {
577 tevent_req_error(req, wbc_status);
578 return;
581 subreq = wbcNetbiosName_send(state, state->ev, state->wb_ctx);
582 if (tevent_req_nomem(subreq, req)) {
583 return;
586 tevent_req_set_callback(subreq, wbcInterfaceDetails_netbios_name, req);
589 static void wbcInterfaceDetails_netbios_name(struct tevent_req *subreq)
591 struct tevent_req *req = tevent_req_callback_data(
592 subreq, struct tevent_req);
593 struct wbc_interface_details_state *state = tevent_req_data(
594 req, struct wbc_interface_details_state);
595 wbcErr wbc_status;
597 wbc_status = wbcNetbiosName_recv(subreq, state->details,
598 &state->details->netbios_name);
599 TALLOC_FREE(subreq);
600 if (!WBC_ERROR_IS_OK(wbc_status)) {
601 tevent_req_error(req, wbc_status);
602 return;
605 subreq = wbcDomainName_send(state, state->ev, state->wb_ctx);
606 if (tevent_req_nomem(subreq, req)) {
607 return;
610 tevent_req_set_callback(subreq, wbcInterfaceDetails_domain_name, req);
613 static void wbcInterfaceDetails_domain_name(struct tevent_req *subreq)
615 struct tevent_req *req = tevent_req_callback_data(
616 subreq, struct tevent_req);
617 struct wbc_interface_details_state *state = tevent_req_data(
618 req, struct wbc_interface_details_state);
619 wbcErr wbc_status;
621 wbc_status = wbcDomainName_recv(subreq, state->details,
622 &state->details->netbios_domain);
623 TALLOC_FREE(subreq);
624 if (!WBC_ERROR_IS_OK(wbc_status)) {
625 tevent_req_error(req, wbc_status);
626 return;
629 subreq = wbcDomainInfo_send(state, state->ev, state->wb_ctx,
630 state->details->netbios_domain);
631 if (tevent_req_nomem(subreq, req)) {
632 return;
635 tevent_req_set_callback(subreq, wbcInterfaceDetails_domain_info, req);
638 static void wbcInterfaceDetails_domain_info(struct tevent_req *subreq)
640 struct tevent_req *req = tevent_req_callback_data(
641 subreq, struct tevent_req);
642 struct wbc_interface_details_state *state = tevent_req_data(
643 req, struct wbc_interface_details_state);
644 struct wbcDomainInfo *domain;
645 wbcErr wbc_status;
647 wbc_status = wbcDomainInfo_recv(subreq, state, &domain);
648 TALLOC_FREE(subreq);
649 if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
650 tevent_req_done(req);
651 return;
654 if (!WBC_ERROR_IS_OK(wbc_status)) {
655 tevent_req_error(req, wbc_status);
656 return;
658 state->details->dns_domain = talloc_strdup(state->details,
659 domain->dns_name);
660 if (tevent_req_nomem(state->details->dns_domain, req)) {
661 return;
664 TALLOC_FREE(domain);
665 tevent_req_done(req);
669 * @brief Receive useful information about the winbind service
671 * @param req tevent_req containing the request
672 * @param mem_ctx talloc context to allocate memory from
673 * @param *details pointer to hold the struct wbcInterfaceDetails
675 * @return #wbcErr
678 wbcErr wbcInterfaceDetails_recv(struct tevent_req *req,
679 TALLOC_CTX *mem_ctx,
680 struct wbcInterfaceDetails **details)
682 struct wbc_interface_details_state *state = tevent_req_data(
683 req, struct wbc_interface_details_state);
684 wbcErr wbc_status;
686 if (tevent_req_is_wbcerr(req, &wbc_status)) {
687 tevent_req_received(req);
688 return wbc_status;
691 *details = talloc_steal(mem_ctx, state->details);
693 tevent_req_received(req);
694 return WBC_ERR_SUCCESS;
697 struct wbc_domain_info_state {
698 struct winbindd_request req;
699 struct wbcDomainInfo *info;
702 static void wbcDomainInfo_done(struct tevent_req *subreq);
705 * @brief Request status of a given trusted domain
707 * @param mem_ctx talloc context to allocate memory from
708 * @param ev tevent context to use for async requests
709 * @param wb_ctx winbind context
710 * @param domain domain to request status from
712 * @return tevent_req on success, NULL on failure
715 struct tevent_req *wbcDomainInfo_send(TALLOC_CTX *mem_ctx,
716 struct tevent_context *ev,
717 struct wb_context *wb_ctx,
718 const char *domain)
720 struct tevent_req *req, *subreq;
721 struct wbc_domain_info_state *state;
723 if (!domain) {
724 return NULL;
727 req = tevent_req_create(mem_ctx, &state, struct wbc_domain_info_state);
728 if (req == NULL) {
729 return NULL;
732 state->info = talloc(state, struct wbcDomainInfo);
733 if (tevent_req_nomem(state->info, req)) {
734 return tevent_req_post(req, ev);
737 ZERO_STRUCT(state->req);
739 strncpy(state->req.domain_name, domain,
740 sizeof(state->req.domain_name)-1);
742 state->req.cmd = WINBINDD_DOMAIN_INFO;
744 subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
745 if (tevent_req_nomem(subreq, req)) {
746 return tevent_req_post(req, ev);
749 tevent_req_set_callback(subreq, wbcDomainInfo_done, req);
750 return req;
753 static void wbcDomainInfo_done(struct tevent_req *subreq)
755 struct tevent_req *req = tevent_req_callback_data(
756 subreq, struct tevent_req);
757 struct wbc_domain_info_state *state = tevent_req_data(
758 req, struct wbc_domain_info_state);
759 struct winbindd_response *resp;
760 wbcErr wbc_status;
762 wbc_status = wb_trans_recv(subreq, state, &resp);
763 TALLOC_FREE(subreq);
764 if (!WBC_ERROR_IS_OK(wbc_status)) {
765 tevent_req_error(req, wbc_status);
766 return;
769 state->info->short_name = talloc_strdup(state->info,
770 resp->data.domain_info.name);
771 if (tevent_req_nomem(state->info->short_name, req)) {
772 return;
775 state->info->dns_name = talloc_strdup(state->info,
776 resp->data.domain_info.alt_name);
777 if (tevent_req_nomem(state->info->dns_name, req)) {
778 return;
781 wbc_status = wbcStringToSid(resp->data.domain_info.sid,
782 &state->info->sid);
783 if (!WBC_ERROR_IS_OK(wbc_status)) {
784 tevent_req_error(req, wbc_status);
785 return;
788 if (resp->data.domain_info.native_mode) {
789 state->info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
791 if (resp->data.domain_info.active_directory) {
792 state->info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
794 if (resp->data.domain_info.primary) {
795 state->info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
798 TALLOC_FREE(resp);
800 tevent_req_done(req);
804 * @brief Receive information about a trusted domain
806 * @param req tevent_req containing the request
807 * @param mem_ctx talloc context to allocate memory from
808 * @param *dinfo pointer to returned struct wbcDomainInfo
810 * @return #wbcErr
813 wbcErr wbcDomainInfo_recv(struct tevent_req *req,
814 TALLOC_CTX *mem_ctx,
815 struct wbcDomainInfo **dinfo)
817 struct wbc_domain_info_state *state = tevent_req_data(
818 req, struct wbc_domain_info_state);
819 wbcErr wbc_status;
821 if (tevent_req_is_wbcerr(req, &wbc_status)) {
822 tevent_req_received(req);
823 return wbc_status;
826 if (dinfo == NULL) {
827 tevent_req_received(req);
828 return WBC_ERR_INVALID_PARAM;
831 *dinfo = talloc_steal(mem_ctx, state->info);
833 tevent_req_received(req);
834 return WBC_ERR_SUCCESS;