libwbclient: Add async call framework.
[samba.git] / source4 / libcli / wbclient / wbclient.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind client library.
5
6    Copyright (C) 2008 Kai Blin  <kai@samba.org>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program 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
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/wbclient/wbclient.h"
24
25 /**
26  * Get the server_id of the winbind task.
27  *
28  * \param[in] msg_ctx message context to use
29  * \param[in] mem_ctx talloc context to use
30  * \param[out] ids array of server_id structs containing the winbind id
31  * \return NT_STATUS_OK on success, NT_STATUS_INTERNAL_ERROR on failure
32  */
33 static NTSTATUS get_server_id(struct messaging_context *msg_ctx,
34                               TALLOC_CTX *mem_ctx, struct server_id **ids)
35 {
36         *ids = irpc_servers_byname(msg_ctx, mem_ctx, "winbind_server");
37         if (*ids == NULL || (*ids)[0].id == 0) {
38                 DEBUG(0, ("Geting the winbind server ID failed.\n"));
39                 return NT_STATUS_INTERNAL_ERROR;
40         }
41         return NT_STATUS_OK;
42 }
43
44 /**
45  * Initialize the wbclient context, talloc_free() when done.
46  *
47  * \param mem_ctx talloc context to allocate memory from
48  * \param msg_ctx message context to use
49  * \param
50  */
51 struct wbc_context *wbc_init(TALLOC_CTX *mem_ctx,
52                              struct messaging_context *msg_ctx,
53                              struct tevent_context *event_ctx)
54 {
55         struct wbc_context *ctx;
56         NTSTATUS status;
57
58         ctx = talloc(mem_ctx, struct wbc_context);
59         if (ctx == NULL) return NULL;
60
61         status = get_server_id(msg_ctx, mem_ctx, &ctx->ids);
62         if (!NT_STATUS_IS_OK(status)) {
63                 talloc_free(ctx);
64                 return NULL;
65         }
66
67         ctx->msg_ctx = msg_ctx;
68         ctx->event_ctx = event_ctx;
69
70         return ctx;
71 }
72
73 struct wbc_idmap_state {
74         struct composite_context *ctx;
75         struct winbind_get_idmap *req;
76         struct irpc_request *irpc_req;
77         struct id_mapping *ids;
78 };
79
80 static void sids_to_xids_recv_ids(struct irpc_request *req);
81
82 struct composite_context *wbc_sids_to_xids_send(struct wbc_context *wbc_ctx,
83                                                 TALLOC_CTX *mem_ctx,
84                                                 uint32_t count,
85                                                 struct id_mapping *ids)
86 {
87         struct composite_context *ctx;
88         struct wbc_idmap_state *state;
89
90         DEBUG(5, ("wbc_sids_to_xids called\n"));
91
92         ctx = composite_create(mem_ctx, wbc_ctx->event_ctx);
93         if (ctx == NULL) return NULL;
94
95         state = talloc(ctx, struct wbc_idmap_state);
96         if (composite_nomem(state, ctx)) return ctx;
97         ctx->private_data = state;
98
99         state->req = talloc(state, struct winbind_get_idmap);
100         if (composite_nomem(state->req, ctx)) return ctx;
101
102         state->req->in.count = count;
103         state->req->in.level = WINBIND_IDMAP_LEVEL_SIDS_TO_XIDS;
104         state->req->in.ids = ids;
105         state->ctx = ctx;
106
107         state->irpc_req = IRPC_CALL_SEND(wbc_ctx->msg_ctx, wbc_ctx->ids[0],
108                                          winbind, WINBIND_GET_IDMAP, state->req,
109                                          state);
110         if (composite_nomem(state->irpc_req, ctx)) return ctx;
111
112         composite_continue_irpc(ctx, state->irpc_req, sids_to_xids_recv_ids,
113                                 state);
114         return ctx;
115 }
116
117 static void sids_to_xids_recv_ids(struct irpc_request *req)
118 {
119         struct wbc_idmap_state *state = talloc_get_type_abort(
120                                                         req->async.private_data,
121                                                         struct wbc_idmap_state);
122
123         state->ctx->status = irpc_call_recv(state->irpc_req);
124         if (!composite_is_ok(state->ctx)) return;
125
126         state->ids = state->req->out.ids;
127         composite_done(state->ctx);
128 }
129
130 NTSTATUS wbc_sids_to_xids_recv(struct composite_context *ctx,
131                                struct id_mapping **ids)
132 {
133         NTSTATUS status = composite_wait(ctx);
134                 DEBUG(5, ("wbc_sids_to_xids_recv called\n"));
135         if (NT_STATUS_IS_OK(status)) {
136                 struct wbc_idmap_state *state = talloc_get_type_abort(
137                                                         ctx->private_data,
138                                                         struct wbc_idmap_state);
139                 *ids = state->ids;
140         }
141
142         return status;
143 }
144
145 static void xids_to_sids_recv_ids(struct irpc_request *req);
146
147 struct composite_context *wbc_xids_to_sids_send(struct wbc_context *wbc_ctx,
148                                                 TALLOC_CTX *mem_ctx,
149                                                 uint32_t count,
150                                                 struct id_mapping *ids)
151 {
152         struct composite_context *ctx;
153         struct wbc_idmap_state *state;
154
155         DEBUG(5, ("wbc_xids_to_sids called\n"));
156
157         ctx = composite_create(mem_ctx, wbc_ctx->event_ctx);
158         if (ctx == NULL) return NULL;
159
160         state = talloc(ctx, struct wbc_idmap_state);
161         if (composite_nomem(state, ctx)) return ctx;
162         ctx->private_data = state;
163
164         state->req = talloc(state, struct winbind_get_idmap);
165         if (composite_nomem(state->req, ctx)) return ctx;
166
167         state->req->in.count = count;
168         state->req->in.level = WINBIND_IDMAP_LEVEL_XIDS_TO_SIDS;
169         state->req->in.ids = ids;
170         state->ctx = ctx;
171
172         state->irpc_req = IRPC_CALL_SEND(wbc_ctx->msg_ctx, wbc_ctx->ids[0],
173                                          winbind, WINBIND_GET_IDMAP, state->req,
174                                          state);
175         if (composite_nomem(state->irpc_req, ctx)) return ctx;
176
177         composite_continue_irpc(ctx, state->irpc_req, xids_to_sids_recv_ids,
178                         state);
179
180         return ctx;
181 }
182
183 static void xids_to_sids_recv_ids(struct irpc_request *req)
184 {
185         struct wbc_idmap_state *state = talloc_get_type_abort(
186                                                         req->async.private_data,
187                                                         struct wbc_idmap_state);
188
189         state->ctx->status = irpc_call_recv(state->irpc_req);
190         if (!composite_is_ok(state->ctx)) return;
191
192         state->ids = state->req->out.ids;
193         composite_done(state->ctx);
194 }
195
196 NTSTATUS wbc_xids_to_sids_recv(struct composite_context *ctx,
197                                struct id_mapping **ids)
198 {
199         NTSTATUS status = composite_wait(ctx);
200                 DEBUG(5, ("wbc_xids_to_sids_recv called\n"));
201         if (NT_STATUS_IS_OK(status)) {
202                 struct wbc_idmap_state *state = talloc_get_type_abort(
203                                                         ctx->private_data,
204                                                         struct wbc_idmap_state);
205                 *ids = state->ids;
206         }
207
208         return status;
209 }
210