diff options
-rw-r--r-- | source3/smbd/globals.h | 3 | ||||
-rw-r--r-- | source3/smbd/smbXsrv_open.c | 77 |
2 files changed, 80 insertions, 0 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 3461bc50df..150275894b 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -462,6 +462,9 @@ NTSTATUS smbXsrv_open_global_traverse( int (*fn)(struct smbXsrv_open_global0 *, void *), void *private_data); +NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id); + + struct smbd_smb2_request { struct smbd_smb2_request *prev, *next; diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c index 97d6cd48eb..27dd50c65a 100644 --- a/source3/smbd/smbXsrv_open.c +++ b/source3/smbd/smbXsrv_open.c @@ -1372,3 +1372,80 @@ NTSTATUS smbXsrv_open_global_traverse( return status; } + +NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) +{ + NTSTATUS status; + TALLOC_CTX *frame = talloc_stackframe(); + struct smbXsrv_open_global0 *op = NULL; + uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; + TDB_DATA key; + struct db_record *rec; + bool delete_open = false; + uint32_t global_id = persistent_id & UINT32_MAX; + + key = smbXsrv_open_global_id_to_key(global_id, key_buf); + rec = dbwrap_fetch_locked(smbXsrv_open_global_db_ctx, frame, key); + if (rec == NULL) { + status = NT_STATUS_NOT_FOUND; + DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " + "failed to fetch record from %s - %s\n", + global_id, dbwrap_name(smbXsrv_open_global_db_ctx), + nt_errstr(status))); + goto done; + } + + status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &op); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " + "failed to read record: %s\n", + global_id, nt_errstr(status))); + goto done; + } + + if (server_id_is_disconnected(&op->server_id)) { + struct timeval now, disconnect_time; + int64_t tdiff; + now = timeval_current(); + nttime_to_timeval(&disconnect_time, op->disconnect_time); + tdiff = usec_time_diff(&now, &disconnect_time); + delete_open = (tdiff >= 1000*op->durable_timeout_msec); + + DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " + "disconnected at [%s] %us ago with " + "timeout of %us -%s reached\n", + global_id, + nt_time_string(frame, op->disconnect_time), + (unsigned)(tdiff/1000000), + op->durable_timeout_msec / 1000, + delete_open ? "" : " not")); + } else if (!serverid_exists(&op->server_id)) { + DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " + "server[%s] does not exist\n", + global_id, server_id_str(frame, &op->server_id))); + delete_open = true; + } + + if (!delete_open) { + goto done; + } + + status = dbwrap_record_delete(rec); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " + "failed to delete record" + "from %s: %s\n", global_id, + dbwrap_name(smbXsrv_open_global_db_ctx), + nt_errstr(status))); + goto done; + } + + DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " + "delete record from %s\n", + global_id, + dbwrap_name(smbXsrv_open_global_db_ctx))); + +done: + talloc_free(frame); + return status; +} |