TODO - s4:smbd:smb2: add durable handle v2 support
authorMichael Adam <obnox@samba.org>
Fri, 2 Mar 2012 21:42:11 +0000 (22:42 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 10 May 2012 16:46:48 +0000 (18:46 +0200)
source3/smbd/smb2_create.c

index 17b8d80fd6db53a0163503347851499ac0fcceac..fd10cbe13865d7638b3b67dfd050b20dded59ee5 100644 (file)
@@ -725,7 +725,12 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                uint64_t allocation_size = 0;
                struct smb2_create_blob *twrp = NULL;
                struct smb2_create_blob *qfid = NULL;
+               struct smb2_create_blob *dh2q = NULL;
+               struct smb2_create_blob *dh2c = NULL;
                bool do_durable_reconnect = false;
+               bool persistent_requested = false;
+               bool persistent_granted = false;
+               uint32_t durable_v2_timeout = 0;
 
                exta = smb2_create_blob_find(&in_context_blobs,
                                             SMB2_CREATE_TAG_EXTA);
@@ -743,6 +748,10 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                                             SMB2_CREATE_TAG_TWRP);
                qfid = smb2_create_blob_find(&in_context_blobs,
                                             SMB2_CREATE_TAG_QFID);
+               dh2q = smb2_create_blob_find(&in_context_blobs,
+                                            SMB2_CREATE_TAG_DH2Q);
+               dh2c = smb2_create_blob_find(&in_context_blobs,
+                                            SMB2_CREATE_TAG_DH2C);
 
                fname = talloc_strdup(state, in_name);
                if (tevent_req_nomem(fname, req)) {
@@ -814,11 +823,38 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
                                return tevent_req_post(req, ev);
                        }
+
+
                        /*
                         * durable handle request is processed below.
                         */
                }
 
+               if (dh2q) {
+                       uint32_t dh2q_flags;
+
+                       if (dh2q->data.length != 32) {
+                               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                               return tevent_req_post(req, ev);
+                       }
+
+                       /* TODO - sanity checks - other blobs */
+
+                       /*
+                        * durable handle v2 request processed below
+                        */
+
+                       durable_v2_timeout = SVAL(dh2q->data.data, 0);
+                       dh2q_flags = SVAL(dh2q->data.data, 4);
+                       persistent_requested = dh2q_flags & SMB2_DHANDLE_FLAG_PERSISTENT;
+
+                       persistent_granted = persistent_requested;
+
+                       /*
+                        * TODO: extract create guid
+                        */
+               }
+
                if (dhnc) {
                        uint64_t persistent_id;
 
@@ -851,6 +887,46 @@ DEBUG(0, ("OBNOX - dhnc found (%s:%s)\n", __location__, __FUNCTION__));
                        do_durable_reconnect = true;
                }
 
+               if (dh2c) {
+                       uint64_t persistent_id;
+                       uint32_t dh2c_flags;
+
+DEBUG(0, ("OBNOX - dh2c found (%s:%s)\n", __location__, __FUNCTION__));
+
+                       if (dh2c->data.length != 36) {
+                               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                               return tevent_req_post(req, ev);
+                       }
+
+                       persistent_id = BVAL(dh2c->data.data, 0);
+                       /*
+                        * TODO: extract and check create guid
+                        */
+                       dh2c_flags = SVAL(dh2c->data.data, 32);
+                       persistent_requested = dh2c_flags & SMB2_DHANDLE_FLAG_PERSISTENT;
+
+                       status = smb2srv_open_recreate(smb2req->sconn->conn,
+                                                      persistent_id,
+                                                      &op);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               tevent_req_nterror(req, status);
+                               return tevent_req_post(req, ev);
+                       }
+
+                       if (!op->global->durable) {
+                               talloc_free(op);
+                               tevent_req_nterror(req,
+                                       NT_STATUS_OBJECT_NAME_NOT_FOUND);
+                               return tevent_req_post(req, ev);
+                       }
+
+                       if (persistent_requested && op->global->persistent) {
+                               persistent_granted = true;
+                       }
+
+                       do_durable_reconnect = true;
+               }
+
                if (alsi) {
                        if (dhnc) {
                                tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
@@ -1047,6 +1123,41 @@ DEBUG(0, ("OBNOX - constructing a dhnq response blob (%s: %s)\n", __location__,
                        }
                }
 
+               if (dh2c || (dh2q && BATCH_OPLOCK_TYPE(result->oplock_type))) {
+                       uint8_t p[8];
+                       DATA_BLOB blob = data_blob_const(p, sizeof(p));
+                       uint32_t durable_v2_response_flags = 0;
+
+DEBUG(0, ("OBNOX - constructing a dh2q response blob (%s: %s)\n", __location__, __FUNCTION__));
+
+                       if (persistent_granted) {
+                               durable_v2_response_flags |= SMB2_DHANDLE_FLAG_PERSISTENT;
+                       }
+
+                       SIVAL(p, 0, durable_v2_timeout);
+                       SIVAL(p, 4, durable_v2_response_flags);
+
+                       result->smbXsrv->global->backend_file_id = result->file_id;
+                       result->smbXsrv->global->durable = true;
+                       result->smbXsrv->global->persistent = persistent_granted;
+
+                       status = smbXsrv_open_update(result->smbXsrv);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               tevent_req_nterror(req, status);
+                               return tevent_req_post(req, ev);
+                       }
+
+                       ZERO_STRUCT(p);
+
+                       status = smb2_create_blob_add(state, &out_context_blobs,
+                                                     SMB2_CREATE_TAG_DH2Q,
+                                                     blob);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               tevent_req_nterror(req, status);
+                               return tevent_req_post(req, ev);
+                       }
+               }
+
                if (qfid) {
                        uint8_t p[32];
                        uint64_t file_index = get_FileIndex(result->conn,