/* scan for valid base SMB requests */ bool torture_smb_scan(struct torture_context *torture) { static struct smbcli_state *cli; int op; struct smbcli_request *req; NTSTATUS status; for (op=0x0;op<=0xFF;op++) { if (op == SMBreadbraw) continue; if (!torture_open_connection(&cli, torture, 0)) { return false; } req = smbcli_request_setup(cli->tree, op, 0, 0); if (!smbcli_request_send(req)) { smbcli_request_destroy(req); break; } usleep(10000); smbcli_transport_process(cli->transport); if (req->state > SMBCLI_REQUEST_RECV) { status = smbcli_request_simple_recv(req); printf("op=0x%x status=%s\n", op, nt_errstr(status)); torture_close_connection(cli); continue; } sleep(1); smbcli_transport_process(cli->transport); if (req->state > SMBCLI_REQUEST_RECV) { status = smbcli_request_simple_recv(req); printf("op=0x%x status=%s\n", op, nt_errstr(status)); } else { printf("op=0x%x no reply\n", op); smbcli_request_destroy(req); continue; /* don't attempt close! */ } torture_close_connection(cli); } printf("smb scan finished\n"); return true; }
static void receive_lock_result(struct smbcli_request *req) { struct lock_result_state *state = (struct lock_result_state *)req->async.private_data; state->status = smbcli_request_simple_recv(req); state->done = true; }
/* a handler for simple async replies this handler can only be used for functions that don't return any parameters (those that just return a status code) */ static void async_simple(struct smbcli_request *c_req) { struct async_info *async = c_req->async.private_data; struct ntvfs_request *req = async->req; req->async_states->status = smbcli_request_simple_recv(c_req); talloc_free(async); req->async_states->send_fn(req); }
static void echo_completion(struct smbcli_request *req) { struct offline_state *state = (struct offline_state *)req->async.private_data; NTSTATUS status = smbcli_request_simple_recv(req); if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) || NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT)) { talloc_free(state->tree); state->tree = NULL; num_connected--; DEBUG(0,("lost connection\n")); test_failed++; } }
static void echo_completion(struct smbcli_request *req) { struct benchlock_state *state = (struct benchlock_state *)req->async.private_data; NTSTATUS status = smbcli_request_simple_recv(req); if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) || NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT) || NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) { talloc_free(state->tree); state->tree = NULL; num_connected--; DEBUG(0,("reopening connection to %s\n", state->dest_host)); talloc_free(state->te); state->te = event_add_timed(state->ev, state->mem_ctx, timeval_current_ofs(1,0), reopen_connection, state); } }
/* called when a setoffline completes */ static void setoffline_callback(struct smbcli_request *req) { struct offline_state *state = req->async.private_data; NTSTATUS status; status = smbcli_request_simple_recv(req); if (!NT_STATUS_IS_OK(status)) { printf("Failed to set offline file '%s' - %s\n", state->fname, nt_errstr(status)); test_failed++; } state->req = NULL; state->count++; if (!test_finished) { test_offline(state); } }
/* called when a lock completes */ static void lock_completion(struct smbcli_request *req) { struct benchlock_state *state = (struct benchlock_state *)req->async.private_data; NTSTATUS status = smbcli_request_simple_recv(req); state->req = NULL; if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) || NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT) || NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) { talloc_free(state->tree); state->tree = NULL; num_connected--; DEBUG(0,("reopening connection to %s\n", state->dest_host)); talloc_free(state->te); state->te = event_add_timed(state->ev, state->mem_ctx, timeval_current_ofs(1,0), reopen_connection, state); } else { DEBUG(0,("Lock failed - %s\n", nt_errstr(status))); lock_failed++; } return; } switch (state->stage) { case LOCK_INITIAL: state->stage = LOCK_LOCK; break; case LOCK_LOCK: state->stage = LOCK_UNLOCK; break; case LOCK_UNLOCK: state->stage = LOCK_LOCK; break; } state->count++; lock_send(state); }
static void async_close_recv(struct smbcli_request *req) { struct async_context *c = req->async.private; NTSTATUS status; status = smbcli_request_simple_recv(req); talloc_free(c->io_close); c->io_close = 0; if (c->io_open) { talloc_free(c->io_open); c->io_open = 0; } if (c->io_read) { talloc_free(c->io_read); c->io_read = 0; } if (c->io_write) { talloc_free(c->io_write); c->io_write = 0; } if (c->cb_close) c->cb_close(c->cb_ctx); }
/* called when a close completes */ static void close_completed(struct smbcli_request *req) { struct benchopen_state *state = (struct benchopen_state *)req->async.private_data; NTSTATUS status = smbcli_request_simple_recv(req); state->req_close = NULL; if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) || NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT) || NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) { talloc_free(state->tree); talloc_free(state->cli); state->tree = NULL; state->cli = NULL; num_connected--; DEBUG(0,("[%u] reopening connection to %s\n", state->client_num, state->dest_host)); talloc_free(state->te); state->te = event_add_timed(state->ev, state->mem_ctx, timeval_current_ofs(1,0), reopen_connection, state); return; } if (!NT_STATUS_IS_OK(status)) { close_failed++; DEBUG(0,("[%u] close failed %d (fnum[%d]) - %s\n", state->client_num, state->close_file_num, state->close_fnum, nt_errstr(status))); return; } DEBUG(2,("[%d] close completed %d (fnum[%d])\n", state->client_num, state->close_file_num, state->close_fnum)); }
/**************************************************************************** Send a exit (sync interface) *****************************************************************************/ _PUBLIC_ NTSTATUS smb_raw_exit(struct smbcli_session *session) { struct smbcli_request *req = smb_raw_exit_send(session); return smbcli_request_simple_recv(req); }
/**************************************************************************** Send a ulogoff (sync interface) *****************************************************************************/ NTSTATUS smb_raw_ulogoff(struct smbcli_session *session) { struct smbcli_request *req = smb_raw_ulogoff_send(session); return smbcli_request_simple_recv(req); }
/* test a lock that conflicts with an existing lock */ static bool test_mux_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { union smb_lock io; NTSTATUS status; int fnum; bool ret = true; struct smbcli_request *req; struct smb_lock_entry lock[1]; struct timeval t; printf("TESTING MULTIPLEXED LOCK/LOCK/UNLOCK\n"); fnum = smbcli_open(cli->tree, BASEDIR "\\write.dat", O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { printf("open failed in mux_write - %s\n", smbcli_errstr(cli->tree)); ret = false; goto done; } printf("establishing a lock\n"); io.lockx.level = RAW_LOCK_LOCKX; io.lockx.in.file.fnum = fnum; io.lockx.in.mode = 0; io.lockx.in.timeout = 0; io.lockx.in.lock_cnt = 1; io.lockx.in.ulock_cnt = 0; lock[0].pid = 1; lock[0].offset = 0; lock[0].count = 4; io.lockx.in.locks = &lock[0]; status = smb_raw_lock(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); printf("the second lock will conflict with the first\n"); lock[0].pid = 2; io.lockx.in.timeout = 1000; status = smb_raw_lock(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); printf("this will too, but we'll unlock while waiting\n"); t = timeval_current(); req = smb_raw_lock_send(cli->tree, &io); printf("unlock the first range\n"); lock[0].pid = 1; io.lockx.in.ulock_cnt = 1; io.lockx.in.lock_cnt = 0; io.lockx.in.timeout = 0; status = smb_raw_lock(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); printf("recv the async reply\n"); status = smbcli_request_simple_recv(req); CHECK_STATUS(status, NT_STATUS_OK); printf("async lock took %.2f msec\n", timeval_elapsed(&t) * 1000); if (timeval_elapsed(&t) > 0.1) { printf("failed to trigger early lock retry\n"); return false; } printf("reopening with an exit\n"); smb_raw_exit(cli->session); fnum = smbcli_open(cli->tree, BASEDIR "\\write.dat", O_RDWR | O_CREAT, DENY_NONE); printf("Now trying with a cancel\n"); io.lockx.level = RAW_LOCK_LOCKX; io.lockx.in.file.fnum = fnum; io.lockx.in.mode = 0; io.lockx.in.timeout = 0; io.lockx.in.lock_cnt = 1; io.lockx.in.ulock_cnt = 0; lock[0].pid = 1; lock[0].offset = 0; lock[0].count = 4; io.lockx.in.locks = &lock[0]; status = smb_raw_lock(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); lock[0].pid = 2; io.lockx.in.timeout = 1000; status = smb_raw_lock(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); req = smb_raw_lock_send(cli->tree, &io); /* cancel the blocking lock */ smb_raw_ntcancel(req); printf("sending 2nd cancel\n"); /* the 2nd cancel is totally harmless, but tests the server trying to cancel an already cancelled request */ smb_raw_ntcancel(req); printf("sent 2nd cancel\n"); lock[0].pid = 1; io.lockx.in.ulock_cnt = 1; io.lockx.in.lock_cnt = 0; io.lockx.in.timeout = 0; status = smb_raw_lock(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); status = smbcli_request_simple_recv(req); CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); printf("cancel a lock using exit to close file\n"); lock[0].pid = 1; io.lockx.in.ulock_cnt = 0; io.lockx.in.lock_cnt = 1; io.lockx.in.timeout = 1000; status = smb_raw_lock(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); t = timeval_current(); lock[0].pid = 2; req = smb_raw_lock_send(cli->tree, &io); smb_raw_exit(cli->session); smb_raw_exit(cli->session); smb_raw_exit(cli->session); smb_raw_exit(cli->session); printf("recv the async reply\n"); status = smbcli_request_simple_recv(req); CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); printf("async lock exit took %.2f msec\n", timeval_elapsed(&t) * 1000); if (timeval_elapsed(&t) > 0.1) { printf("failed to trigger early lock failure\n"); return false; } done: return ret; }
/**************************************************************************** Send a echo (sync interface) *****************************************************************************/ NTSTATUS smb_raw_echo(struct smbcli_transport *transport, struct smb_echo *p) { struct smbcli_request *req = smb_raw_echo_send(transport, p); return smbcli_request_simple_recv(req); }
/**************************************************************************** Rename a file - sync interface ****************************************************************************/ _PUBLIC_ NTSTATUS smb_raw_rename(struct smbcli_tree *tree, union smb_rename *parms) { struct smbcli_request *req = smb_raw_rename_send(tree, parms); return smbcli_request_simple_recv(req); }
/**************************************************************************** Remove a directory - sync interface ****************************************************************************/ _PUBLIC_ NTSTATUS smb_raw_rmdir(struct smbcli_tree *tree, struct smb_rmdir *parms) { struct smbcli_request *req = smb_raw_rmdir_send(tree, parms); return smbcli_request_simple_recv(req); }