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 */ 13enum fsinfo_stage {FSINFO_CONNECT, FSINFO_QUERY}; 14 15 16static void fsinfo_raw_handler(struct smbcli_request *req); 17static void fsinfo_composite_handler(struct composite_context *c); 18static void fsinfo_state_handler(struct composite_context *c); 19 20struct 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 30static NTSTATUS fsinfo_connect(struct composite_context *c, 31 struct smb_composite_fsinfo *io) 32{ 33 NTSTATUS status; 34 struct fsinfo_state *state; 35 state = talloc_get_type(c->private_data, struct fsinfo_state); 36 37 status = smb_composite_connect_recv(state->creq, c); 38 NT_STATUS_NOT_OK_RETURN(status); 39 40 state->fsinfo = talloc(state, union smb_fsinfo); 41 NT_STATUS_HAVE_NO_MEMORY(state->fsinfo); 42 43 state->fsinfo->generic.level = io->in.level; 44 45 state->req = smb_raw_fsinfo_send(state->connect->out.tree, 46 state, 47 state->fsinfo); 48 NT_STATUS_HAVE_NO_MEMORY(state->req); 49 50 state->req->async.private_data = c; 51 state->req->async.fn = fsinfo_raw_handler; 52 53 state->stage = FSINFO_QUERY; 54 55 return NT_STATUS_OK; 56} 57 58static NTSTATUS fsinfo_query(struct composite_context *c, 59 struct smb_composite_fsinfo *io) 60{ 61 NTSTATUS status; 62 struct fsinfo_state *state; 63 state = talloc_get_type(c->private_data, struct fsinfo_state); 64 65 status = smb_raw_fsinfo_recv(state->req, state, state->fsinfo); 66 NT_STATUS_NOT_OK_RETURN(status); 67 68 state->io->out.fsinfo = state->fsinfo; 69 70 c->state = COMPOSITE_STATE_DONE; 71 72 if (c->async.fn) 73 c->async.fn(c); 74 75 return NT_STATUS_OK; 76 77} 78 79/* 80 handler for completion of a sub-request in fsinfo 81*/ 82static void fsinfo_state_handler(struct composite_context *creq) 83{ 84 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 switch (state->stage) { 89 case FSINFO_CONNECT: 90 creq->status = fsinfo_connect(creq, state->io); 91 break; 92 93 case FSINFO_QUERY: 94 creq->status = fsinfo_query(creq, state->io); 95 break; 96 } 97 98 if (!NT_STATUS_IS_OK(creq->status)) { 99 creq->state = COMPOSITE_STATE_ERROR; 100 } 101 102 if (creq->state >= COMPOSITE_STATE_DONE && creq->async.fn) { 103 creq->async.fn(creq); 104 } 105} 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*/ 111static void fsinfo_raw_handler(struct smbcli_request *req) 112{ 113 struct composite_context *c = talloc_get_type(req->async.private_data, 114 struct composite_context); 115 fsinfo_state_handler(c); 116} 117 118static void fsinfo_composite_handler(struct composite_context *creq) 119{ 120 struct composite_context *c = talloc_get_type(creq->async.private_data, 121 struct composite_context); 122 fsinfo_state_handler(c); 123} 124 125/* 126 composite fsinfo call - connects to a tree and queries a file system information 127*/ 128struct composite_context *smb_composite_fsinfo_send(struct smbcli_tree *tree, 129 struct smb_composite_fsinfo *io, 130 struct resolve_context *resolve_ctx) 131{ 132 struct composite_context *c; 133 struct fsinfo_state *state; 134 135 c = talloc_zero(tree, struct composite_context); 136 if (c == NULL) goto failed; 137 138 state = talloc(c, struct fsinfo_state); 139 if (state == NULL) goto failed; 140 141 state->io = io; 142 143 state->connect = talloc(state, struct smb_composite_connect); 144 145 if (state->connect == NULL) goto failed; 146 147 state->connect->in.dest_host = io->in.dest_host; 148 state->connect->in.dest_ports = io->in.dest_ports; 149 state->connect->in.socket_options = io->in.socket_options; 150 state->connect->in.called_name = io->in.called_name; 151 state->connect->in.service = io->in.service; 152 state->connect->in.service_type = io->in.service_type; 153 state->connect->in.credentials = io->in.credentials; 154 state->connect->in.fallback_to_anonymous = false; 155 state->connect->in.workgroup = io->in.workgroup; 156 state->connect->in.iconv_convenience = io->in.iconv_convenience; 157 state->connect->in.gensec_settings = io->in.gensec_settings; 158 159 state->connect->in.options = tree->session->transport->options; 160 state->connect->in.session_options = tree->session->options; 161 162 c->state = COMPOSITE_STATE_IN_PROGRESS; 163 state->stage = FSINFO_CONNECT; 164 c->private_data = state; 165 166 state->creq = smb_composite_connect_send(state->connect, state, 167 resolve_ctx, c->event_ctx); 168 169 if (state->creq == NULL) goto failed; 170 171 state->creq->async.private_data = c; 172 state->creq->async.fn = fsinfo_composite_handler; 173 174 return c; 175failed: 176 talloc_free(c); 177 return NULL; 178} 179 180/* 181 composite fsinfo call - recv side 182*/ 183NTSTATUS smb_composite_fsinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) 184{ 185 NTSTATUS status; 186 187 status = composite_wait(c); 188 189 if (NT_STATUS_IS_OK(status)) { 190 struct fsinfo_state *state = talloc_get_type(c->private_data, struct fsinfo_state); 191 talloc_steal(mem_ctx, state->io->out.fsinfo); 192 } 193 194 talloc_free(c); 195 return status; 196} 197 198 199/* 200 composite fsinfo call - sync interface 201*/ 202NTSTATUS smb_composite_fsinfo(struct smbcli_tree *tree, 203 TALLOC_CTX *mem_ctx, 204 struct smb_composite_fsinfo *io, 205 struct resolve_context *resolve_ctx) 206{ 207 struct composite_context *c = smb_composite_fsinfo_send(tree, io, resolve_ctx); 208 return smb_composite_fsinfo_recv(c, mem_ctx); 209} 210 211