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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libcli/raw/libcliraw.h"
23 #include "dlinklist.h"
25 /****************************************************************************
26 change notify (async send)
27 ****************************************************************************/
28 struct smbcli_request *smb_raw_changenotify_send(struct smbcli_tree *tree, struct smb_notify *parms)
30 struct smb_nttrans nt;
34 nt.in.max_param = parms->in.buffer_size;
36 nt.in.setup_count = 4;
38 SIVAL(setup, 0, parms->in.completion_filter);
39 SSVAL(setup, 4, parms->in.fnum);
40 SSVAL(setup, 6, parms->in.recursive);
41 nt.in.function = NT_TRANSACT_NOTIFY_CHANGE;
42 nt.in.params = data_blob(NULL, 0);
43 nt.in.data = data_blob(NULL, 0);
45 return smb_raw_nttrans_send(tree, &nt);
48 /****************************************************************************
49 change notify (async recv)
50 ****************************************************************************/
51 NTSTATUS smb_raw_changenotify_recv(struct smbcli_request *req,
52 TALLOC_CTX *mem_ctx, struct smb_notify *parms)
54 struct smb_nttrans nt;
57 struct smbcli_session *session = req?req->session:NULL;
59 status = smb_raw_nttrans_recv(req, mem_ctx, &nt);
60 if (!NT_STATUS_IS_OK(status)) {
64 parms->out.changes = NULL;
65 parms->out.num_changes = 0;
68 for (ofs=0; nt.out.params.length - ofs > 12; ) {
69 uint32_t next = IVAL(nt.out.params.data, ofs);
70 parms->out.num_changes++;
72 ofs + next >= nt.out.params.length) break;
77 parms->out.changes = talloc_array(mem_ctx, struct notify_changes, parms->out.num_changes);
78 if (!parms->out.changes) {
79 return NT_STATUS_NO_MEMORY;
82 for (i=ofs=0; i<parms->out.num_changes; i++) {
83 parms->out.changes[i].action = IVAL(nt.out.params.data, ofs+4);
84 smbcli_blob_pull_string(session, mem_ctx, &nt.out.params,
85 &parms->out.changes[i].name,
86 ofs+8, ofs+12, STR_UNICODE);
87 ofs += IVAL(nt.out.params.data, ofs);
93 /****************************************************************************
94 handle ntcancel replies from the server,
95 as the MID of the real reply and the ntcancel reply is the same
96 we need to do find out to what request the reply belongs
97 ****************************************************************************/
98 struct smbcli_request *smbcli_handle_ntcancel_reply(struct smbcli_request *req,
99 uint_t len, const uint8_t *hdr)
101 struct smbcli_request *ntcancel;
103 if (!req) return req;
105 if (!req->ntcancel) return req;
107 if (len >= MIN_SMB_SIZE + NBT_HDR_SIZE &&
108 (CVAL(hdr, HDR_FLG) & FLAG_REPLY) &&
109 CVAL(hdr,HDR_COM) == SMBntcancel) {
110 ntcancel = req->ntcancel;
111 DLIST_REMOVE(req->ntcancel, ntcancel);
114 * TODO: untill we understand how the
115 * smb_signing works for this case we
116 * return NULL, to just ignore the packet
125 /****************************************************************************
126 Send a NT Cancel request - used to hurry along a pending request. Usually
127 used to cancel a pending change notify request
128 note that this request does not expect a response!
129 ****************************************************************************/
130 NTSTATUS smb_raw_ntcancel(struct smbcli_request *oldreq)
132 struct smbcli_request *req;
134 req = smbcli_request_setup_transport(oldreq->transport, SMBntcancel, 0, 0);
136 SSVAL(req->out.hdr, HDR_MID, SVAL(oldreq->out.hdr, HDR_MID));
137 SSVAL(req->out.hdr, HDR_PID, SVAL(oldreq->out.hdr, HDR_PID));
138 SSVAL(req->out.hdr, HDR_TID, SVAL(oldreq->out.hdr, HDR_TID));
139 SSVAL(req->out.hdr, HDR_UID, SVAL(oldreq->out.hdr, HDR_UID));
141 /* this request does not expect a reply, so tell the signing
142 subsystem not to allocate an id for a reply */
143 req->sign_single_increment = 1;
144 req->one_way_request = 1;
147 * smbcli_request_send() free's oneway requests
148 * but we want to keep it under oldreq->ntcancel
150 if (!talloc_reference(oldreq, req)) {
152 return NT_STATUS_NO_MEMORY;
155 smbcli_request_send(req);
157 DLIST_ADD_END(oldreq->ntcancel, req, struct smbcli_request *);