📄 gentest.c
字号:
printf("oplock close fnum=%d\n", fnum); io.close.level = RAW_CLOSE_CLOSE; io.close.in.file.fnum = fnum; io.close.in.write_time = 0; req = smb_raw_close_send(tree, &io); if (req == NULL) { printf("WARNING: close failed in oplock_handler_close\n"); return false; } req->async.fn = oplock_handler_close_recv_smb; req->async.private = NULL; return true;}/* the idle function tries to cope with getting an oplock break on a connection, and an operation on another connection blocking until that break is acked we check for operations on all transports in the idle function*/static void idle_func_smb(struct smbcli_transport *transport, void *private){ int i, j; for (i=0;i<NSERVERS;i++) { for (j=0;j<NINSTANCES;j++) { if (servers[i].smb_tree[j] && transport != servers[i].smb_tree[j]->session->transport) { smbcli_transport_process(servers[i].smb_tree[j]->session->transport); } } }}static void oplock_handler_close_recv_smb2(struct smb2_request *req){ NTSTATUS status; struct smb2_close io; status = smb2_close_recv(req, &io); if (!NT_STATUS_IS_OK(status)) { printf("close failed in oplock_handler\n"); smb_panic("close failed in oplock_handler"); }}static void oplock_handler_ack_callback_smb2(struct smb2_request *req){ NTSTATUS status; struct smb2_break br; status = smb2_break_recv(req, &br); if (!NT_STATUS_IS_OK(status)) { printf("oplock break ack failed in oplock_handler\n"); smb_panic("oplock break ack failed in oplock_handler"); }}static bool send_oplock_ack_smb2(struct smb2_tree *tree, struct smb2_handle handle, uint8_t level){ struct smb2_break br; struct smb2_request *req; ZERO_STRUCT(br); br.in.file.handle = handle; br.in.oplock_level = level; br.in.reserved = gen_reserved8(); br.in.reserved2 = gen_reserved32(); req = smb2_break_send(tree, &br); if (req == NULL) return false; req->async.fn = oplock_handler_ack_callback_smb2; req->async.private_data = NULL; return true;}/* the oplock handler will either ack the break or close the file*/static bool oplock_handler_smb2(struct smb2_transport *transport, const struct smb2_handle *handle, uint8_t level, void *private_data){ struct smb2_close io; unsigned i, j; bool do_close; struct smb2_tree *tree = NULL; struct smb2_request *req; srandom(current_op.seed); do_close = gen_chance(50); i = ((uintptr_t)private_data) >> 8; j = ((uintptr_t)private_data) & 0xFF; if (i >= NSERVERS || j >= NINSTANCES) { printf("Bad private_data in oplock_handler\n"); return false; } oplocks[i][j].got_break = true; oplocks[i][j].smb2_handle = *handle; oplocks[i][j].handle = fnum_to_handle_smb2(i, j, *handle); oplocks[i][j].level = level; oplocks[i][j].do_close = do_close; tree = talloc_get_type(servers[i].smb2_tree[j], struct smb2_tree); if (!tree) { printf("Oplock break not for one of our trees!?\n"); return false; } if (!do_close) { printf("oplock ack handle=%d\n", oplocks[i][j].handle); return send_oplock_ack_smb2(tree, *handle, level); } printf("oplock close fnum=%d\n", oplocks[i][j].handle); ZERO_STRUCT(io); io.in.file.handle = *handle; io.in.flags = 0; req = smb2_close_send(tree, &io); if (req == NULL) { printf("WARNING: close failed in oplock_handler_close\n"); return false; } req->async.fn = oplock_handler_close_recv_smb2; req->async.private_data = NULL; return true;}/* the idle function tries to cope with getting an oplock break on a connection, and an operation on another connection blocking until that break is acked we check for operations on all transports in the idle function*/static void idle_func_smb2(struct smb2_transport *transport, void *private){ int i, j; for (i=0;i<NSERVERS;i++) { for (j=0;j<NINSTANCES;j++) { if (servers[i].smb2_tree[j] && transport != servers[i].smb2_tree[j]->session->transport) { // smb2_transport_process(servers[i].smb2_tree[j]->session->transport); } } }}/* compare NTSTATUS, using checking ignored patterns*/static bool compare_status(NTSTATUS status1, NTSTATUS status2){ if (NT_STATUS_EQUAL(status1, status2)) return true; /* one code being an error and the other OK is always an error */ if (NT_STATUS_IS_OK(status1) || NT_STATUS_IS_OK(status2)) { current_op.mismatch = nt_errstr(status1); return false; } /* if we are ignoring one of the status codes then consider this a match */ if (ignore_pattern(nt_errstr(status1)) || ignore_pattern(nt_errstr(status2))) { return true; } current_op.mismatch = nt_errstr(status1); return false;}/* check for pending packets on all connections*/static void check_pending(void){ int i, j; msleep(20); for (j=0;j<NINSTANCES;j++) { for (i=0;i<NSERVERS;i++) { // smb2_transport_process(servers[i].smb2_tree[j]->session->transport); } } }/* check that the same oplock breaks have been received by all instances*/static bool check_oplocks(const char *call){ int i, j; int tries = 0; if (!options.use_oplocks || options.smb2) { /* no smb2 oplocks in gentest yet */ return true; }again: check_pending(); for (j=0;j<NINSTANCES;j++) { for (i=1;i<NSERVERS;i++) { if (oplocks[0][j].got_break != oplocks[i][j].got_break || oplocks[0][j].handle != oplocks[i][j].handle || oplocks[0][j].level != oplocks[i][j].level) { if (tries++ < 10) goto again; printf("oplock break inconsistent - %d/%d/%d vs %d/%d/%d\n", oplocks[0][j].got_break, oplocks[0][j].handle, oplocks[0][j].level, oplocks[i][j].got_break, oplocks[i][j].handle, oplocks[i][j].level); current_op.mismatch = "oplock break"; return false; } } } /* if we got a break and closed then remove the handle */ for (j=0;j<NINSTANCES;j++) { if (oplocks[0][j].got_break && oplocks[0][j].do_close) { uint16_t fnums[NSERVERS]; for (i=0;i<NSERVERS;i++) { fnums[i] = oplocks[i][j].smb_handle; } gen_remove_handle_smb(j, fnums); break; } } return true;}/* check that the same change notify info has been received by all instances*/static bool check_notifies(const char *call){ int i, j; int tries = 0; if (options.smb2) { /* no smb2 notifies in gentest yet */ return true; }again: check_pending(); for (j=0;j<NINSTANCES;j++) { for (i=1;i<NSERVERS;i++) { int n; union smb_notify not1, not2; if (notifies[0][j].notify_count != notifies[i][j].notify_count) { if (tries++ < 10) goto again; printf("Notify count inconsistent %d %d\n", notifies[0][j].notify_count, notifies[i][j].notify_count); current_op.mismatch = "notify count"; return false; } if (notifies[0][j].notify_count == 0) continue; if (!NT_STATUS_EQUAL(notifies[0][j].status, notifies[i][j].status)) { printf("Notify status mismatch - %s - %s\n", nt_errstr(notifies[0][j].status), nt_errstr(notifies[i][j].status)); current_op.mismatch = "Notify status"; return false; } if (!NT_STATUS_IS_OK(notifies[0][j].status)) { continue; } not1 = notifies[0][j].notify; not2 = notifies[i][j].notify; for (n=0;n<not1.nttrans.out.num_changes;n++) { if (not1.nttrans.out.changes[n].action != not2.nttrans.out.changes[n].action) { printf("Notify action %d inconsistent %d %d\n", n, not1.nttrans.out.changes[n].action, not2.nttrans.out.changes[n].action); current_op.mismatch = "notify action"; return false; } if (strcmp(not1.nttrans.out.changes[n].name.s, not2.nttrans.out.changes[n].name.s)) { printf("Notify name %d inconsistent %s %s\n", n, not1.nttrans.out.changes[n].name.s, not2.nttrans.out.changes[n].name.s); current_op.mismatch = "notify name"; return false; } if (not1.nttrans.out.changes[n].name.private_length != not2.nttrans.out.changes[n].name.private_length) { printf("Notify name length %d inconsistent %d %d\n", n, not1.nttrans.out.changes[n].name.private_length, not2.nttrans.out.changes[n].name.private_length); current_op.mismatch = "notify name length"; return false; } } } } ZERO_STRUCT(notifies); return true;}#define GEN_COPY_PARM do { \ int i; \ for (i=1;i<NSERVERS;i++) { \ parm[i] = parm[0]; \ } \} while (0)#define GEN_CALL(call, treetype, treefield) do { \ int i; \ ZERO_STRUCT(oplocks); \ ZERO_STRUCT(notifies); \ for (i=0;i<NSERVERS;i++) { \ struct treetype *tree = servers[i].treefield[instance]; \ status[i] = call; \ } \ current_op.status = status[0]; \ for (i=1;i<NSERVERS;i++) { \ if (!compare_status(status[i], status[0])) { \ printf("status different in %s - %s %s\n", #call, \ nt_errstr(status[0]), nt_errstr(status[i])); \ current_op.mismatch = nt_errstr(status[0]); \ return false; \ } \ } \ if (!check_oplocks(#call)) return false; \ if (!check_notifies(#call)) return false; \ if (!NT_STATUS_IS_OK(status[0])) { \ return true; \ } \} while(0)#define GEN_CALL_SMB(call) GEN_CALL(call, smbcli_tree, smb_tree)#define GEN_CALL_SMB2(call) GEN_CALL(call, smb2_tree, smb2_tree)#define ADD_HANDLE_SMB2(name, field) do { \ struct smb2_handle handles[NSERVERS]; \ int i; \ for (i=0;i<NSERVERS;i++) { \ handles[i] = parm[i].field; \ } \ gen_add_handle_smb2(instance, name, handles); \} while(0)#define REMOVE_HANDLE_SMB2(field) do { \ struct smb2_handle handles[NSERVERS]; \ int i; \ for (i=0;i<NSERVERS;i++) { \ handles[i] = parm[i].field; \ } \ gen_remove_handle_smb2(instance, handles); \} while(0)#define ADD_HANDLE_SMB(name, field) do { \ uint16_t handles[NSERVERS]; \ int i; \ for (i=0;i<NSERVERS;i++) { \ handles[i] = parm[i].field; \ } \ gen_add_handle_smb(instance, name, handles); \} while(0)#define REMOVE_HANDLE_SMB(field) do { \ uint16_t handles[NSERVERS]; \ int i; \ for (i=0;i<NSERVERS;i++) { \ handles[i] = parm[i].field; \ } \ gen_remove_handle_smb(instance, handles); \} while(0)#define GEN_SET_FNUM_SMB2(field) do { \ int i; \ for (i=0;i<NSERVERS;i++) { \ parm[i].field = gen_lookup_handle_smb2(i, parm[i].field.data[0]); \ } \} while(0)#define GEN_SET_FNUM_SMB(field) do { \ int i; \ for (i=0;i<NSERVERS;i++) { \ parm[i].field = gen_lookup_handle_smb(i, parm[i].field); \ } \} while(0)#define CHECK_EQUAL(field) do { \ if (parm[0].field != parm[1].field && !ignore_pattern(#field)) { \ current_op.mismatch = #field; \ printf("Mismatch in %s - 0x%llx 0x%llx\n", #field, \ (unsigned long long)parm[0].field, (unsigned long long)parm[1].field); \ return false; \ } \} while(0)#define CHECK_SECDESC(field) do { \ if (!security_acl_equal(parm[0].field->dacl, parm[1].field->dacl) && !ignore_pattern(#field)) { \ current_op.mismatch = #field; \ printf("Mismatch in %s\n", #field); \ return false; \ } \} while(0)#define CHECK_ATTRIB(field) do { \ if (!options.mask_indexing) { \ CHECK_EQUAL(field); \ } else if ((~FILE_ATTRIBUTE_NONINDEXED & parm[0].field) != (~FILE_ATTRIBUTE_NONINDEXED & parm[1].field) && !ignore_pattern(#field)) { \ current_op.mismatch = #field; \ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \ (int)parm[0].field, (int)parm[1].field); \ return false; \ } \} while(0)#define CHECK_WSTR_EQUAL(field) do { \ if ((!parm[0].field.s && parm[1].field.s) || (parm[0].field.s && !parm[1].field.s)) { \ current_op.mismatch = #field; \ printf("%s is NULL!\n", #field); \ return false; \ } \ if (parm[0].field.s && strcmp(parm[0].field.s, parm[1].field.s) != 0 && !ignore_pattern(#field)) { \ current_op.mismatch = #field; \ printf("Mismatch in %s - %s %s\n", #field, \ parm[0].field.s, parm[1].field.s); \ return false; \ } \ CHECK_EQUAL(field.private_length); \} while(0)#define CHECK_BLOB_EQUAL(field) do { \ if (memcmp(parm[0].field.data, parm[1].field.data, parm[0].field.length) != 0 && !ignore_pattern(#field)) { \ current_op.mismatch = #field; \ printf("Mismatch in %s\n", #field); \ return false; \ } \ CHECK_EQUAL(field.length); \} while(0)#define CHECK_TIMES_EQUAL(field) do { \ if (labs(parm[0].field - parm[1].field) > time_skew() && \ !ignore_pattern(#field)) { \ current_op.mismatch = #field; \ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \ (int)parm[0].field, (int)parm[1].field); \ return false; \ } \} while(0)#define CHECK_NTTIMES_EQUAL(field) do { \ if (labs(nt_time_to_unix(parm[0].field) - \ nt_time_to_unix(parm[1].field)) > time_skew() && \ !ignore_pattern(#field)) { \ current_op.mismatch = #field; \ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \ (int)nt_time_to_unix(parm[0].field), \ (int)nt_time_to_unix(parm[1].field)); \ return false; \ } \} while(0)/* compare returned fileinfo structures*/static bool cmp_fileinfo(int instance, union smb_fileinfo parm[NSERVERS], NTSTATUS status[NSERVERS]){ int i; enum smb_fileinfo_level level = parm[0].generic.level; if (level == RAW_FILEINFO_ALL_INFORMATION &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -