libcli/smb: move smb2cli_flush.c from source3 to the toplevel
[obnox/samba/samba-obnox.git] / source3 / libsmb / smb2cli_set_info.c
1 /*
2    Unix SMB/CIFS implementation.
3    smb2 lib
4    Copyright (C) Stefan Metzmacher 2012
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 "client.h"
22 #include "async_smb.h"
23 #include "../libcli/smb/smbXcli_base.h"
24 #include "smb2cli.h"
25 #include "libsmb/proto.h"
26 #include "lib/util/tevent_ntstatus.h"
27 #include "../librpc/ndr/libndr.h"
28
29 struct smb2cli_set_info_state {
30         uint8_t fixed[0x20];
31         uint8_t dyn_pad[1];
32 };
33
34 static void smb2cli_set_info_done(struct tevent_req *subreq);
35
36 struct tevent_req *smb2cli_set_info_send(TALLOC_CTX *mem_ctx,
37                                          struct tevent_context *ev,
38                                          struct smbXcli_conn *conn,
39                                          uint32_t timeout_msec,
40                                          struct smbXcli_session *session,
41                                          uint32_t tcon_id,
42                                          uint8_t in_info_type,
43                                          uint8_t in_file_info_class,
44                                          const DATA_BLOB *in_input_buffer,
45                                          uint32_t in_additional_info,
46                                          uint64_t in_fid_persistent,
47                                          uint64_t in_fid_volatile)
48 {
49         struct tevent_req *req, *subreq;
50         struct smb2cli_set_info_state *state;
51         uint8_t *fixed;
52         uint8_t *dyn;
53         size_t dyn_len;
54         uint16_t input_buffer_offset = 0;
55         uint32_t input_buffer_length = 0;
56
57         req = tevent_req_create(mem_ctx, &state,
58                                 struct smb2cli_set_info_state);
59         if (req == NULL) {
60                 return NULL;
61         }
62
63         if (in_input_buffer) {
64                 input_buffer_offset = SMB2_HDR_BODY+0x20;
65                 input_buffer_length = in_input_buffer->length;
66         }
67
68         fixed = state->fixed;
69
70         SSVAL(fixed, 0x00, 0x21);
71         SCVAL(fixed, 0x02, in_info_type);
72         SCVAL(fixed, 0x03, in_file_info_class);
73         SIVAL(fixed, 0x04, input_buffer_length);
74         SSVAL(fixed, 0x08, input_buffer_offset);
75         SSVAL(fixed, 0x0A, 0); /* reserved */
76         SIVAL(fixed, 0x0C, in_additional_info);
77         SBVAL(fixed, 0x10, in_fid_persistent);
78         SBVAL(fixed, 0x18, in_fid_volatile);
79
80         if (input_buffer_length > 0) {
81                 dyn = in_input_buffer->data;
82                 dyn_len = in_input_buffer->length;
83         } else {
84                 dyn = state->dyn_pad;
85                 dyn_len = sizeof(state->dyn_pad);
86         }
87
88         subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_SETINFO,
89                                   0, 0, /* flags */
90                                   timeout_msec,
91                                   0xFEFF, /* pid */
92                                   tcon_id,
93                                   session,
94                                   state->fixed, sizeof(state->fixed),
95                                   dyn, dyn_len);
96         if (tevent_req_nomem(subreq, req)) {
97                 return tevent_req_post(req, ev);
98         }
99         tevent_req_set_callback(subreq, smb2cli_set_info_done, req);
100         return req;
101 }
102
103 static void smb2cli_set_info_done(struct tevent_req *subreq)
104 {
105         struct tevent_req *req =
106                 tevent_req_callback_data(subreq,
107                 struct tevent_req);
108         NTSTATUS status;
109         static const struct smb2cli_req_expected_response expected[] = {
110         {
111                 .status = NT_STATUS_OK,
112                 .body_size = 0x02
113         },
114         };
115
116         status = smb2cli_req_recv(subreq, NULL, NULL,
117                                   expected, ARRAY_SIZE(expected));
118         if (tevent_req_nterror(req, status)) {
119                 return;
120         }
121
122         tevent_req_done(req);
123 }
124
125 NTSTATUS smb2cli_set_info_recv(struct tevent_req *req)
126 {
127         NTSTATUS status;
128
129         if (tevent_req_is_nterror(req, &status)) {
130                 tevent_req_received(req);
131                 return status;
132         }
133
134         tevent_req_received(req);
135         return NT_STATUS_OK;
136 }
137
138 NTSTATUS smb2cli_set_info(struct smbXcli_conn *conn,
139                           uint32_t timeout_msec,
140                           struct smbXcli_session *session,
141                           uint32_t tcon_id,
142                           uint8_t in_info_type,
143                           uint8_t in_file_info_class,
144                           const DATA_BLOB *in_input_buffer,
145                           uint32_t in_additional_info,
146                           uint64_t in_fid_persistent,
147                           uint64_t in_fid_volatile)
148 {
149         TALLOC_CTX *frame = talloc_stackframe();
150         struct tevent_context *ev;
151         struct tevent_req *req;
152         NTSTATUS status = NT_STATUS_NO_MEMORY;
153
154         if (smbXcli_conn_has_async_calls(conn)) {
155                 /*
156                  * Can't use sync call while an async call is in flight
157                  */
158                 status = NT_STATUS_INVALID_PARAMETER_MIX;
159                 goto fail;
160         }
161         ev = tevent_context_init(frame);
162         if (ev == NULL) {
163                 goto fail;
164         }
165         req = smb2cli_set_info_send(frame, ev,
166                                     conn, timeout_msec,
167                                     session, tcon_id,
168                                     in_info_type,
169                                     in_file_info_class,
170                                     in_input_buffer,
171                                     in_additional_info,
172                                     in_fid_persistent,
173                                     in_fid_volatile);
174         if (req == NULL) {
175                 goto fail;
176         }
177         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
178                 goto fail;
179         }
180         status = smb2cli_set_info_recv(req);
181
182  fail:
183         TALLOC_FREE(frame);
184         return status;
185 }