Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : async implementation of WINBINDD_SHOW_SEQUENCE
4 : Copyright (C) Volker Lendecke 2009
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "winbindd.h"
22 :
23 : struct winbindd_show_sequence_state {
24 : bool one_domain;
25 : /* One domain */
26 : uint32_t seqnum;
27 :
28 : /* All domains */
29 : int num_domains;
30 : NTSTATUS *statuses;
31 : struct winbindd_domain **domains;
32 : uint32_t *seqnums;
33 : };
34 :
35 : static void winbindd_show_sequence_done_one(struct tevent_req *subreq);
36 : static void winbindd_show_sequence_done_all(struct tevent_req *subreq);
37 :
38 20 : struct tevent_req *winbindd_show_sequence_send(TALLOC_CTX *mem_ctx,
39 : struct tevent_context *ev,
40 : struct winbindd_cli_state *cli,
41 : struct winbindd_request *request)
42 : {
43 0 : struct tevent_req *req, *subreq;
44 0 : struct winbindd_show_sequence_state *state;
45 :
46 20 : req = tevent_req_create(mem_ctx, &state,
47 : struct winbindd_show_sequence_state);
48 20 : if (req == NULL) {
49 0 : return NULL;
50 : }
51 20 : state->one_domain = false;
52 20 : state->domains = NULL;
53 20 : state->statuses = NULL;
54 20 : state->seqnums = NULL;
55 :
56 : /* Ensure null termination */
57 20 : request->domain_name[sizeof(request->domain_name)-1]='\0';
58 :
59 20 : DEBUG(3, ("show_sequence %s\n", request->domain_name));
60 :
61 20 : if (request->domain_name[0] != '\0') {
62 0 : struct winbindd_domain *domain;
63 :
64 16 : state->one_domain = true;
65 :
66 16 : domain = find_domain_from_name_noinit(
67 16 : request->domain_name);
68 16 : if (domain == NULL) {
69 0 : tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
70 0 : return tevent_req_post(req, ev);
71 : }
72 :
73 16 : subreq = wb_seqnum_send(state, ev, domain);
74 16 : if (tevent_req_nomem(subreq, req)) {
75 0 : return tevent_req_post(req, ev);
76 : }
77 16 : tevent_req_set_callback(
78 : subreq, winbindd_show_sequence_done_one, req);
79 16 : return req;
80 : }
81 :
82 4 : subreq = wb_seqnums_send(state, ev);
83 4 : if (tevent_req_nomem(subreq, req)) {
84 0 : return tevent_req_post(req, ev);
85 : }
86 4 : tevent_req_set_callback(subreq, winbindd_show_sequence_done_all, req);
87 4 : return req;
88 : }
89 :
90 16 : static void winbindd_show_sequence_done_one(struct tevent_req *subreq)
91 : {
92 16 : struct tevent_req *req = tevent_req_callback_data(
93 : subreq, struct tevent_req);
94 16 : struct winbindd_show_sequence_state *state = tevent_req_data(
95 : req, struct winbindd_show_sequence_state);
96 0 : NTSTATUS status;
97 :
98 16 : status = wb_seqnum_recv(subreq, &state->seqnum);
99 16 : TALLOC_FREE(subreq);
100 16 : if (tevent_req_nterror(req, status)) {
101 0 : return;
102 : }
103 16 : tevent_req_done(req);
104 : }
105 :
106 4 : static void winbindd_show_sequence_done_all(struct tevent_req *subreq)
107 : {
108 4 : struct tevent_req *req = tevent_req_callback_data(
109 : subreq, struct tevent_req);
110 4 : struct winbindd_show_sequence_state *state = tevent_req_data(
111 : req, struct winbindd_show_sequence_state);
112 0 : NTSTATUS status;
113 :
114 4 : status = wb_seqnums_recv(subreq, state, &state->num_domains,
115 : &state->domains, &state->statuses,
116 : &state->seqnums);
117 4 : TALLOC_FREE(subreq);
118 4 : if (tevent_req_nterror(req, status)) {
119 0 : return;
120 : }
121 4 : tevent_req_done(req);
122 : }
123 :
124 20 : NTSTATUS winbindd_show_sequence_recv(struct tevent_req *req,
125 : struct winbindd_response *response)
126 : {
127 20 : struct winbindd_show_sequence_state *state = tevent_req_data(
128 : req, struct winbindd_show_sequence_state);
129 0 : NTSTATUS status;
130 0 : char *extra_data;
131 0 : int i;
132 :
133 20 : if (tevent_req_is_nterror(req, &status)) {
134 0 : return status;
135 : }
136 :
137 20 : if (state->one_domain) {
138 16 : response->data.sequence_number = state->seqnum;
139 16 : return NT_STATUS_OK;
140 : }
141 :
142 4 : extra_data = talloc_strdup(response, "");
143 4 : if (extra_data == NULL) {
144 0 : return NT_STATUS_NO_MEMORY;
145 : }
146 :
147 20 : for (i=0; i<state->num_domains; i++) {
148 16 : if (!NT_STATUS_IS_OK(state->statuses[i])
149 16 : || (state->seqnums[i] == DOM_SEQUENCE_NONE)) {
150 0 : extra_data = talloc_asprintf_append_buffer(
151 : extra_data, "%s : DISCONNECTED\n",
152 0 : state->domains[i]->name);
153 : } else {
154 16 : extra_data = talloc_asprintf_append_buffer(
155 : extra_data, "%s : %d\n",
156 16 : state->domains[i]->name,
157 16 : (int)state->seqnums[i]);
158 : }
159 16 : if (extra_data == NULL) {
160 0 : return NT_STATUS_NO_MEMORY;
161 : }
162 : }
163 :
164 4 : response->extra_data.data = extra_data;
165 4 : response->length += talloc_get_size(extra_data);
166 4 : return NT_STATUS_OK;
167 : }
|