summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/raw/clitransport.c3
-rw-r--r--source4/libcli/raw/libcliraw.h3
-rw-r--r--source4/libcli/raw/rawnotify.c43
3 files changed, 49 insertions, 0 deletions
diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c
index f579457252..2580df4aeb 100644
--- a/source4/libcli/raw/clitransport.c
+++ b/source4/libcli/raw/clitransport.c
@@ -391,6 +391,9 @@ static NTSTATUS smbcli_transport_finish_recv(void *private, DATA_BLOB blob)
if (req->mid == mid) break;
}
+ /* see if it's a ntcancel reply for the current MID */
+ req = smbcli_handle_ntcancel_reply(req, len, hdr);
+
if (!req) {
DEBUG(1,("Discarding unmatched reply with mid %d op %d\n", mid, op));
goto error;
diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h
index a853bd177c..dfc4dc37b5 100644
--- a/source4/libcli/raw/libcliraw.h
+++ b/source4/libcli/raw/libcliraw.h
@@ -231,6 +231,9 @@ struct smbcli_request {
/* the sequence number of this packet - used for signing */
uint_t seq_num;
+ /* list of ntcancel request for this requests */
+ struct smbcli_request *ntcancel;
+
/* set if this is a one-way request, meaning we are not
expecting a reply from the server. */
uint_t one_way_request:1;
diff --git a/source4/libcli/raw/rawnotify.c b/source4/libcli/raw/rawnotify.c
index e48545419f..1215a93f59 100644
--- a/source4/libcli/raw/rawnotify.c
+++ b/source4/libcli/raw/rawnotify.c
@@ -20,6 +20,7 @@
#include "includes.h"
#include "libcli/raw/libcliraw.h"
+#include "dlinklist.h"
/****************************************************************************
change notify (async send)
@@ -89,6 +90,37 @@ NTSTATUS smb_raw_changenotify_recv(struct smbcli_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
@@ -111,7 +143,18 @@ NTSTATUS smb_raw_ntcancel(struct smbcli_request *oldreq)
req->sign_single_increment = 1;
req->one_way_request = 1;
+ /*
+ * 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;
+ }
+
smbcli_request_send(req);
+ DLIST_ADD_END(oldreq->ntcancel, req, struct smbcli_request *);
+
return NT_STATUS_OK;
}