libcli/smb2: make it possible to handle incoming oplock requests
authorStefan Metzmacher <metze@samba.org>
Fri, 18 Apr 2008 20:27:24 +0000 (22:27 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 18 Apr 2008 23:54:44 +0000 (01:54 +0200)
metze

source/libcli/smb2/smb2.h
source/libcli/smb2/transport.c

index 726df64090f318c823f9e49e1eeea6fe63b75e09..ae66a6e0d3bd898916fcc36bf03d2924797b0b38 100644 (file)
@@ -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;
 };
 
 
index af19fcb0a9cbd0489d853f80a4097fa09cc1f5a3..8eb60a06f132c9a76216d762cc63bae093c76970 100644 (file)
@@ -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);