TODO s4:libcli/smb2: don't schedule idle handlers on a dead connection
[metze/samba/wip.git] / source4 / libcli / smb2 / transport.c
index a3845a60cbc255a3423e917a886e695fa5f733d4..b501b52ce51843e894c96f39cd8d1d61f4e7fd3d 100644 (file)
@@ -48,8 +48,6 @@ struct smb2_transport *smb2_transport_init(struct smbcli_socket *sock,
                                           struct smbcli_options *options)
 {
        struct smb2_transport *transport;
-       struct GUID client_guid;
-       uint32_t smb2_capabilities = 0;
 
        transport = talloc_zero(parent_ctx, struct smb2_transport);
        if (!transport) return NULL;
@@ -57,21 +55,24 @@ struct smb2_transport *smb2_transport_init(struct smbcli_socket *sock,
        transport->ev = sock->event.ctx;
        transport->options = *options;
 
-       TALLOC_FREE(sock->event.fde);
-       TALLOC_FREE(sock->event.te);
+       if (transport->options.max_protocol == PROTOCOL_DEFAULT) {
+               transport->options.max_protocol = PROTOCOL_LATEST;
+       }
 
-       client_guid = GUID_random();
+       if (transport->options.max_protocol < PROTOCOL_SMB2_02) {
+               transport->options.max_protocol = PROTOCOL_LATEST;
+       }
 
-       /* TODO: hand this in via the options? */
-       smb2_capabilities = SMB2_CAP_ALL;
+       TALLOC_FREE(sock->event.fde);
+       TALLOC_FREE(sock->event.te);
 
        transport->conn = smbXcli_conn_create(transport,
                                              sock->sock->fd,
                                              sock->hostname,
                                              options->signing,
                                              0, /* smb1_capabilities */
-                                             &client_guid,
-                                             smb2_capabilities);
+                                             &options->client_guid,
+                                             options->smb2_capabilities);
        if (transport->conn == NULL) {
                talloc_free(transport);
                return NULL;
@@ -115,8 +116,7 @@ void smb2_transport_send(struct smb2_request *req)
        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_tcon *tcon = NULL;
        struct smbXcli_session *session = NULL;
        bool need_pending_break = false;
        size_t hdr_ofs;
@@ -147,13 +147,13 @@ void smb2_transport_send(struct smb2_request *req)
                                            0, /* additional_flags */
                                            0, /*clear_flags */
                                            0, /* timeout_msec */
-                                           0, /* pid */
-                                           0, /* tid */
+                                           NULL, /* tcon */
                                            NULL, /* session */
                                            NULL, /* body */
                                            0, /* body_fixed */
                                            NULL, /* dyn */
-                                           0); /* dyn_len */
+                                           0, /* dyn_len */
+                                           0); /* max_dyn_len */
                if (subreq != NULL) {
                        smbXcli_req_set_pending(subreq);
                        tevent_req_set_callback(subreq,
@@ -167,6 +167,10 @@ void smb2_transport_send(struct smb2_request *req)
                session = req->session->smbXcli;
        }
 
+       if (req->tree) {
+               tcon = req->tree->smbXcli;
+       }
+
        if (transport->compound.related) {
                additional_flags |= SMB2_HDR_FLAG_CHAINED;
        }
@@ -185,11 +189,11 @@ void smb2_transport_send(struct smb2_request *req)
                                         additional_flags,
                                         clear_flags,
                                         timeout_msec,
-                                        pid,
-                                        tid,
+                                        tcon,
                                         session,
                                         body.data, body.length,
-                                        dyn.data, dyn.length);
+                                        dyn.data, dyn.length,
+                                        0); /* max_dyn_len */
        if (req->subreq == NULL) {
                req->state = SMB2_REQUEST_ERROR;
                req->status = NT_STATUS_NO_MEMORY;
@@ -233,6 +237,7 @@ void smb2_transport_send(struct smb2_request *req)
        status = smb2cli_req_compound_submit(reqs, num_reqs);
 
        TALLOC_FREE(transport->compound.reqs);
+       transport->compound.related = false;
 
        if (!NT_STATUS_IS_OK(status)) {
                req->status = status;
@@ -314,7 +319,6 @@ static void smb2_transport_break_handler(struct tevent_req *subreq)
                tevent_req_callback_data(subreq,
                struct smb2_transport);
        NTSTATUS status;
-       uint8_t *hdr;
        uint8_t *body;
        uint16_t len = 0;
        bool lease;
@@ -341,13 +345,13 @@ static void smb2_transport_break_handler(struct tevent_req *subreq)
                                    0, /* additional_flags */
                                    0, /*clear_flags */
                                    0, /* timeout_msec */
-                                   0, /* pid */
-                                   0, /* tid */
+                                   NULL, /* tcon */
                                    NULL, /* session */
                                    NULL, /* body */
                                    0, /* body_fixed */
                                    NULL, /* dyn */
-                                   0); /* dyn_len */
+                                   0, /* dyn_len */
+                                   0); /* max_dyn_len */
        if (subreq != NULL) {
                smbXcli_req_set_pending(subreq);
                tevent_req_set_callback(subreq,
@@ -356,7 +360,6 @@ static void smb2_transport_break_handler(struct tevent_req *subreq)
                transport->break_subreq = subreq;
        }
 
-       hdr = recv_iov[0].iov_base;
        body = recv_iov[1].iov_base;
 
        len = recv_iov[1].iov_len;
@@ -395,6 +398,7 @@ static void smb2_transport_break_handler(struct tevent_req *subreq)
                struct smb2_lease_break lb;
 
                ZERO_STRUCT(lb);
+               lb.new_epoch =                  SVAL(body, 0x2);
                lb.break_flags =                SVAL(body, 0x4);
                memcpy(&lb.current_lease.lease_key, body+0x8,
                    sizeof(struct smb2_lease_key));
@@ -452,6 +456,14 @@ static void idle_handler(struct tevent_context *ev,
 
        transport->idle.func(transport, transport->idle.private_data);
 
+       if (transport->idle.func == NULL) {
+               return;
+       }
+
+       if (!smbXcli_conn_is_connected(transport->conn)) {
+               return;
+       }
+
        next = timeval_current_ofs_usec(transport->idle.period);
        transport->idle.te = tevent_add_timer(transport->ev,
                                              transport,
@@ -470,6 +482,15 @@ void smb2_transport_idle_handler(struct smb2_transport *transport,
                                 void *private_data)
 {
        TALLOC_FREE(transport->idle.te);
+       ZERO_STRUCT(transport->idle);
+
+       if (idle_func == NULL) {
+               return;
+       }
+
+       if (!smbXcli_conn_is_connected(transport->conn)) {
+               return;
+       }
 
        transport->idle.func = idle_func;
        transport->idle.private_data = private_data;