/src/samba/source4/libcli/smb2/notify.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | |
4 | | SMB2 client notify calls |
5 | | |
6 | | Copyright (C) Stefan Metzmacher 2006 |
7 | | |
8 | | This program is free software; you can redistribute it and/or modify |
9 | | it under the terms of the GNU General Public License as published by |
10 | | the Free Software Foundation; either version 3 of the License, or |
11 | | (at your option) any later version. |
12 | | |
13 | | This program is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU General Public License for more details. |
17 | | |
18 | | You should have received a copy of the GNU General Public License |
19 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #include "includes.h" |
23 | | #include "libcli/raw/libcliraw.h" |
24 | | #include "libcli/raw/raw_proto.h" |
25 | | #include "libcli/smb2/smb2.h" |
26 | | #include "libcli/smb2/smb2_calls.h" |
27 | | |
28 | | /* |
29 | | send a notify request |
30 | | */ |
31 | | struct smb2_request *smb2_notify_send(struct smb2_tree *tree, struct smb2_notify *io) |
32 | 0 | { |
33 | 0 | struct smb2_request *req; |
34 | 0 | uint32_t old_timeout; |
35 | |
|
36 | 0 | req = smb2_request_init_tree(tree, SMB2_OP_NOTIFY, 0x20, false, 0); |
37 | 0 | if (req == NULL) return NULL; |
38 | | |
39 | 0 | SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0x0030); |
40 | |
|
41 | 0 | SSVAL(req->out.body, 0x02, io->in.recursive); |
42 | 0 | SIVAL(req->out.body, 0x04, io->in.buffer_size); |
43 | 0 | smb2_push_handle(req->out.body+0x08, &io->in.file.handle); |
44 | 0 | SIVAL(req->out.body, 0x18, io->in.completion_filter); |
45 | 0 | SIVAL(req->out.body, 0x1C, io->in.unknown); |
46 | |
|
47 | 0 | req->credit_charge = (MAX(io->in.buffer_size, 1) - 1)/ 65536 + 1; |
48 | |
|
49 | 0 | old_timeout = req->transport->options.request_timeout; |
50 | 0 | req->transport->options.request_timeout = 0; |
51 | 0 | smb2_transport_send(req); |
52 | 0 | req->transport->options.request_timeout = old_timeout; |
53 | |
|
54 | 0 | return req; |
55 | 0 | } |
56 | | |
57 | | |
58 | | /* |
59 | | recv a notify reply |
60 | | */ |
61 | | NTSTATUS smb2_notify_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, |
62 | | struct smb2_notify *io) |
63 | 0 | { |
64 | 0 | NTSTATUS status; |
65 | 0 | DATA_BLOB blob; |
66 | 0 | uint32_t ofs, i; |
67 | |
|
68 | 0 | if (!smb2_request_receive(req) || |
69 | 0 | !smb2_request_is_ok(req)) { |
70 | 0 | return smb2_request_destroy(req); |
71 | 0 | } |
72 | | |
73 | 0 | SMB2_CHECK_PACKET_RECV(req, 0x08, true); |
74 | | |
75 | 0 | status = smb2_pull_o16s32_blob(&req->in, mem_ctx, req->in.body+0x02, &blob); |
76 | 0 | if (!NT_STATUS_IS_OK(status)) { |
77 | 0 | return status; |
78 | 0 | } |
79 | | |
80 | 0 | io->out.changes = NULL; |
81 | 0 | io->out.num_changes = 0; |
82 | | |
83 | | /* count them */ |
84 | 0 | for (ofs=0; blob.length - ofs > 12; ) { |
85 | 0 | uint32_t next = IVAL(blob.data, ofs); |
86 | 0 | io->out.num_changes++; |
87 | 0 | if (next == 0 || (ofs + next) >= blob.length) break; |
88 | 0 | ofs += next; |
89 | 0 | } |
90 | | |
91 | | /* allocate array */ |
92 | 0 | io->out.changes = talloc_array(mem_ctx, struct notify_changes, io->out.num_changes); |
93 | 0 | if (!io->out.changes) { |
94 | 0 | return NT_STATUS_NO_MEMORY; |
95 | 0 | } |
96 | | |
97 | 0 | for (i=ofs=0; i<io->out.num_changes; i++) { |
98 | 0 | io->out.changes[i].action = IVAL(blob.data, ofs+4); |
99 | 0 | smbcli_blob_pull_string(NULL, mem_ctx, &blob, |
100 | 0 | &io->out.changes[i].name, |
101 | 0 | ofs+8, ofs+12, STR_UNICODE); |
102 | 0 | ofs += IVAL(blob.data, ofs); |
103 | 0 | } |
104 | |
|
105 | 0 | return smb2_request_destroy(req); |
106 | 0 | } |
107 | | |
108 | | /* |
109 | | sync notify request |
110 | | */ |
111 | | NTSTATUS smb2_notify(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, |
112 | | struct smb2_notify *io) |
113 | 0 | { |
114 | 0 | struct smb2_request *req = smb2_notify_send(tree, io); |
115 | 0 | return smb2_notify_recv(req, mem_ctx, io); |
116 | 0 | } |