r26654: libcli/smb_composite: Rather than specifying each of the gazillion options...
[jelmer/samba4-debian.git] / source / libcli / raw / rawnotify.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client change notify operations
4    Copyright (C) Andrew Tridgell 2003
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 "libcli/raw/libcliraw.h"
22 #include "lib/util/dlinklist.h"
23
24 /****************************************************************************
25 change notify (async send)
26 ****************************************************************************/
27 struct smbcli_request *smb_raw_changenotify_send(struct smbcli_tree *tree, union smb_notify *parms)
28 {
29         struct smb_nttrans nt;
30         uint8_t setup[8];
31
32         if (parms->nttrans.level != RAW_NOTIFY_NTTRANS) {
33                 return NULL;
34         }
35
36         nt.in.max_setup = 0;
37         nt.in.max_param = parms->nttrans.in.buffer_size;
38         nt.in.max_data = 0;
39         nt.in.setup_count = 4;
40         nt.in.setup = setup;
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);
47
48         return smb_raw_nttrans_send(tree, &nt);
49 }
50
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)
56 {
57         struct smb_nttrans nt;
58         NTSTATUS status;
59         uint32_t ofs, i;
60         struct smbcli_session *session = req?req->session:NULL;
61
62         if (parms->nttrans.level != RAW_NOTIFY_NTTRANS) {
63                 return NT_STATUS_INVALID_LEVEL;
64         }
65
66         status = smb_raw_nttrans_recv(req, mem_ctx, &nt);
67         if (!NT_STATUS_IS_OK(status)) {
68                 return status;
69         }
70
71         parms->nttrans.out.changes = NULL;
72         parms->nttrans.out.num_changes = 0;
73         
74         /* count them */
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++;
78                 if (next == 0 ||
79                     ofs + next >= nt.out.params.length) break;
80                 ofs += next;
81         }
82
83         /* allocate array */
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;
87         }
88
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);
95         }
96
97         return NT_STATUS_OK;
98 }
99
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)
107 {
108         struct smbcli_request *ntcancel;
109
110         if (!req) return req;
111
112         if (!req->ntcancel) return req;
113
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);
119
120                 /*
121                  * TODO: untill we understand how the 
122                  *       smb_signing works for this case we 
123                  *       return NULL, to just ignore the packet
124                  */
125                 /*return ntcancel;*/
126                 return NULL;
127         }
128
129         return req;
130 }
131
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)
138 {
139         struct smbcli_request *req;
140
141         req = smbcli_request_setup_transport(oldreq->transport, SMBntcancel, 0, 0);
142
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));   
147
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;
152
153         /* 
154          * smbcli_request_send() free's oneway requests
155          * but we want to keep it under oldreq->ntcancel
156          */
157         if (!talloc_reference(oldreq, req)) {
158                 talloc_free(req);
159                 return NT_STATUS_NO_MEMORY;
160         }
161
162         smbcli_request_send(req);
163
164         DLIST_ADD_END(oldreq->ntcancel, req, struct smbcli_request *);
165
166         return NT_STATUS_OK;
167 }