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