summaryrefslogtreecommitdiffstats
path: root/source3/libsmb
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2013-09-13 15:50:10 +0200
committerStefan Metzmacher <metze@samba.org>2014-01-07 08:37:42 +0100
commit024fc73047ffb6bb25dfdfbd99dbd7f490eaaa13 (patch)
treec5b43f853ca3c6d32b53a4896dfc95e17d158add /source3/libsmb
parentacbd12adf90830070db7e5aec088aa3051dfaa63 (diff)
downloadsamba-024fc73047ffb6bb25dfdfbd99dbd7f490eaaa13.tar.gz
samba-024fc73047ffb6bb25dfdfbd99dbd7f490eaaa13.tar.xz
samba-024fc73047ffb6bb25dfdfbd99dbd7f490eaaa13.zip
libcli/smb: move source3/libsmb/cli_np_tstream.c to tstream_smbXcli_np.c
This code is generic enough to have it in the top level now. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cli_np_tstream.c1337
-rw-r--r--source3/libsmb/cli_np_tstream.h52
2 files changed, 0 insertions, 1389 deletions
diff --git a/source3/libsmb/cli_np_tstream.c b/source3/libsmb/cli_np_tstream.c
deleted file mode 100644
index 48ff8a37bf..0000000000
--- a/source3/libsmb/cli_np_tstream.c
+++ /dev/null
@@ -1,1337 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Stefan Metzmacher 2010
-
- 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 "system/network.h"
-#include "libsmb/libsmb.h"
-#include "libsmb/smb2cli.h"
-#include "../libcli/smb/smbXcli_base.h"
-#include "../lib/util/tevent_ntstatus.h"
-#include "../lib/tsocket/tsocket.h"
-#include "../lib/tsocket/tsocket_internal.h"
-#include "cli_np_tstream.h"
-#include "libcli/security/security.h"
-
-static const struct tstream_context_ops tstream_cli_np_ops;
-
-/*
- * Windows uses 4280 (the max xmit/recv size negotiated on DCERPC).
- * This is fits into the max_xmit negotiated at the SMB layer.
- *
- * On the sending side they may use SMBtranss if the request does not
- * fit into a single SMBtrans call.
- *
- * Windows uses 1024 as max data size of a SMBtrans request and then
- * possibly reads the rest of the DCERPC fragment (up to 3256 bytes)
- * via a SMBreadX.
- *
- * For now we just ask for the full 4280 bytes (max data size) in the SMBtrans
- * request to get the whole fragment at once (like samba 3.5.x and below did.
- *
- * It is important that we use do SMBwriteX with the size of a full fragment,
- * otherwise we may get NT_STATUS_PIPE_BUSY on the SMBtrans request
- * from NT4 servers. (See bug #8195)
- */
-#define TSTREAM_CLI_NP_MAX_BUF_SIZE 4280
-
-#define TSTREAM_CLI_NP_DESIRED_ACCESS ( \
- SEC_STD_READ_CONTROL | \
- SEC_FILE_READ_DATA | \
- SEC_FILE_WRITE_DATA | \
- SEC_FILE_APPEND_DATA | \
- SEC_FILE_READ_EA | \
- SEC_FILE_WRITE_EA | \
- SEC_FILE_READ_ATTRIBUTE | \
- SEC_FILE_WRITE_ATTRIBUTE | \
-0)
-
-struct tstream_cli_np_ref;
-
-struct tstream_cli_np {
- struct tstream_cli_np_ref *ref;
- struct smbXcli_conn *conn;
- struct smbXcli_session *session;
- struct smbXcli_tcon *tcon;
- uint16_t pid;
- unsigned int timeout;
-
- const char *npipe;
- bool is_smb1;
- uint16_t fnum;
- uint64_t fid_persistent;
- uint64_t fid_volatile;
-
- struct {
- bool active;
- struct tevent_req *read_req;
- struct tevent_req *write_req;
- uint16_t setup[2];
- } trans;
-
- struct {
- off_t ofs;
- size_t left;
- uint8_t *buf;
- } read, write;
-};
-
-struct tstream_cli_np_ref {
- struct tstream_cli_np *cli_nps;
-};
-
-static int tstream_cli_np_destructor(struct tstream_cli_np *cli_nps)
-{
- NTSTATUS status;
-
- if (cli_nps->ref != NULL) {
- cli_nps->ref->cli_nps = NULL;
- TALLOC_FREE(cli_nps->ref);
- }
-
- if (!smbXcli_conn_is_connected(cli_nps->conn)) {
- return 0;
- }
-
- /*
- * TODO: do not use a sync call with a destructor!!!
- *
- * This only happens, if a caller does talloc_free(),
- * while the everything was still ok.
- *
- * If we get an unexpected failure within a normal
- * operation, we already do an async cli_close_send()/_recv().
- *
- * Once we've fixed all callers to call
- * tstream_disconnect_send()/_recv(), this will
- * never be called.
- */
- if (cli_nps->is_smb1) {
- status = smb1cli_close(cli_nps->conn,
- cli_nps->timeout,
- cli_nps->pid,
- cli_nps->tcon,
- cli_nps->session,
- cli_nps->fnum, UINT32_MAX);
- } else {
- status = smb2cli_close(cli_nps->conn,
- cli_nps->timeout,
- cli_nps->session,
- cli_nps->tcon,
- 0, /* flags */
- cli_nps->fid_persistent,
- cli_nps->fid_volatile);
- }
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("tstream_cli_np_destructor: cli_close "
- "failed on pipe %s. Error was %s\n",
- cli_nps->npipe, nt_errstr(status)));
- }
- /*
- * We can't do much on failure
- */
- return 0;
-}
-
-static int tstream_cli_np_ref_destructor(struct tstream_cli_np_ref *ref)
-{
- if (ref->cli_nps == NULL) {
- return 0;
- }
-
- ref->cli_nps->conn = NULL;
- ref->cli_nps->session = NULL;
- ref->cli_nps->tcon = NULL;
- ref->cli_nps->ref = NULL;
-
- return 0;
-};
-
-struct tstream_cli_np_open_state {
- struct smbXcli_conn *conn;
- struct smbXcli_session *session;
- struct smbXcli_tcon *tcon;
- uint16_t pid;
- unsigned int timeout;
-
- bool is_smb1;
- uint16_t fnum;
- uint64_t fid_persistent;
- uint64_t fid_volatile;
- const char *npipe;
-};
-
-static void tstream_cli_np_open_done(struct tevent_req *subreq);
-
-struct tevent_req *tstream_cli_np_open_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbXcli_conn *conn,
- struct smbXcli_session *session,
- struct smbXcli_tcon *tcon,
- uint16_t pid, unsigned int timeout,
- const char *npipe)
-{
- struct tevent_req *req;
- struct tstream_cli_np_open_state *state;
- struct tevent_req *subreq;
-
- req = tevent_req_create(mem_ctx, &state,
- struct tstream_cli_np_open_state);
- if (!req) {
- return NULL;
- }
- state->conn = conn;
- state->tcon = tcon;
- state->session = session;
- state->pid = pid;
- state->timeout = timeout;
-
- state->npipe = talloc_strdup(state, npipe);
- if (tevent_req_nomem(state->npipe, req)) {
- return tevent_req_post(req, ev);
- }
-
- if (smbXcli_conn_protocol(conn) < PROTOCOL_SMB2_02) {
- state->is_smb1 = true;
- }
-
- if (state->is_smb1) {
- const char *smb1_npipe;
-
- /*
- * Windows and newer Samba versions allow
- * the pipe name without leading backslash,
- * but we should better behave like windows clients
- */
- smb1_npipe = talloc_asprintf(state, "\\%s", state->npipe);
- if (tevent_req_nomem(smb1_npipe, req)) {
- return tevent_req_post(req, ev);
- }
- subreq = smb1cli_ntcreatex_send(state, ev, state->conn,
- state->timeout,
- state->pid,
- state->tcon,
- state->session,
- smb1_npipe,
- 0, /* CreatFlags */
- 0, /* RootDirectoryFid */
- TSTREAM_CLI_NP_DESIRED_ACCESS,
- 0, /* AllocationSize */
- 0, /* FileAttributes */
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, /* CreateDisposition */
- 0, /* CreateOptions */
- 2, /* NTCREATEX_IMPERSONATION_IMPERSONATION */
- 0); /* SecurityFlags */
- } else {
- subreq = smb2cli_create_send(state, ev, state->conn,
- state->timeout, state->session,
- state->tcon,
- npipe,
- SMB2_OPLOCK_LEVEL_NONE,
- SMB2_IMPERSONATION_IMPERSONATION,
- TSTREAM_CLI_NP_DESIRED_ACCESS,
- 0, /* file_attributes */
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN,
- 0, /* create_options */
- NULL); /* blobs */
- }
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, tstream_cli_np_open_done, req);
-
- return req;
-}
-
-static void tstream_cli_np_open_done(struct tevent_req *subreq)
-{
- struct tevent_req *req =
- tevent_req_callback_data(subreq, struct tevent_req);
- struct tstream_cli_np_open_state *state =
- tevent_req_data(req, struct tstream_cli_np_open_state);
- NTSTATUS status;
-
- if (state->is_smb1) {
- status = smb1cli_ntcreatex_recv(subreq, &state->fnum);
- } else {
- status = smb2cli_create_recv(subreq,
- &state->fid_persistent,
- &state->fid_volatile,
- NULL);
- }
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- }
-
- tevent_req_done(req);
-}
-
-NTSTATUS _tstream_cli_np_open_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- struct tstream_context **_stream,
- const char *location)
-{
- struct tstream_cli_np_open_state *state =
- tevent_req_data(req, struct tstream_cli_np_open_state);
- struct tstream_context *stream;
- struct tstream_cli_np *cli_nps;
- NTSTATUS status;
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- stream = tstream_context_create(mem_ctx,
- &tstream_cli_np_ops,
- &cli_nps,
- struct tstream_cli_np,
- location);
- if (!stream) {
- tevent_req_received(req);
- return NT_STATUS_NO_MEMORY;
- }
- ZERO_STRUCTP(cli_nps);
-
- cli_nps->ref = talloc_zero(state->conn, struct tstream_cli_np_ref);
- if (cli_nps->ref == NULL) {
- TALLOC_FREE(cli_nps);
- tevent_req_received(req);
- return NT_STATUS_NO_MEMORY;
- }
- cli_nps->ref->cli_nps = cli_nps;
- cli_nps->conn = state->conn;
- cli_nps->session = state->session;
- cli_nps->tcon = state->tcon;
- cli_nps->pid = state->pid;
- cli_nps->timeout = state->timeout;
- cli_nps->npipe = talloc_move(cli_nps, &state->npipe);
- cli_nps->is_smb1 = state->is_smb1;
- cli_nps->fnum = state->fnum;
- cli_nps->fid_persistent = state->fid_persistent;
- cli_nps->fid_volatile = state->fid_volatile;
-
- talloc_set_destructor(cli_nps, tstream_cli_np_destructor);
- talloc_set_destructor(cli_nps->ref, tstream_cli_np_ref_destructor);
-
- cli_nps->trans.active = false;
- cli_nps->trans.read_req = NULL;
- cli_nps->trans.write_req = NULL;
- SSVAL(cli_nps->trans.setup+0, 0, TRANSACT_DCERPCCMD);
- SSVAL(cli_nps->trans.setup+1, 0, cli_nps->fnum);
-
- *_stream = stream;
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
-
-static ssize_t tstream_cli_np_pending_bytes(struct tstream_context *stream)
-{
- struct tstream_cli_np *cli_nps = tstream_context_data(stream,
- struct tstream_cli_np);
-
- if (!smbXcli_conn_is_connected(cli_nps->conn)) {
- errno = ENOTCONN;
- return -1;
- }
-
- return cli_nps->read.left;
-}
-
-bool tstream_is_cli_np(struct tstream_context *stream)
-{
- struct tstream_cli_np *cli_nps =
- talloc_get_type(_tstream_context_data(stream),
- struct tstream_cli_np);
-
- if (!cli_nps) {
- return false;
- }
-
- return true;
-}
-
-NTSTATUS tstream_cli_np_use_trans(struct tstream_context *stream)
-{
- struct tstream_cli_np *cli_nps = tstream_context_data(stream,
- struct tstream_cli_np);
-
- if (cli_nps->trans.read_req) {
- return NT_STATUS_PIPE_BUSY;
- }
-
- if (cli_nps->trans.write_req) {
- return NT_STATUS_PIPE_BUSY;
- }
-
- if (cli_nps->trans.active) {
- return NT_STATUS_PIPE_BUSY;
- }
-
- cli_nps->trans.active = true;
-
- return NT_STATUS_OK;
-}
-
-unsigned int tstream_cli_np_set_timeout(struct tstream_context *stream,
- unsigned int timeout)
-{
- struct tstream_cli_np *cli_nps = tstream_context_data(stream,
- struct tstream_cli_np);
- unsigned int old_timeout = cli_nps->timeout;
-
- cli_nps->timeout = timeout;
- return old_timeout;
-}
-
-struct tstream_cli_np_writev_state {
- struct tstream_context *stream;
- struct tevent_context *ev;
-
- struct iovec *vector;
- size_t count;
-
- int ret;
-
- struct {
- int val;
- const char *location;
- } error;
-};
-
-static int tstream_cli_np_writev_state_destructor(struct tstream_cli_np_writev_state *state)
-{
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
-
- cli_nps->trans.write_req = NULL;
-
- return 0;
-}
-
-static void tstream_cli_np_writev_write_next(struct tevent_req *req);
-
-static struct tevent_req *tstream_cli_np_writev_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct tstream_context *stream,
- const struct iovec *vector,
- size_t count)
-{
- struct tevent_req *req;
- struct tstream_cli_np_writev_state *state;
- struct tstream_cli_np *cli_nps = tstream_context_data(stream,
- struct tstream_cli_np);
-
- req = tevent_req_create(mem_ctx, &state,
- struct tstream_cli_np_writev_state);
- if (!req) {
- return NULL;
- }
- state->stream = stream;
- state->ev = ev;
- state->ret = 0;
-
- talloc_set_destructor(state, tstream_cli_np_writev_state_destructor);
-
- if (!smbXcli_conn_is_connected(cli_nps->conn)) {
- tevent_req_error(req, ENOTCONN);
- return tevent_req_post(req, ev);
- }
-
- /*
- * we make a copy of the vector so we can change the structure
- */
- state->vector = talloc_array(state, struct iovec, count);
- if (tevent_req_nomem(state->vector, req)) {
- return tevent_req_post(req, ev);
- }
- memcpy(state->vector, vector, sizeof(struct iovec) * count);
- state->count = count;
-
- tstream_cli_np_writev_write_next(req);
- if (!tevent_req_is_in_progress(req)) {
- return tevent_req_post(req, ev);
- }
-
- return req;
-}
-
-static void tstream_cli_np_readv_trans_start(struct tevent_req *req);
-static void tstream_cli_np_writev_write_done(struct tevent_req *subreq);
-
-static void tstream_cli_np_writev_write_next(struct tevent_req *req)
-{
- struct tstream_cli_np_writev_state *state =
- tevent_req_data(req,
- struct tstream_cli_np_writev_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
- struct tevent_req *subreq;
- size_t i;
- size_t left = 0;
-
- for (i=0; i < state->count; i++) {
- left += state->vector[i].iov_len;
- }
-
- if (left == 0) {
- TALLOC_FREE(cli_nps->write.buf);
- tevent_req_done(req);
- return;
- }
-
- cli_nps->write.ofs = 0;
- cli_nps->write.left = MIN(left, TSTREAM_CLI_NP_MAX_BUF_SIZE);
- cli_nps->write.buf = talloc_realloc(cli_nps, cli_nps->write.buf,
- uint8_t, cli_nps->write.left);
- if (tevent_req_nomem(cli_nps->write.buf, req)) {
- return;
- }
-
- /*
- * copy the pending buffer first
- */
- while (cli_nps->write.left > 0 && state->count > 0) {
- uint8_t *base = (uint8_t *)state->vector[0].iov_base;
- size_t len = MIN(cli_nps->write.left, state->vector[0].iov_len);
-
- memcpy(cli_nps->write.buf + cli_nps->write.ofs, base, len);
-
- base += len;
- state->vector[0].iov_base = base;
- state->vector[0].iov_len -= len;
-
- cli_nps->write.ofs += len;
- cli_nps->write.left -= len;
-
- if (state->vector[0].iov_len == 0) {
- state->vector += 1;
- state->count -= 1;
- }
-
- state->ret += len;
- }
-
- if (cli_nps->trans.active && state->count == 0) {
- cli_nps->trans.active = false;
- cli_nps->trans.write_req = req;
- return;
- }
-
- if (cli_nps->trans.read_req && state->count == 0) {
- cli_nps->trans.write_req = req;
- tstream_cli_np_readv_trans_start(cli_nps->trans.read_req);
- return;
- }
-
- if (cli_nps->is_smb1) {
- subreq = smb1cli_writex_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->pid,
- cli_nps->tcon,
- cli_nps->session,
- cli_nps->fnum,
- 8, /* 8 means message mode. */
- cli_nps->write.buf,
- 0, /* offset */
- cli_nps->write.ofs); /* size */
- } else {
- subreq = smb2cli_write_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->session,
- cli_nps->tcon,
- cli_nps->write.ofs, /* length */
- 0, /* offset */
- cli_nps->fid_persistent,
- cli_nps->fid_volatile,
- 0, /* remaining_bytes */
- 0, /* flags */
- cli_nps->write.buf);
- }
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq,
- tstream_cli_np_writev_write_done,
- req);
-}
-
-static void tstream_cli_np_writev_disconnect_now(struct tevent_req *req,
- int error,
- const char *location);
-
-static void tstream_cli_np_writev_write_done(struct tevent_req *subreq)
-{
- struct tevent_req *req =
- tevent_req_callback_data(subreq, struct tevent_req);
- struct tstream_cli_np_writev_state *state =
- tevent_req_data(req, struct tstream_cli_np_writev_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
- uint32_t written;
- NTSTATUS status;
-
- if (cli_nps->is_smb1) {
- status = smb1cli_writex_recv(subreq, &written, NULL);
- } else {
- status = smb2cli_write_recv(subreq, &written);
- }
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tstream_cli_np_writev_disconnect_now(req, EIO, __location__);
- return;
- }
-
- if (written != cli_nps->write.ofs) {
- tstream_cli_np_writev_disconnect_now(req, EIO, __location__);
- return;
- }
-
- tstream_cli_np_writev_write_next(req);
-}
-
-static void tstream_cli_np_writev_disconnect_done(struct tevent_req *subreq);
-
-static void tstream_cli_np_writev_disconnect_now(struct tevent_req *req,
- int error,
- const char *location)
-{
- struct tstream_cli_np_writev_state *state =
- tevent_req_data(req,
- struct tstream_cli_np_writev_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
- struct tevent_req *subreq;
-
- state->error.val = error;
- state->error.location = location;
-
- if (!smbXcli_conn_is_connected(cli_nps->conn)) {
- /* return the original error */
- _tevent_req_error(req, state->error.val, state->error.location);
- return;
- }
-
- if (cli_nps->is_smb1) {
- subreq = smb1cli_close_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->pid,
- cli_nps->tcon,
- cli_nps->session,
- cli_nps->fnum, UINT32_MAX);
- } else {
- subreq = smb2cli_close_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->session,
- cli_nps->tcon,
- 0, /* flags */
- cli_nps->fid_persistent,
- cli_nps->fid_volatile);
- }
- if (subreq == NULL) {
- /* return the original error */
- _tevent_req_error(req, state->error.val, state->error.location);
- return;
- }
- tevent_req_set_callback(subreq,
- tstream_cli_np_writev_disconnect_done,
- req);
-}
-
-static void tstream_cli_np_writev_disconnect_done(struct tevent_req *subreq)
-{
- struct tevent_req *req =
- tevent_req_callback_data(subreq, struct tevent_req);
- struct tstream_cli_np_writev_state *state =
- tevent_req_data(req, struct tstream_cli_np_writev_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream, struct tstream_cli_np);
-
- if (cli_nps->is_smb1) {
- smb1cli_close_recv(subreq);
- } else {
- smb2cli_close_recv(subreq);
- }
- TALLOC_FREE(subreq);
-
- cli_nps->conn = NULL;
- cli_nps->tcon = NULL;
- cli_nps->session = NULL;
-
- /* return the original error */
- _tevent_req_error(req, state->error.val, state->error.location);
-}
-
-static int tstream_cli_np_writev_recv(struct tevent_req *req,
- int *perrno)
-{
- struct tstream_cli_np_writev_state *state =
- tevent_req_data(req,
- struct tstream_cli_np_writev_state);
- int ret;
-
- ret = tsocket_simple_int_recv(req, perrno);
- if (ret == 0) {
- ret = state->ret;
- }
-
- tevent_req_received(req);
- return ret;
-}
-
-struct tstream_cli_np_readv_state {
- struct tstream_context *stream;
- struct tevent_context *ev;
-
- struct iovec *vector;
- size_t count;
-
- int ret;
-
- struct {
- struct tevent_immediate *im;
- } trans;
-
- struct {
- int val;
- const char *location;
- } error;
-};
-
-static int tstream_cli_np_readv_state_destructor(struct tstream_cli_np_readv_state *state)
-{
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
-
- cli_nps->trans.read_req = NULL;
-
- return 0;
-}
-
-static void tstream_cli_np_readv_read_next(struct tevent_req *req);
-
-static struct tevent_req *tstream_cli_np_readv_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct tstream_context *stream,
- struct iovec *vector,
- size_t count)
-{
- struct tevent_req *req;
- struct tstream_cli_np_readv_state *state;
- struct tstream_cli_np *cli_nps =
- tstream_context_data(stream, struct tstream_cli_np);
-
- req = tevent_req_create(mem_ctx, &state,
- struct tstream_cli_np_readv_state);
- if (!req) {
- return NULL;
- }
- state->stream = stream;
- state->ev = ev;
- state->ret = 0;
-
- talloc_set_destructor(state, tstream_cli_np_readv_state_destructor);
-
- if (!smbXcli_conn_is_connected(cli_nps->conn)) {
- tevent_req_error(req, ENOTCONN);
- return tevent_req_post(req, ev);
- }
-
- /*
- * we make a copy of the vector so we can change the structure
- */
- state->vector = talloc_array(state, struct iovec, count);
- if (tevent_req_nomem(state->vector, req)) {
- return tevent_req_post(req, ev);
- }
- memcpy(state->vector, vector, sizeof(struct iovec) * count);
- state->count = count;
-
- tstream_cli_np_readv_read_next(req);
- if (!tevent_req_is_in_progress(req)) {
- return tevent_req_post(req, ev);
- }
-
- return req;
-}
-
-static void tstream_cli_np_readv_read_done(struct tevent_req *subreq);
-
-static void tstream_cli_np_readv_read_next(struct tevent_req *req)
-{
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req,
- struct tstream_cli_np_readv_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
- struct tevent_req *subreq;
-
- /*
- * copy the pending buffer first
- */
- while (cli_nps->read.left > 0 && state->count > 0) {
- uint8_t *base = (uint8_t *)state->vector[0].iov_base;
- size_t len = MIN(cli_nps->read.left, state->vector[0].iov_len);
-
- memcpy(base, cli_nps->read.buf + cli_nps->read.ofs, len);
-
- base += len;
- state->vector[0].iov_base = base;
- state->vector[0].iov_len -= len;
-
- cli_nps->read.ofs += len;
- cli_nps->read.left -= len;
-
- if (state->vector[0].iov_len == 0) {
- state->vector += 1;
- state->count -= 1;
- }
-
- state->ret += len;
- }
-
- if (cli_nps->read.left == 0) {
- TALLOC_FREE(cli_nps->read.buf);
- }
-
- if (state->count == 0) {
- tevent_req_done(req);
- return;
- }
-
- if (cli_nps->trans.active) {
- cli_nps->trans.active = false;
- cli_nps->trans.read_req = req;
- return;
- }
-
- if (cli_nps->trans.write_req) {
- cli_nps->trans.read_req = req;
- tstream_cli_np_readv_trans_start(req);
- return;
- }
-
- if (cli_nps->is_smb1) {
- subreq = smb1cli_readx_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->pid,
- cli_nps->tcon,
- cli_nps->session,
- cli_nps->fnum,
- 0, /* offset */
- TSTREAM_CLI_NP_MAX_BUF_SIZE);
- } else {
- subreq = smb2cli_read_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->session,
- cli_nps->tcon,
- TSTREAM_CLI_NP_MAX_BUF_SIZE, /* length */
- 0, /* offset */
- cli_nps->fid_persistent,
- cli_nps->fid_volatile,
- 0, /* minimum_count */
- 0); /* remaining_bytes */
- }
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq,
- tstream_cli_np_readv_read_done,
- req);
-}
-
-static void tstream_cli_np_readv_trans_done(struct tevent_req *subreq);
-
-static void tstream_cli_np_readv_trans_start(struct tevent_req *req)
-{
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req,
- struct tstream_cli_np_readv_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
- struct tevent_req *subreq;
-
- state->trans.im = tevent_create_immediate(state);
- if (tevent_req_nomem(state->trans.im, req)) {
- return;
- }
-
- if (cli_nps->is_smb1) {
- subreq = smb1cli_trans_send(state, state->ev,
- cli_nps->conn, SMBtrans,
- 0, 0, /* *_flags */
- 0, 0, /* *_flags2 */
- cli_nps->timeout,
- cli_nps->pid,
- cli_nps->tcon,
- cli_nps->session,
- "\\PIPE\\",
- 0, 0, 0,
- cli_nps->trans.setup, 2,
- 0,
- NULL, 0, 0,
- cli_nps->write.buf,
- cli_nps->write.ofs,
- TSTREAM_CLI_NP_MAX_BUF_SIZE);
- } else {
- DATA_BLOB in_input_buffer = data_blob_null;
- DATA_BLOB in_output_buffer = data_blob_null;
-
- in_input_buffer = data_blob_const(cli_nps->write.buf,
- cli_nps->write.ofs);
-
- subreq = smb2cli_ioctl_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->session,
- cli_nps->tcon,
- cli_nps->fid_persistent,
- cli_nps->fid_volatile,
- FSCTL_NAMED_PIPE_READ_WRITE,
- 0, /* in_max_input_length */
- &in_input_buffer,
- /* in_max_output_length */
- TSTREAM_CLI_NP_MAX_BUF_SIZE,
- &in_output_buffer,
- SMB2_IOCTL_FLAG_IS_FSCTL);
- }
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq,
- tstream_cli_np_readv_trans_done,
- req);
-}
-
-static void tstream_cli_np_readv_disconnect_now(struct tevent_req *req,
- int error,
- const char *location);
-static void tstream_cli_np_readv_trans_next(struct tevent_context *ctx,
- struct tevent_immediate *im,
- void *private_data);
-
-static void tstream_cli_np_readv_trans_done(struct tevent_req *subreq)
-{
- struct tevent_req *req =
- tevent_req_callback_data(subreq, struct tevent_req);
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req, struct tstream_cli_np_readv_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream, struct tstream_cli_np);
- uint8_t *rcvbuf;
- uint32_t received;
- NTSTATUS status;
-
- if (cli_nps->is_smb1) {
- status = smb1cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
- NULL, 0, NULL,
- &rcvbuf, 0, &received);
- } else {
- DATA_BLOB out_input_buffer = data_blob_null;
- DATA_BLOB out_output_buffer = data_blob_null;
-
- status = smb2cli_ioctl_recv(subreq, state,
- &out_input_buffer,
- &out_output_buffer);
-
- /* Note that rcvbuf is not a talloc pointer here */
- rcvbuf = out_output_buffer.data;
- received = out_output_buffer.length;
- }
- TALLOC_FREE(subreq);
- if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
- status = NT_STATUS_OK;
- }
- if (!NT_STATUS_IS_OK(status)) {
- tstream_cli_np_readv_disconnect_now(req, EIO, __location__);
- return;
- }
-
- if (received > TSTREAM_CLI_NP_MAX_BUF_SIZE) {
- tstream_cli_np_readv_disconnect_now(req, EIO, __location__);
- return;
- }
-
- if (received == 0) {
- tstream_cli_np_readv_disconnect_now(req, EPIPE, __location__);
- return;
- }
-
- cli_nps->read.ofs = 0;
- cli_nps->read.left = received;
- cli_nps->read.buf = talloc_array(cli_nps, uint8_t, received);
- if (cli_nps->read.buf == NULL) {
- TALLOC_FREE(subreq);
- tevent_req_nomem(cli_nps->read.buf, req);
- return;
- }
- memcpy(cli_nps->read.buf, rcvbuf, received);
-
- if (cli_nps->trans.write_req == NULL) {
- tstream_cli_np_readv_read_next(req);
- return;
- }
-
- tevent_schedule_immediate(state->trans.im, state->ev,
- tstream_cli_np_readv_trans_next, req);
-
- tevent_req_done(cli_nps->trans.write_req);
-}
-
-static void tstream_cli_np_readv_trans_next(struct tevent_context *ctx,
- struct tevent_immediate *im,
- void *private_data)
-{
- struct tevent_req *req =
- talloc_get_type_abort(private_data,
- struct tevent_req);
-
- tstream_cli_np_readv_read_next(req);
-}
-
-static void tstream_cli_np_readv_read_done(struct tevent_req *subreq)
-{
- struct tevent_req *req =
- tevent_req_callback_data(subreq, struct tevent_req);
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req, struct tstream_cli_np_readv_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream, struct tstream_cli_np);
- uint8_t *rcvbuf;
- uint32_t received;
- NTSTATUS status;
-
- /*
- * We must free subreq in this function as there is
- * a timer event attached to it.
- */
-
- if (cli_nps->is_smb1) {
- status = smb1cli_readx_recv(subreq, &received, &rcvbuf);
- } else {
- status = smb2cli_read_recv(subreq, state, &rcvbuf, &received);
- }
- /*
- * We can't TALLOC_FREE(subreq) as usual here, as rcvbuf still is a
- * child of that.
- */
- if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
- /*
- * NT_STATUS_BUFFER_TOO_SMALL means that there's
- * more data to read when the named pipe is used
- * in message mode (which is the case here).
- *
- * But we hide this from the caller.
- */
- status = NT_STATUS_OK;
- }
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(subreq);
- tstream_cli_np_readv_disconnect_now(req, EIO, __location__);
- return;
- }
-
- if (received > TSTREAM_CLI_NP_MAX_BUF_SIZE) {
- TALLOC_FREE(subreq);
- tstream_cli_np_readv_disconnect_now(req, EIO, __location__);
- return;
- }
-
- if (received == 0) {
- TALLOC_FREE(subreq);
- tstream_cli_np_readv_disconnect_now(req, EPIPE, __location__);
- return;
- }
-
- cli_nps->read.ofs = 0;
- cli_nps->read.left = received;
- cli_nps->read.buf = talloc_array(cli_nps, uint8_t, received);
- if (cli_nps->read.buf == NULL) {
- TALLOC_FREE(subreq);
- tevent_req_nomem(cli_nps->read.buf, req);
- return;
- }
- memcpy(cli_nps->read.buf, rcvbuf, received);
- TALLOC_FREE(subreq);
-
- tstream_cli_np_readv_read_next(req);
-}
-
-static void tstream_cli_np_readv_disconnect_done(struct tevent_req *subreq);
-
-static void tstream_cli_np_readv_error(struct tevent_req *req);
-
-static void tstream_cli_np_readv_disconnect_now(struct tevent_req *req,
- int error,
- const char *location)
-{
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req,
- struct tstream_cli_np_readv_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
- struct tevent_req *subreq;
-
- state->error.val = error;
- state->error.location = location;
-
- if (!smbXcli_conn_is_connected(cli_nps->conn)) {
- /* return the original error */
- tstream_cli_np_readv_error(req);
- return;
- }
-
- if (cli_nps->is_smb1) {
- subreq = smb1cli_close_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->pid,
- cli_nps->tcon,
- cli_nps->session,
- cli_nps->fnum, UINT32_MAX);
- } else {
- subreq = smb2cli_close_send(state, state->ev,
- cli_nps->conn,
- cli_nps->timeout,
- cli_nps->session,
- cli_nps->tcon,
- 0, /* flags */
- cli_nps->fid_persistent,
- cli_nps->fid_volatile);
- }
- if (subreq == NULL) {
- /* return the original error */
- tstream_cli_np_readv_error(req);
- return;
- }
- tevent_req_set_callback(subreq,
- tstream_cli_np_readv_disconnect_done,
- req);
-}
-
-static void tstream_cli_np_readv_disconnect_done(struct tevent_req *subreq)
-{
- struct tevent_req *req =
- tevent_req_callback_data(subreq, struct tevent_req);
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req, struct tstream_cli_np_readv_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream, struct tstream_cli_np);
-
- if (cli_nps->is_smb1) {
- smb1cli_close_recv(subreq);
- } else {
- smb2cli_close_recv(subreq);
- }
- TALLOC_FREE(subreq);
-
- cli_nps->conn = NULL;
- cli_nps->session = NULL;
- cli_nps->tcon = NULL;
-
- tstream_cli_np_readv_error(req);
-}
-
-static void tstream_cli_np_readv_error_trigger(struct tevent_context *ctx,
- struct tevent_immediate *im,
- void *private_data);
-
-static void tstream_cli_np_readv_error(struct tevent_req *req)
-{
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req,
- struct tstream_cli_np_readv_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream,
- struct tstream_cli_np);
-
- if (cli_nps->trans.write_req == NULL) {
- /* return the original error */
- _tevent_req_error(req, state->error.val, state->error.location);
- return;
- }
-
- if (state->trans.im == NULL) {
- /* return the original error */
- _tevent_req_error(req, state->error.val, state->error.location);
- return;
- }
-
- tevent_schedule_immediate(state->trans.im, state->ev,
- tstream_cli_np_readv_error_trigger, req);
-
- /* return the original error for writev */
- _tevent_req_error(cli_nps->trans.write_req,
- state->error.val, state->error.location);
-}
-
-static void tstream_cli_np_readv_error_trigger(struct tevent_context *ctx,
- struct tevent_immediate *im,
- void *private_data)
-{
- struct tevent_req *req =
- talloc_get_type_abort(private_data,
- struct tevent_req);
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req,
- struct tstream_cli_np_readv_state);
-
- /* return the original error */
- _tevent_req_error(req, state->error.val, state->error.location);
-}
-
-static int tstream_cli_np_readv_recv(struct tevent_req *req,
- int *perrno)
-{
- struct tstream_cli_np_readv_state *state =
- tevent_req_data(req, struct tstream_cli_np_readv_state);
- int ret;
-
- ret = tsocket_simple_int_recv(req, perrno);
- if (ret == 0) {
- ret = state->ret;
- }
-
- tevent_req_received(req);
- return ret;
-}
-
-struct tstream_cli_np_disconnect_state {
- struct tstream_context *stream;
-};
-
-static void tstream_cli_np_disconnect_done(struct tevent_req *subreq);
-
-static struct tevent_req *tstream_cli_np_disconnect_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct tstream_context *stream)
-{
- struct tstream_cli_np *cli_nps = tstream_context_data(stream,
- struct tstream_cli_np);
- struct tevent_req *req;
- struct tstream_cli_np_disconnect_state *state;
- struct tevent_req *subreq;
-
- req = tevent_req_create(mem_ctx, &state,
- struct tstream_cli_np_disconnect_state);
- if (req == NULL) {
- return NULL;
- }
-
- state->stream = stream;
-
- if (!smbXcli_conn_is_connected(cli_nps->conn)) {
- tevent_req_error(req, ENOTCONN);
- return tevent_req_post(req, ev);
- }
-
- if (cli_nps->is_smb1) {
- subreq = smb1cli_close_send(state, ev, cli_nps->conn,
- cli_nps->timeout,
- cli_nps->pid,
- cli_nps->tcon,
- cli_nps->session,
- cli_nps->fnum, UINT32_MAX);
- } else {
- subreq = smb2cli_close_send(state, ev, cli_nps->conn,
- cli_nps->timeout,
- cli_nps->session,
- cli_nps->tcon,
- 0, /* flags */
- cli_nps->fid_persistent,
- cli_nps->fid_volatile);
- }
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, tstream_cli_np_disconnect_done, req);
-
- return req;
-}
-
-static void tstream_cli_np_disconnect_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct tstream_cli_np_disconnect_state *state =
- tevent_req_data(req, struct tstream_cli_np_disconnect_state);
- struct tstream_cli_np *cli_nps =
- tstream_context_data(state->stream, struct tstream_cli_np);
- NTSTATUS status;
-
- if (cli_nps->is_smb1) {
- status = smb1cli_close_recv(subreq);
- } else {
- status = smb2cli_close_recv(subreq);
- }
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_error(req, EIO);
- return;
- }
-
- cli_nps->conn = NULL;
- cli_nps->session = NULL;
- cli_nps->tcon = NULL;
-
- tevent_req_done(req);
-}
-
-static int tstream_cli_np_disconnect_recv(struct tevent_req *req,
- int *perrno)
-{
- int ret;
-
- ret = tsocket_simple_int_recv(req, perrno);
-
- tevent_req_received(req);
- return ret;
-}
-
-static const struct tstream_context_ops tstream_cli_np_ops = {
- .name = "cli_np",
-
- .pending_bytes = tstream_cli_np_pending_bytes,
-
- .readv_send = tstream_cli_np_readv_send,
- .readv_recv = tstream_cli_np_readv_recv,
-
- .writev_send = tstream_cli_np_writev_send,
- .writev_recv = tstream_cli_np_writev_recv,
-
- .disconnect_send = tstream_cli_np_disconnect_send,
- .disconnect_recv = tstream_cli_np_disconnect_recv,
-};
diff --git a/source3/libsmb/cli_np_tstream.h b/source3/libsmb/cli_np_tstream.h
deleted file mode 100644
index 2404e7844a..0000000000
--- a/source3/libsmb/cli_np_tstream.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Stefan Metzmacher 2010
-
- 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/>.
-*/
-
-#ifndef _CLI_NP_TSTREAM_H_
-#define _CLI_NP_TSTREAM_H_
-
-struct tevent_context;
-struct tevent_req;
-struct cli_state;
-struct tstream_context;
-struct smbXcli_conn;
-struct smbXcli_session;
-struct smbXcli_tcon;
-
-struct tevent_req *tstream_cli_np_open_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbXcli_conn *conn,
- struct smbXcli_session *session,
- struct smbXcli_tcon *tcon,
- uint16_t pid, unsigned int timeout,
- const char *npipe);
-NTSTATUS _tstream_cli_np_open_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- struct tstream_context **_stream,
- const char *location);
-#define tstream_cli_np_open_recv(req, mem_ctx, stream) \
- _tstream_cli_np_open_recv(req, mem_ctx, stream, __location__)
-
-bool tstream_is_cli_np(struct tstream_context *stream);
-
-NTSTATUS tstream_cli_np_use_trans(struct tstream_context *stream);
-
-unsigned int tstream_cli_np_set_timeout(struct tstream_context *stream,
- unsigned int timeout);
-
-#endif /* _CLI_NP_TSTREAM_H_ */