summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/smb2/smb2.h11
-rw-r--r--source4/libcli/smb2/transport.c43
2 files changed, 54 insertions, 0 deletions
diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h
index 726df64090..ae66a6e0d3 100644
--- a/source4/libcli/smb2/smb2.h
+++ b/source4/libcli/smb2/smb2.h
@@ -21,6 +21,8 @@
#include "libcli/raw/request.h"
+struct smb2_handle;
+
struct smb2_options {
uint32_t timeout;
};
@@ -58,6 +60,15 @@ struct smb2_transport {
void *private;
uint_t period;
} idle;
+
+ struct {
+ /* a oplock break request handler */
+ bool (*handler)(struct smb2_transport *transport,
+ const struct smb2_handle *handle,
+ uint8_t level, void *private_data);
+ /* private data passed to the oplock handler */
+ void *private_data;
+ } oplock;
};
diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c
index af19fcb0a9..8eb60a06f1 100644
--- a/source4/libcli/smb2/transport.c
+++ b/source4/libcli/smb2/transport.c
@@ -140,6 +140,44 @@ void smb2_transport_dead(struct smb2_transport *transport, NTSTATUS status)
}
}
+static bool smb2_handle_oplock_break(struct smb2_transport *transport,
+ const DATA_BLOB *blob)
+{
+ uint8_t *hdr;
+ uint16_t opcode;
+ uint64_t seqnum;
+
+ hdr = blob->data+NBT_HDR_SIZE;
+
+ if (blob->length < (SMB2_MIN_SIZE+0x18)) {
+ DEBUG(1,("Discarding smb2 oplock reply of size %u\n",
+ blob->length));
+ return false;
+ }
+
+ opcode = SVAL(hdr, SMB2_HDR_OPCODE);
+ seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
+
+ if ((opcode != SMB2_OP_BREAK) ||
+ (seqnum != UINT64_MAX)) {
+ return false;
+ }
+
+ if (transport->oplock.handler) {
+ uint8_t *body = hdr+SMB2_HDR_BODY;
+ struct smb2_handle h;
+ uint8_t level;
+
+ level = CVAL(body, 0x02);
+ smb2_pull_handle(body+0x08, &h);
+
+ transport->oplock.handler(transport, &h, level,
+ transport->oplock.private_data);
+ }
+
+ return true;
+}
+
/*
we have a full request in our receive buffer - match it to a pending request
and process
@@ -167,6 +205,11 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
goto error;
}
+ if (smb2_handle_oplock_break(transport, &blob)) {
+ talloc_free(buffer);
+ return NT_STATUS_OK;
+ }
+
flags = IVAL(hdr, SMB2_HDR_FLAGS);
seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID);