diff options
-rw-r--r-- | source4/libcli/raw/clitransport.c | 3 | ||||
-rw-r--r-- | source4/libcli/raw/libcliraw.h | 3 | ||||
-rw-r--r-- | source4/libcli/raw/rawnotify.c | 43 |
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; } |