/src/samba/source4/libcli/raw/rawioctl.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | client file operations |
4 | | Copyright (C) Andrew Tridgell 2003 |
5 | | Copyright (C) James J Myers 2003 <myersjj@samba.org> |
6 | | |
7 | | This program is free software; you can redistribute it and/or modify |
8 | | it under the terms of the GNU General Public License as published by |
9 | | the Free Software Foundation; either version 3 of the License, or |
10 | | (at your option) any later version. |
11 | | |
12 | | This program is distributed in the hope that it will be useful, |
13 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | GNU General Public License for more details. |
16 | | |
17 | | You should have received a copy of the GNU General Public License |
18 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include "includes.h" |
22 | | #include "libcli/raw/libcliraw.h" |
23 | | #include "libcli/raw/raw_proto.h" |
24 | | |
25 | 0 | #define SETUP_REQUEST(cmd, wct, buflen) do { \ |
26 | 0 | req = smbcli_request_setup(tree, cmd, wct, buflen); \ |
27 | 0 | if (!req) return NULL; \ |
28 | 0 | } while (0) |
29 | | |
30 | | /* |
31 | | send a raw smb ioctl - async send |
32 | | */ |
33 | | static struct smbcli_request *smb_raw_smbioctl_send(struct smbcli_tree *tree, |
34 | | union smb_ioctl *parms) |
35 | 0 | { |
36 | 0 | struct smbcli_request *req; |
37 | |
|
38 | 0 | SETUP_REQUEST(SMBioctl, 3, 0); |
39 | | |
40 | 0 | SSVAL(req->out.vwv, VWV(0), parms->ioctl.in.file.fnum); |
41 | 0 | SIVAL(req->out.vwv, VWV(1), parms->ioctl.in.request); |
42 | |
|
43 | 0 | if (!smbcli_request_send(req)) { |
44 | 0 | smbcli_request_destroy(req); |
45 | 0 | return NULL; |
46 | 0 | } |
47 | | |
48 | 0 | return req; |
49 | 0 | } |
50 | | |
51 | | /* |
52 | | send a raw smb ioctl - async recv |
53 | | */ |
54 | | static NTSTATUS smb_raw_smbioctl_recv(struct smbcli_request *req, |
55 | | TALLOC_CTX *mem_ctx, |
56 | | union smb_ioctl *parms) |
57 | 0 | { |
58 | 0 | if (!smbcli_request_receive(req) || |
59 | 0 | smbcli_request_is_error(req)) { |
60 | 0 | return smbcli_request_destroy(req); |
61 | 0 | } |
62 | | |
63 | 0 | parms->ioctl.out.blob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, req->in.data, -1); |
64 | 0 | return smbcli_request_destroy(req); |
65 | 0 | } |
66 | | |
67 | | |
68 | | |
69 | | /**************************************************************************** |
70 | | NT ioctl (async send) |
71 | | ****************************************************************************/ |
72 | | static struct smbcli_request *smb_raw_ntioctl_send(struct smbcli_tree *tree, |
73 | | union smb_ioctl *parms) |
74 | 0 | { |
75 | 0 | struct smb_nttrans nt; |
76 | 0 | uint8_t setup[8]; |
77 | |
|
78 | 0 | nt.in.max_setup = 4; |
79 | 0 | nt.in.max_param = 0; |
80 | 0 | nt.in.max_data = parms->ntioctl.in.max_data; |
81 | 0 | nt.in.setup_count = 4; |
82 | 0 | nt.in.setup = setup; |
83 | 0 | SIVAL(setup, 0, parms->ntioctl.in.function); |
84 | 0 | SSVAL(setup, 4, parms->ntioctl.in.file.fnum); |
85 | 0 | SCVAL(setup, 6, parms->ntioctl.in.fsctl); |
86 | 0 | SCVAL(setup, 7, parms->ntioctl.in.filter); |
87 | 0 | nt.in.function = NT_TRANSACT_IOCTL; |
88 | 0 | nt.in.params = data_blob(NULL, 0); |
89 | 0 | nt.in.data = parms->ntioctl.in.blob; |
90 | |
|
91 | 0 | return smb_raw_nttrans_send(tree, &nt); |
92 | 0 | } |
93 | | |
94 | | /**************************************************************************** |
95 | | NT ioctl (async recv) |
96 | | ****************************************************************************/ |
97 | | static NTSTATUS smb_raw_ntioctl_recv(struct smbcli_request *req, |
98 | | TALLOC_CTX *mem_ctx, |
99 | | union smb_ioctl *parms) |
100 | 0 | { |
101 | 0 | NTSTATUS status; |
102 | 0 | struct smb_nttrans nt; |
103 | 0 | TALLOC_CTX *tmp_mem; |
104 | |
|
105 | 0 | tmp_mem = talloc_new(mem_ctx); |
106 | 0 | NT_STATUS_HAVE_NO_MEMORY(tmp_mem); |
107 | | |
108 | 0 | status = smb_raw_nttrans_recv(req, tmp_mem, &nt); |
109 | 0 | if (!NT_STATUS_IS_OK(status)) goto fail; |
110 | | |
111 | 0 | parms->ntioctl.out.blob = nt.out.data; |
112 | 0 | talloc_steal(mem_ctx, parms->ntioctl.out.blob.data); |
113 | |
|
114 | 0 | fail: |
115 | 0 | talloc_free(tmp_mem); |
116 | 0 | return status; |
117 | 0 | } |
118 | | |
119 | | |
120 | | /* |
121 | | send a raw ioctl - async send |
122 | | */ |
123 | | struct smbcli_request *smb_raw_ioctl_send(struct smbcli_tree *tree, union smb_ioctl *parms) |
124 | 0 | { |
125 | 0 | struct smbcli_request *req = NULL; |
126 | |
|
127 | 0 | switch (parms->generic.level) { |
128 | 0 | case RAW_IOCTL_IOCTL: |
129 | 0 | req = smb_raw_smbioctl_send(tree, parms); |
130 | 0 | break; |
131 | | |
132 | 0 | case RAW_IOCTL_NTIOCTL: |
133 | 0 | req = smb_raw_ntioctl_send(tree, parms); |
134 | 0 | break; |
135 | | |
136 | 0 | case RAW_IOCTL_SMB2: |
137 | 0 | case RAW_IOCTL_SMB2_NO_HANDLE: |
138 | 0 | return NULL; |
139 | 0 | } |
140 | | |
141 | 0 | return req; |
142 | 0 | } |
143 | | |
144 | | /* |
145 | | recv a raw ioctl - async recv |
146 | | */ |
147 | | NTSTATUS smb_raw_ioctl_recv(struct smbcli_request *req, |
148 | | TALLOC_CTX *mem_ctx, union smb_ioctl *parms) |
149 | 0 | { |
150 | 0 | switch (parms->generic.level) { |
151 | 0 | case RAW_IOCTL_IOCTL: |
152 | 0 | return smb_raw_smbioctl_recv(req, mem_ctx, parms); |
153 | | |
154 | 0 | case RAW_IOCTL_NTIOCTL: |
155 | 0 | return smb_raw_ntioctl_recv(req, mem_ctx, parms); |
156 | | |
157 | 0 | case RAW_IOCTL_SMB2: |
158 | 0 | case RAW_IOCTL_SMB2_NO_HANDLE: |
159 | 0 | break; |
160 | 0 | } |
161 | 0 | return NT_STATUS_INVALID_LEVEL; |
162 | 0 | } |
163 | | |
164 | | /* |
165 | | send a raw ioctl - sync interface |
166 | | */ |
167 | | NTSTATUS smb_raw_ioctl(struct smbcli_tree *tree, |
168 | | TALLOC_CTX *mem_ctx, union smb_ioctl *parms) |
169 | 0 | { |
170 | 0 | struct smbcli_request *req; |
171 | 0 | req = smb_raw_ioctl_send(tree, parms); |
172 | 0 | return smb_raw_ioctl_recv(req, mem_ctx, parms); |
173 | 0 | } |