r14173: change smb interface structures to always use
[jelmer/samba4-debian.git] / source / libcli / raw / rawnotify.c
index 7d635da0dc7996441357bc2cd789e154cbd4f714..3adb1b000b272c45a1768b00046194eca758d1f2 100644 (file)
 */
 
 #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);
@@ -46,42 +48,41 @@ struct cli_request *smb_raw_changenotify_send(struct cli_tree *tree, struct smb_
 /****************************************************************************
 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);
        }
@@ -89,17 +90,48 @@ NTSTATUS smb_raw_changenotify_recv(struct cli_request *req,
        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));   
@@ -108,9 +140,21 @@ NTSTATUS smb_raw_ntcancel(struct cli_request *oldreq)
 
        /* 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;
 }