/* sees what IOCTLs are supported */ bool torture_ioctl_test(struct torture_context *tctx, struct smbcli_state *cli) { uint16_t device, function; int fnum; const char *fname = "\\ioctl.dat"; NTSTATUS status; union smb_ioctl parms; TALLOC_CTX *mem_ctx; mem_ctx = talloc_named_const(tctx, 0, "ioctl_test"); smbcli_unlink(cli->tree, fname); fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); if (fnum == -1) { torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); return false; } parms.ioctl.level = RAW_IOCTL_IOCTL; parms.ioctl.in.file.fnum = fnum; parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO; status = smb_raw_ioctl(cli->tree, mem_ctx, &parms); torture_comment(tctx, "ioctl job info: %s\n", smbcli_errstr(cli->tree)); for (device=0;device<0x100;device++) { torture_comment(tctx, "testing device=0x%x\n", device); for (function=0;function<0x100;function++) { parms.ioctl.in.request = (device << 16) | function; status = smb_raw_ioctl(cli->tree, mem_ctx, &parms); if (NT_STATUS_IS_OK(status)) { torture_comment(tctx, "ioctl device=0x%x function=0x%x OK : %d bytes\n", device, function, (int)parms.ioctl.out.blob.length); } } } return true; }
/* get shadow volume data */ _PUBLIC_ NTSTATUS smb_raw_shadow_data(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, struct smb_shadow_copy *info) { union smb_ioctl nt; NTSTATUS status; DATA_BLOB blob; uint32_t dlength; int i; uint32_t ofs; nt.ntioctl.level = RAW_IOCTL_NTIOCTL; nt.ntioctl.in.function = FSCTL_GET_SHADOW_COPY_DATA; nt.ntioctl.in.file.fnum = info->in.file.fnum; nt.ntioctl.in.fsctl = True; nt.ntioctl.in.filter = 0; nt.ntioctl.in.max_data = info->in.max_data; nt.ntioctl.in.blob = data_blob(NULL, 0); status = smb_raw_ioctl(tree, mem_ctx, &nt); if (!NT_STATUS_IS_OK(status)) { return status; } blob = nt.ntioctl.out.blob; if (blob.length < 12) { return NT_STATUS_INVALID_NETWORK_RESPONSE; } info->out.num_volumes = IVAL(blob.data, 0); info->out.num_names = IVAL(blob.data, 4); dlength = IVAL(blob.data, 8); if (dlength > blob.length - 12) { return NT_STATUS_INVALID_NETWORK_RESPONSE; } info->out.names = talloc_array(mem_ctx, const char *, info->out.num_names); NT_STATUS_HAVE_NO_MEMORY(info->out.names); ofs = 12; for (i=0;i<info->out.num_names;i++) { size_t len; len = smbcli_blob_pull_ucs2(info->out.names, &blob, &info->out.names[i], blob.data+ofs, -1, STR_TERMINATE); if (len == 0) { return NT_STATUS_INVALID_NETWORK_RESPONSE; } ofs += len; } return status; }
/* ioctl interface */ static NTSTATUS cvfs_ioctl(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_ioctl *io) { struct cvfs_private *p = ntvfs->private_data; struct smbcli_request *c_req; SETUP_PID_AND_FILE; /* see if the front end will allow us to perform this function asynchronously. */ if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_ioctl(p->tree, req, io); } c_req = smb_raw_ioctl_send(p->tree, io); ASYNC_RECV_TAIL(io, async_ioctl); }