Line data Source code
1 : /*
2 : a composite API for quering file system information
3 : */
4 :
5 : #include "includes.h"
6 : #include "libcli/raw/libcliraw.h"
7 : #include "libcli/raw/raw_proto.h"
8 : #include "libcli/composite/composite.h"
9 : #include "libcli/smb_composite/smb_composite.h"
10 : #include "libcli/resolve/resolve.h"
11 :
12 : /* the stages of this call */
13 : enum fsinfo_stage {FSINFO_CONNECT, FSINFO_QUERY};
14 :
15 :
16 : static void fsinfo_raw_handler(struct smbcli_request *req);
17 : static void fsinfo_composite_handler(struct composite_context *c);
18 : static void fsinfo_state_handler(struct composite_context *c);
19 :
20 : struct fsinfo_state {
21 : enum fsinfo_stage stage;
22 : struct composite_context *creq;
23 : struct smb_composite_fsinfo *io;
24 : struct smb_composite_connect *connect;
25 : union smb_fsinfo *fsinfo;
26 : struct smbcli_tree *tree;
27 : struct smbcli_request *req;
28 : };
29 :
30 10 : static NTSTATUS fsinfo_connect(struct composite_context *c,
31 : struct smb_composite_fsinfo *io)
32 : {
33 : NTSTATUS status;
34 : struct fsinfo_state *state;
35 10 : state = talloc_get_type(c->private_data, struct fsinfo_state);
36 :
37 10 : status = smb_composite_connect_recv(state->creq, c);
38 10 : NT_STATUS_NOT_OK_RETURN(status);
39 :
40 10 : state->fsinfo = talloc(state, union smb_fsinfo);
41 10 : NT_STATUS_HAVE_NO_MEMORY(state->fsinfo);
42 :
43 10 : state->fsinfo->generic.level = io->in.level;
44 :
45 10 : state->req = smb_raw_fsinfo_send(state->connect->out.tree,
46 : state,
47 : state->fsinfo);
48 10 : NT_STATUS_HAVE_NO_MEMORY(state->req);
49 :
50 10 : state->req->async.private_data = c;
51 10 : state->req->async.fn = fsinfo_raw_handler;
52 :
53 10 : state->stage = FSINFO_QUERY;
54 :
55 10 : return NT_STATUS_OK;
56 : }
57 :
58 10 : static NTSTATUS fsinfo_query(struct composite_context *c,
59 : struct smb_composite_fsinfo *io)
60 : {
61 : NTSTATUS status;
62 : struct fsinfo_state *state;
63 10 : state = talloc_get_type(c->private_data, struct fsinfo_state);
64 :
65 10 : status = smb_raw_fsinfo_recv(state->req, state, state->fsinfo);
66 10 : NT_STATUS_NOT_OK_RETURN(status);
67 :
68 10 : state->io->out.fsinfo = state->fsinfo;
69 :
70 10 : c->state = COMPOSITE_STATE_DONE;
71 :
72 10 : if (c->async.fn)
73 10 : c->async.fn(c);
74 :
75 10 : return NT_STATUS_OK;
76 :
77 : }
78 :
79 : /*
80 : handler for completion of a sub-request in fsinfo
81 : */
82 20 : static void fsinfo_state_handler(struct composite_context *creq)
83 : {
84 20 : struct fsinfo_state *state = talloc_get_type(creq->private_data, struct fsinfo_state);
85 :
86 : /* when this handler is called, the stage indicates what
87 : call has just finished */
88 20 : switch (state->stage) {
89 10 : case FSINFO_CONNECT:
90 10 : creq->status = fsinfo_connect(creq, state->io);
91 10 : break;
92 :
93 10 : case FSINFO_QUERY:
94 10 : creq->status = fsinfo_query(creq, state->io);
95 10 : break;
96 : }
97 :
98 20 : if (!NT_STATUS_IS_OK(creq->status)) {
99 0 : creq->state = COMPOSITE_STATE_ERROR;
100 : }
101 :
102 20 : if (creq->state >= COMPOSITE_STATE_DONE && creq->async.fn) {
103 10 : creq->async.fn(creq);
104 : }
105 20 : }
106 :
107 : /*
108 : As raw and composite handlers take different requests, we need to handlers
109 : to adapt both for the same state machine in fsinfo_state_handler()
110 : */
111 10 : static void fsinfo_raw_handler(struct smbcli_request *req)
112 : {
113 10 : struct composite_context *c = talloc_get_type(req->async.private_data,
114 : struct composite_context);
115 10 : fsinfo_state_handler(c);
116 10 : }
117 :
118 10 : static void fsinfo_composite_handler(struct composite_context *creq)
119 : {
120 10 : struct composite_context *c = talloc_get_type(creq->async.private_data,
121 : struct composite_context);
122 10 : fsinfo_state_handler(c);
123 10 : }
124 :
125 : /*
126 : composite fsinfo call - connects to a tree and queries a file system information
127 : */
128 10 : struct composite_context *smb_composite_fsinfo_send(struct smbcli_tree *tree,
129 : struct smb_composite_fsinfo *io,
130 : struct resolve_context *resolve_ctx,
131 : struct tevent_context *event_ctx)
132 : {
133 : struct composite_context *c;
134 : struct fsinfo_state *state;
135 :
136 10 : c = talloc_zero(tree, struct composite_context);
137 10 : if (c == NULL) goto failed;
138 :
139 10 : c->event_ctx = event_ctx;
140 10 : if (c->event_ctx == NULL) goto failed;
141 :
142 10 : state = talloc(c, struct fsinfo_state);
143 10 : if (state == NULL) goto failed;
144 :
145 10 : state->io = io;
146 :
147 10 : state->connect = talloc_zero(state, struct smb_composite_connect);
148 :
149 10 : if (state->connect == NULL) goto failed;
150 :
151 10 : state->connect->in.dest_host = io->in.dest_host;
152 10 : state->connect->in.dest_ports = io->in.dest_ports;
153 10 : state->connect->in.socket_options = io->in.socket_options;
154 10 : state->connect->in.called_name = io->in.called_name;
155 10 : state->connect->in.service = io->in.service;
156 10 : state->connect->in.service_type = io->in.service_type;
157 10 : state->connect->in.credentials = io->in.credentials;
158 10 : state->connect->in.fallback_to_anonymous = false;
159 10 : state->connect->in.workgroup = io->in.workgroup;
160 10 : state->connect->in.gensec_settings = io->in.gensec_settings;
161 :
162 10 : state->connect->in.options = tree->session->transport->options;
163 10 : state->connect->in.session_options = tree->session->options;
164 :
165 10 : c->state = COMPOSITE_STATE_IN_PROGRESS;
166 10 : state->stage = FSINFO_CONNECT;
167 10 : c->private_data = state;
168 :
169 10 : state->creq = smb_composite_connect_send(state->connect, state,
170 : resolve_ctx, c->event_ctx);
171 :
172 10 : if (state->creq == NULL) goto failed;
173 :
174 10 : state->creq->async.private_data = c;
175 10 : state->creq->async.fn = fsinfo_composite_handler;
176 :
177 10 : return c;
178 0 : failed:
179 0 : talloc_free(c);
180 0 : return NULL;
181 : }
182 :
183 : /*
184 : composite fsinfo call - recv side
185 : */
186 10 : NTSTATUS smb_composite_fsinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
187 : {
188 : NTSTATUS status;
189 :
190 10 : status = composite_wait(c);
191 :
192 10 : if (NT_STATUS_IS_OK(status)) {
193 10 : struct fsinfo_state *state = talloc_get_type(c->private_data, struct fsinfo_state);
194 10 : talloc_steal(mem_ctx, state->io->out.fsinfo);
195 : }
196 :
197 10 : talloc_free(c);
198 10 : return status;
199 : }
200 :
201 :
202 : /*
203 : composite fsinfo call - sync interface
204 : */
205 0 : NTSTATUS smb_composite_fsinfo(struct smbcli_tree *tree,
206 : TALLOC_CTX *mem_ctx,
207 : struct smb_composite_fsinfo *io,
208 : struct resolve_context *resolve_ctx,
209 : struct tevent_context *ev)
210 : {
211 0 : struct composite_context *c = smb_composite_fsinfo_send(tree, io, resolve_ctx, ev);
212 0 : return smb_composite_fsinfo_recv(c, mem_ctx);
213 : }
214 :
|