2 Unix SMB/CIFS implementation.
3 client change notify operations
4 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
21 #include "libcli/raw/libcliraw.h"
22 #include "lib/util/dlinklist.h"
24 /****************************************************************************
25 change notify (async send)
26 ****************************************************************************/
27 struct smbcli_request *smb_raw_changenotify_send(struct smbcli_tree *tree, union smb_notify *parms)
29 struct smb_nttrans nt;
32 if (parms->nttrans.level != RAW_NOTIFY_NTTRANS) {
37 nt.in.max_param = parms->nttrans.in.buffer_size;
39 nt.in.setup_count = 4;
41 SIVAL(setup, 0, parms->nttrans.in.completion_filter);
42 SSVAL(setup, 4, parms->nttrans.in.file.fnum);
43 SSVAL(setup, 6, parms->nttrans.in.recursive);
44 nt.in.function = NT_TRANSACT_NOTIFY_CHANGE;
45 nt.in.params = data_blob(NULL, 0);
46 nt.in.data = data_blob(NULL, 0);
48 return smb_raw_nttrans_send(tree, &nt);
51 /****************************************************************************
52 change notify (async recv)
53 ****************************************************************************/
54 NTSTATUS smb_raw_changenotify_recv(struct smbcli_request *req,
55 TALLOC_CTX *mem_ctx, union smb_notify *parms)
57 struct smb_nttrans nt;
60 struct smbcli_session *session = req?req->session:NULL;
62 if (parms->nttrans.level != RAW_NOTIFY_NTTRANS) {
63 return NT_STATUS_INVALID_LEVEL;
66 status = smb_raw_nttrans_recv(req, mem_ctx, &nt);
67 if (!NT_STATUS_IS_OK(status)) {
71 parms->nttrans.out.changes = NULL;
72 parms->nttrans.out.num_changes = 0;
75 for (ofs=0; nt.out.params.length - ofs > 12; ) {
76 uint32_t next = IVAL(nt.out.params.data, ofs);
77 parms->nttrans.out.num_changes++;
79 ofs + next >= nt.out.params.length) break;
84 parms->nttrans.out.changes = talloc_array(mem_ctx, struct notify_changes, parms->nttrans.out.num_changes);
85 if (!parms->nttrans.out.changes) {
86 return NT_STATUS_NO_MEMORY;
89 for (i=ofs=0; i<parms->nttrans.out.num_changes; i++) {
90 parms->nttrans.out.changes[i].action = IVAL(nt.out.params.data, ofs+4);
91 smbcli_blob_pull_string(session, mem_ctx, &nt.out.params,
92 &parms->nttrans.out.changes[i].name,
93 ofs+8, ofs+12, STR_UNICODE);
94 ofs += IVAL(nt.out.params.data, ofs);
100 /****************************************************************************
101 handle ntcancel replies from the server,
102 as the MID of the real reply and the ntcancel reply is the same
103 we need to do find out to what request the reply belongs
104 ****************************************************************************/
105 struct smbcli_request *smbcli_handle_ntcancel_reply(struct smbcli_request *req,
106 size_t len, const uint8_t *hdr)
108 struct smbcli_request *ntcancel;
110 if (!req) return req;
112 if (!req->ntcancel) return req;
114 if (len >= MIN_SMB_SIZE + NBT_HDR_SIZE &&
115 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) &&
116 CVAL(hdr,HDR_COM) == SMBntcancel) {
117 ntcancel = req->ntcancel;
118 DLIST_REMOVE(req->ntcancel, ntcancel);
121 * TODO: untill we understand how the
122 * smb_signing works for this case we
123 * return NULL, to just ignore the packet
132 /****************************************************************************
133 Send a NT Cancel request - used to hurry along a pending request. Usually
134 used to cancel a pending change notify request
135 note that this request does not expect a response!
136 ****************************************************************************/
137 NTSTATUS smb_raw_ntcancel(struct smbcli_request *oldreq)
139 struct smbcli_request *req;
141 req = smbcli_request_setup_transport(oldreq->transport, SMBntcancel, 0, 0);
143 SSVAL(req->out.hdr, HDR_MID, SVAL(oldreq->out.hdr, HDR_MID));
144 SSVAL(req->out.hdr, HDR_PID, SVAL(oldreq->out.hdr, HDR_PID));
145 SSVAL(req->out.hdr, HDR_TID, SVAL(oldreq->out.hdr, HDR_TID));
146 SSVAL(req->out.hdr, HDR_UID, SVAL(oldreq->out.hdr, HDR_UID));
148 /* this request does not expect a reply, so tell the signing
149 subsystem not to allocate an id for a reply */
150 req->sign_single_increment = 1;
151 req->one_way_request = 1;
154 * smbcli_request_send() free's oneway requests
155 * but we want to keep it under oldreq->ntcancel
157 if (!talloc_reference(oldreq, req)) {
159 return NT_STATUS_NO_MEMORY;
162 smbcli_request_send(req);
164 DLIST_ADD_END(oldreq->ntcancel, req, struct smbcli_request *);