diff options
author | Andrew Bartlett <abartlet@samba.org> | 2008-04-19 09:59:07 +0200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2008-04-19 09:59:07 +0200 |
commit | 61fba825940b03ac954208cc0ead4ed2c0af848a (patch) | |
tree | a1bd49b2ec3ef31f39307439cdd1c4711644c44c /source4/libcli | |
parent | 0321bc02598087685c6ea144e3920a64ab909b83 (diff) | |
parent | f0eb488d221d2d12d750babac0252aac671d92f4 (diff) | |
download | samba-61fba825940b03ac954208cc0ead4ed2c0af848a.tar.gz samba-61fba825940b03ac954208cc0ead4ed2c0af848a.tar.bz2 samba-61fba825940b03ac954208cc0ead4ed2c0af848a.zip |
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-abartlet
(This used to be commit 13a0941d3432dc7dae552048265ad1e762b781d4)
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/raw/interfaces.h | 17 | ||||
-rw-r--r-- | source4/libcli/smb2/break.c | 74 | ||||
-rw-r--r-- | source4/libcli/smb2/config.mk | 2 | ||||
-rw-r--r-- | source4/libcli/smb2/smb2.h | 11 | ||||
-rw-r--r-- | source4/libcli/smb2/transport.c | 43 |
5 files changed, 145 insertions, 2 deletions
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index cf5a3aa25e..bad3743721 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -1862,7 +1862,8 @@ enum smb_lock_level { RAW_LOCK_LOCK, RAW_LOCK_UNLOCK, RAW_LOCK_LOCKX, - RAW_LOCK_SMB2 + RAW_LOCK_SMB2, + RAW_LOCK_SMB2_BREAK }; /* the generic interface is defined to be equal to the lockingX interface */ @@ -1925,6 +1926,20 @@ union smb_lock { uint16_t unknown1; } out; } smb2; + + /* SMB2 Break */ + struct smb2_break { + enum smb_lock_level level; + struct { + union smb_handle file; + + /* static body buffer 24 (0x18) bytes */ + uint8_t oplock_level; + uint8_t reserved; + uint32_t reserved2; + /* struct smb2_handle handle; */ + } in, out; + } smb2_break; }; diff --git a/source4/libcli/smb2/break.c b/source4/libcli/smb2/break.c new file mode 100644 index 0000000000..fe0cceb829 --- /dev/null +++ b/source4/libcli/smb2/break.c @@ -0,0 +1,74 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 client oplock break handling + + Copyright (C) Stefan Metzmacher 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" + +/* + send a break request +*/ +struct smb2_request *smb2_break_send(struct smb2_tree *tree, struct smb2_break *io) +{ + struct smb2_request *req; + + req = smb2_request_init_tree(tree, SMB2_OP_BREAK, 0x18, false, 0); + if (req == NULL) return NULL; + + SCVAL(req->out.body, 0x02, io->in.oplock_level); + SCVAL(req->out.body, 0x03, io->in.reserved); + SIVAL(req->out.body, 0x04, io->in.reserved2); + smb2_push_handle(req->out.body+0x08, &io->in.file.handle); + + smb2_transport_send(req); + + return req; +} + + +/* + recv a break reply +*/ +NTSTATUS smb2_break_recv(struct smb2_request *req, struct smb2_break *io) +{ + if (!smb2_request_receive(req) || + !smb2_request_is_ok(req)) { + return smb2_request_destroy(req); + } + + SMB2_CHECK_PACKET_RECV(req, 0x18, false); + + io->out.oplock_level = CVAL(req->in.body, 0x02); + io->out.reserved = CVAL(req->in.body, 0x03); + io->out.reserved2 = IVAL(req->in.body, 0x04); + smb2_pull_handle(req->in.body+0x08, &io->out.file.handle); + + return smb2_request_destroy(req); +} + +/* + sync flush request +*/ +NTSTATUS smb2_break(struct smb2_tree *tree, struct smb2_break *io) +{ + struct smb2_request *req = smb2_break_send(tree, io); + return smb2_break_recv(req, io); +} diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index e95997db54..18f6245a3e 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -6,5 +6,5 @@ LIBCLI_SMB2_OBJ_FILES = $(addprefix libcli/smb2/, \ transport.o request.o negprot.o session.o tcon.o \ create.o close.o connect.o getinfo.o write.o read.o \ setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \ - lock.o notify.o cancel.o keepalive.o) + lock.o notify.o cancel.o keepalive.o break.o) 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); |