static int smbXsrv_tcon_destructor(struct smbXsrv_tcon *tcon)
{
- struct smbXsrv_tcon_table *table;
- struct db_record *local_rec = NULL;
- struct db_record *global_rec = NULL;
NTSTATUS status;
- if (tcon->table == NULL) {
- return 0;
- }
-
- table = tcon->table;
- tcon->table = NULL;
-
- local_rec = tcon->db_rec;
- tcon->db_rec = NULL;
- if (local_rec == NULL) {
- uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE];
- TDB_DATA key;
-
- key = smbXsrv_tcon_local_id_to_key(tcon->local_id, key_buf);
-
- local_rec = dbwrap_fetch_locked(table->local.db_ctx,
- tcon, key);
- }
-
- if (local_rec != NULL) {
- status = dbwrap_record_delete(local_rec);
- }
-
- global_rec = tcon->global->db_rec;
- tcon->global->db_rec = NULL;
- if (global_rec == NULL) {
- uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE];
- TDB_DATA key;
-
- key = smbXsrv_tcon_global_id_to_key(
- tcon->global->tcon_global_id,
- key_buf);
-
- global_rec = dbwrap_fetch_locked(table->global.db_ctx,
- tcon->global, key);
+ status = smbXsrv_tcon_disconnect(tcon);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("smbXsrv_tcon_destructor: "
+ "smbXsrv_tcon_disconnect() failed - %s\n",
+ nt_errstr(status)));
}
- if (global_rec != NULL) {
- status = dbwrap_record_delete(global_rec);
- }
TALLOC_FREE(tcon->global);
return 0;
return NT_STATUS_OK;
}
+NTSTATUS smbXsrv_tcon_disconnect(struct smbXsrv_tcon *tcon)
+{
+ struct smbXsrv_tcon_table *table;
+ struct db_record *local_rec = NULL;
+ struct db_record *global_rec = NULL;
+ NTSTATUS status;
+ NTSTATUS error = NT_STATUS_OK;
+
+ if (tcon->table == NULL) {
+ return NT_STATUS_OK;
+ }
+
+ table = tcon->table;
+ tcon->table = NULL;
+
+ tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
+
+ global_rec = tcon->global->db_rec;
+ tcon->global->db_rec = NULL;
+ if (global_rec == NULL) {
+ uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE];
+ TDB_DATA key;
+
+ key = smbXsrv_tcon_global_id_to_key(
+ tcon->global->tcon_global_id,
+ key_buf);
+
+ global_rec = dbwrap_fetch_locked(table->global.db_ctx,
+ tcon->global, key);
+ if (global_rec == NULL) {
+ DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
+ "Failed to lock global key '%s'\n",
+ tcon->global->tcon_wire_id,
+ tcon->global->share_name,
+ hex_encode_talloc(global_rec, key.dptr,
+ key.dsize)));
+ error = NT_STATUS_INTERNAL_ERROR;
+ }
+ }
+
+ if (global_rec != NULL) {
+ status = dbwrap_record_delete(global_rec);
+ if (!NT_STATUS_IS_OK(status)) {
+ TDB_DATA key = dbwrap_record_get_key(global_rec);
+
+ DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
+ "failed to delete global key '%s': %s\n",
+ tcon->global->tcon_wire_id,
+ tcon->global->share_name,
+ hex_encode_talloc(global_rec, key.dptr,
+ key.dsize),
+ nt_errstr(status)));
+ error = status;
+ }
+ }
+ TALLOC_FREE(global_rec);
+
+ local_rec = tcon->db_rec;
+ if (local_rec == NULL) {
+ uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE];
+ TDB_DATA key;
+
+ key = smbXsrv_tcon_local_id_to_key(tcon->local_id, key_buf);
+
+ local_rec = dbwrap_fetch_locked(table->local.db_ctx,
+ tcon, key);
+ if (local_rec == NULL) {
+ DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
+ "Failed to lock local key '%s'\n",
+ tcon->global->tcon_wire_id,
+ tcon->global->share_name,
+ hex_encode_talloc(local_rec, key.dptr,
+ key.dsize)));
+ error = NT_STATUS_INTERNAL_ERROR;
+ }
+ }
+
+ if (local_rec != NULL) {
+ status = dbwrap_record_delete(local_rec);
+ if (!NT_STATUS_IS_OK(status)) {
+ TDB_DATA key = dbwrap_record_get_key(local_rec);
+
+ DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
+ "failed to delete local key '%s': %s\n",
+ tcon->global->tcon_wire_id,
+ tcon->global->share_name,
+ hex_encode_talloc(local_rec, key.dptr,
+ key.dsize),
+ nt_errstr(status)));
+ error = status;
+ }
+ }
+ if (tcon->db_rec == NULL) {
+ TALLOC_FREE(local_rec);
+ }
+ tcon->db_rec = NULL;
+
+ if (tcon->compat) {
+ bool ok;
+
+ ok = change_to_user(tcon->compat, tcon->compat->vuid);
+ if (!ok) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
+ "change_to_user() failed: %s\n",
+ tcon->global->tcon_wire_id,
+ tcon->global->share_name,
+ nt_errstr(status)));
+ tcon->compat = NULL;
+ return status;
+ }
+
+ ok = set_current_service(tcon->compat, 0, true);
+ if (!ok) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
+ "set_current_service() failed: %s\n",
+ tcon->global->tcon_wire_id,
+ tcon->global->share_name,
+ nt_errstr(status)));
+ tcon->compat = NULL;
+ return status;
+ }
+
+ close_cnum(tcon->compat, tcon->compat->vuid);
+ tcon->compat = NULL;
+ }
+
+ return error;
+}
+
+struct smbXsrv_tcon_disconnect_all_state {
+ NTSTATUS first_status;
+ int errors;
+};
+
+static int smbXsrv_tcon_disconnect_all_callback(struct db_record *local_rec,
+ void *private_data);
+
+static NTSTATUS smbXsrv_tcon_disconnect_all(struct smbXsrv_tcon_table *table)
+{
+ struct smbXsrv_tcon_disconnect_all_state state;
+ NTSTATUS status;
+ int count = 0;
+
+ ZERO_STRUCT(state);
+
+ if (table == NULL) {
+ return NT_STATUS_OK;
+ }
+
+ status = dbwrap_traverse(table->local.db_ctx,
+ smbXsrv_tcon_disconnect_all_callback,
+ &state, &count);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("smbXsrv_tcon_disconnect_all: "
+ "dbwrap_traverse() failed: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+
+ if (!NT_STATUS_IS_OK(state.first_status)) {
+ DEBUG(0, ("smbXsrv_tcon_disconnect_all: "
+ "count[%d] errors[%d] first[%s]\n",
+ count, state.errors,
+ nt_errstr(state.first_status)));
+ return state.first_status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static int smbXsrv_tcon_disconnect_all_callback(struct db_record *local_rec,
+ void *private_data)
+{
+ struct smbXsrv_tcon_disconnect_all_state *state =
+ (struct smbXsrv_tcon_disconnect_all_state *)private_data;
+ TDB_DATA val;
+ void *ptr = NULL;
+ struct smbXsrv_tcon *tcon = NULL;
+ NTSTATUS status;
+
+ val = dbwrap_record_get_value(local_rec);
+ if (val.dsize != sizeof(ptr)) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ if (NT_STATUS_IS_OK(state->first_status)) {
+ state->first_status = status;
+ }
+ state->errors++;
+ return 0;
+ }
+
+ memcpy(&ptr, val.dptr, val.dsize);
+ tcon = talloc_get_type_abort(ptr, struct smbXsrv_tcon);
+
+ tcon->db_rec = local_rec;
+ status = smbXsrv_tcon_disconnect(tcon);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_IS_OK(state->first_status)) {
+ state->first_status = status;
+ }
+ state->errors++;
+ return 0;
+ }
+
+ return 0;
+}
+
NTSTATUS smb1srv_tcon_table_init(struct smbXsrv_connection *conn)
{
/*
local_id, now, tcon);
}
+NTSTATUS smb1srv_tcon_disconnect_all(struct smbXsrv_connection *conn)
+{
+ return smbXsrv_tcon_disconnect_all(conn->tcon_table);
+}
+
NTSTATUS smb2srv_tcon_table_init(struct smbXsrv_session *session)
{
/*
return smbXsrv_tcon_local_lookup(session->tcon_table,
local_id, now, tcon);
}
+
+NTSTATUS smb2srv_tcon_disconnect_all(struct smbXsrv_session *session)
+{
+ return smbXsrv_tcon_disconnect_all(session->tcon_table);
+}