Exemplo n.º 1
0
/*
  mark the transport as dead
*/
void smb2_transport_dead(struct smb2_transport *transport, NTSTATUS status)
{
    if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
        status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    }
    if (NT_STATUS_IS_OK(status)) {
        status = NT_STATUS_LOCAL_DISCONNECT;
    }

    smbXcli_conn_disconnect(transport->conn, status);
}
Exemplo n.º 2
0
static void _cli_shutdown(struct cli_state *cli)
{
	cli_nt_pipes_close(cli);

	/*
	 * tell our peer to free his resources.  Wihtout this, when an
	 * application attempts to do a graceful shutdown and calls
	 * smbc_free_context() to clean up all connections, some connections
	 * can remain active on the peer end, until some (long) timeout period
	 * later.  This tree disconnect forces the peer to clean up, since the
	 * connection will be going away.
	 */
	if (cli_state_has_tcon(cli)) {
		cli_tdis(cli);
	}

	smbXcli_conn_disconnect(cli->conn, NT_STATUS_OK);

	TALLOC_FREE(cli);
}
Exemplo n.º 3
0
/*
  put a request into the send queue
*/
void smb2_transport_send(struct smb2_request *req)
{
    NTSTATUS status;
    struct smb2_transport *transport = req->transport;
    struct tevent_req **reqs = transport->compound.reqs;
    size_t num_reqs = talloc_array_length(reqs);
    size_t i;
    uint16_t cmd = SVAL(req->out.hdr, SMB2_HDR_OPCODE);
    uint32_t additional_flags = IVAL(req->out.hdr, SMB2_HDR_FLAGS);
    uint32_t clear_flags = 0;
    uint32_t pid = IVAL(req->out.hdr, SMB2_HDR_PID);
    uint32_t tid = IVAL(req->out.hdr, SMB2_HDR_TID);
    struct smbXcli_session *session = NULL;
    bool need_pending_break = false;
    size_t hdr_ofs;
    size_t pdu_len;
    DATA_BLOB body = data_blob_null;
    DATA_BLOB dyn = data_blob_null;
    uint32_t timeout_msec = transport->options.request_timeout * 1000;

    if (transport->oplock.handler) {
        need_pending_break = true;
    }

    if (transport->lease.handler) {
        need_pending_break = true;
    }

    if (transport->break_subreq) {
        need_pending_break = false;
    }

    if (need_pending_break) {
        struct tevent_req *subreq;

        subreq = smb2cli_req_create(transport,
                                    transport->ev,
                                    transport->conn,
                                    SMB2_OP_BREAK,
                                    0, /* additional_flags */
                                    0, /*clear_flags */
                                    0, /* timeout_msec */
                                    0, /* pid */
                                    0, /* tid */
                                    NULL, /* session */
                                    NULL, /* body */
                                    0, /* body_fixed */
                                    NULL, /* dyn */
                                    0); /* dyn_len */
        if (subreq != NULL) {
            smbXcli_req_set_pending(subreq);
            tevent_req_set_callback(subreq,
                                    smb2_transport_break_handler,
                                    transport);
            transport->break_subreq = subreq;
        }
    }

    if (req->session) {
        session = req->session->smbXcli;
    }

    if (transport->compound.related) {
        additional_flags |= SMB2_HDR_FLAG_CHAINED;
    }

    hdr_ofs = PTR_DIFF(req->out.hdr, req->out.buffer);
    pdu_len = req->out.size - hdr_ofs;
    body.data = req->out.body;
    body.length = req->out.body_fixed;
    dyn.data = req->out.body + req->out.body_fixed;
    dyn.length = pdu_len - (SMB2_HDR_BODY + req->out.body_fixed);

    req->subreq = smb2cli_req_create(req,
                                     transport->ev,
                                     transport->conn,
                                     cmd,
                                     additional_flags,
                                     clear_flags,
                                     timeout_msec,
                                     pid,
                                     tid,
                                     session,
                                     body.data, body.length,
                                     dyn.data, dyn.length);
    if (req->subreq == NULL) {
        req->state = SMB2_REQUEST_ERROR;
        req->status = NT_STATUS_NO_MEMORY;
        return;
    }

    if (!tevent_req_is_in_progress(req->subreq)) {
        req->state = SMB2_REQUEST_ERROR;
        req->status = NT_STATUS_INTERNAL_ERROR;/* TODO */
        return;
    }

    tevent_req_set_callback(req->subreq, smb2_request_done, req);

    smb2cli_req_set_notify_async(req->subreq);
    if (req->credit_charge) {
        smb2cli_req_set_credit_charge(req->subreq, req->credit_charge);
    }

    ZERO_STRUCT(req->out);
    req->state = SMB2_REQUEST_RECV;

    if (num_reqs > 0) {
        for (i=0; i < num_reqs; i++) {
            if (reqs[i] != NULL) {
                continue;
            }

            reqs[i] = req->subreq;
            i++;
            break;
        }

        if (i < num_reqs) {
            return;
        }
    } else {
        reqs = &req->subreq;
        num_reqs = 1;
    }
    status = smb2cli_req_compound_submit(reqs, num_reqs);

    TALLOC_FREE(transport->compound.reqs);

    if (!NT_STATUS_IS_OK(status)) {
        req->status = status;
        req->state = SMB2_REQUEST_ERROR;
        smbXcli_conn_disconnect(transport->conn, status);
    }
}