*/
#include "includes.h"
+#include "libcli/raw/libcliraw.h"
+#include "dlinklist.h"
/****************************************************************************
change notify (async send)
****************************************************************************/
-struct cli_request *smb_raw_changenotify_send(struct cli_tree *tree, struct smb_notify *parms)
+struct smbcli_request *smb_raw_changenotify_send(struct smbcli_tree *tree, union smb_notify *parms)
{
struct smb_nttrans nt;
- uint16 setup[4];
+ uint16_t setup[4];
nt.in.max_setup = 0;
- nt.in.max_param = parms->in.buffer_size;
+ nt.in.max_param = parms->notify.in.buffer_size;
nt.in.max_data = 0;
nt.in.setup_count = 4;
nt.in.setup = setup;
- SIVAL(setup, 0, parms->in.completion_filter);
- SSVAL(setup, 4, parms->in.fnum);
- SSVAL(setup, 6, parms->in.recursive);
+ SIVAL(setup, 0, parms->notify.in.completion_filter);
+ SSVAL(setup, 4, parms->notify.file.fnum);
+ SSVAL(setup, 6, parms->notify.in.recursive);
nt.in.function = NT_TRANSACT_NOTIFY_CHANGE;
nt.in.params = data_blob(NULL, 0);
nt.in.data = data_blob(NULL, 0);
/****************************************************************************
change notify (async recv)
****************************************************************************/
-NTSTATUS smb_raw_changenotify_recv(struct cli_request *req,
- TALLOC_CTX *mem_ctx, struct smb_notify *parms)
+NTSTATUS smb_raw_changenotify_recv(struct smbcli_request *req,
+ TALLOC_CTX *mem_ctx, union smb_notify *parms)
{
struct smb_nttrans nt;
NTSTATUS status;
- uint32 ofs, i;
- struct cli_session *session = req?req->session:NULL;
+ uint32_t ofs, i;
+ struct smbcli_session *session = req?req->session:NULL;
status = smb_raw_nttrans_recv(req, mem_ctx, &nt);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- parms->out.changes = NULL;
- parms->out.num_changes = 0;
+ parms->notify.out.changes = NULL;
+ parms->notify.out.num_changes = 0;
/* count them */
for (ofs=0; nt.out.params.length - ofs > 12; ) {
- uint32 next = IVAL(nt.out.params.data, ofs);
- parms->out.num_changes++;
+ uint32_t next = IVAL(nt.out.params.data, ofs);
+ parms->notify.out.num_changes++;
if (next == 0 ||
ofs + next >= nt.out.params.length) break;
ofs += next;
}
/* allocate array */
- parms->out.changes = talloc(mem_ctx, sizeof(parms->out.changes[0]) *
- parms->out.num_changes);
- if (!parms->out.changes) {
+ parms->notify.out.changes = talloc_array(mem_ctx, struct notify_changes, parms->notify.out.num_changes);
+ if (!parms->notify.out.changes) {
return NT_STATUS_NO_MEMORY;
}
- for (i=ofs=0; i<parms->out.num_changes; i++) {
- parms->out.changes[i].action = IVAL(nt.out.params.data, ofs+4);
- cli_blob_pull_string(session, mem_ctx, &nt.out.params,
- &parms->out.changes[i].name,
+ for (i=ofs=0; i<parms->notify.out.num_changes; i++) {
+ parms->notify.out.changes[i].action = IVAL(nt.out.params.data, ofs+4);
+ smbcli_blob_pull_string(session, mem_ctx, &nt.out.params,
+ &parms->notify.out.changes[i].name,
ofs+8, ofs+12, STR_UNICODE);
ofs += IVAL(nt.out.params.data, ofs);
}
return NT_STATUS_OK;
}
+/****************************************************************************
+ handle ntcancel replies from the server,
+ as the MID of the real reply and the ntcancel reply is the same
+ we need to do find out to what request the reply belongs
+****************************************************************************/
+struct smbcli_request *smbcli_handle_ntcancel_reply(struct smbcli_request *req,
+ uint_t len, const uint8_t *hdr)
+{
+ struct smbcli_request *ntcancel;
+
+ if (!req) return req;
+
+ if (!req->ntcancel) return req;
+
+ if (len >= MIN_SMB_SIZE + NBT_HDR_SIZE &&
+ (CVAL(hdr, HDR_FLG) & FLAG_REPLY) &&
+ CVAL(hdr,HDR_COM) == SMBntcancel) {
+ ntcancel = req->ntcancel;
+ DLIST_REMOVE(req->ntcancel, ntcancel);
+
+ /*
+ * TODO: untill we understand how the
+ * smb_signing works for this case we
+ * return NULL, to just ignore the packet
+ */
+ /*return ntcancel;*/
+ return NULL;
+ }
+
+ return req;
+}
/****************************************************************************
Send a NT Cancel request - used to hurry along a pending request. Usually
used to cancel a pending change notify request
note that this request does not expect a response!
****************************************************************************/
-NTSTATUS smb_raw_ntcancel(struct cli_request *oldreq)
+NTSTATUS smb_raw_ntcancel(struct smbcli_request *oldreq)
{
- struct cli_request *req;
+ struct smbcli_request *req;
- req = cli_request_setup_transport(oldreq->transport, SMBntcancel, 0, 0);
+ req = smbcli_request_setup_transport(oldreq->transport, SMBntcancel, 0, 0);
SSVAL(req->out.hdr, HDR_MID, SVAL(oldreq->out.hdr, HDR_MID));
SSVAL(req->out.hdr, HDR_PID, SVAL(oldreq->out.hdr, HDR_PID));
/* this request does not expect a reply, so tell the signing
subsystem not to allocate an id for a reply */
+ req->sign_single_increment = 1;
req->one_way_request = 1;
- cli_request_send(req);
+ /*
+ * smbcli_request_send() free's oneway requests
+ * but we want to keep it under oldreq->ntcancel
+ */
+ if (!talloc_reference(oldreq, req)) {
+ talloc_free(req);
+ return NT_STATUS_NO_MEMORY;
+ }
- return cli_request_destroy(req);
+ smbcli_request_send(req);
+
+ DLIST_ADD_END(oldreq->ntcancel, req, struct smbcli_request *);
+
+ return NT_STATUS_OK;
}