Document probing samples

This commit is contained in:
Lucian Petrut
2026-09-08 14:41:24 +00:00
parent f70a1d485e
commit 14ed40548e
7 changed files with 853 additions and 1 deletions
+135
View File
@@ -0,0 +1,135 @@
#!/usr/bin/env python3
"""Probe NFC write open-flags / opcode. Not part of the library."""
from __future__ import annotations
import os
import struct
import sys
import unittest
sys.path.insert(0, "/home/ubuntu/workspace/vmware_nbd_tests")
os.environ.pop("LD_PRELOAD", None)
from openvixdisklib import nfc_open
from tests.integration.base import TestBase
NFC_AIO_MSG_ERROR = 1
NFC_AIO_MSG_IO = 7
def recvn(sock, size):
buf = bytearray()
while len(buf) < size:
chunk = sock.recv(size - len(buf))
if not chunk:
raise RuntimeError(f"closed, got {len(buf)}/{size}")
buf.extend(chunk)
return bytes(buf)
def open_rw(session, disk_path, oflag):
sock = nfc_open.takeover_authd_socket(session.authd_sock)
nfc_open._handshake(sock, "vddk", "nbdmode", nfc_open.NFC_PROTOCOL_VERSION)
disk = nfc_open.NfcDisk(
sock, disk_path, handle=0, sector_size=nfc_open.NFC_SECTOR_SIZE)
nfc_open._aio_prepare(disk)
path_b = disk_path.encode("utf-8")
open_body = struct.pack(
"<IIIIII", len(path_b), 0, 0, 0, nfc_open.NFC_DISK, oflag)
open_body = open_body.ljust(60, b"\x00")
reply = disk._aio_roundtrip(
nfc_open.NFC_AIO_MSG_OPEN_FILE, open_body, extra=path_b)
handle, sector_size = nfc_open._parse_open_reply(reply)
disk.handle = handle
disk.sector_size = sector_size
echoed = struct.unpack_from("<I", reply, 20)[0]
print(f"OPEN sent=0x{oflag:x} echoed=0x{echoed:x} handle={handle}")
return disk
def try_io(disk, opcode, flags_field, data, send_extra=True):
length = len(data)
payload = struct.pack(
"<QQQQIII",
disk.handle, opcode, 0, length, length, length, flags_field)
op_id = disk._next_op_id()
disk._sock.sendall(
nfc_open._pack_aio_hdr(NFC_AIO_MSG_IO, len(payload), op_id) + payload)
if send_extra:
disk._sock.sendall(data)
rhdr = recvn(disk._sock, 16)
magic, rtype, rsize, rop = struct.unpack_from("<IIII", rhdr)
body = recvn(disk._sock, rsize) if rsize else b""
extra = b""
if rtype == NFC_AIO_MSG_IO and rsize >= 36:
chunk_len = struct.unpack_from("<I", body, 32)[0]
if 0 < chunk_len <= 65536:
extra = recvn(disk._sock, chunk_len)
return rtype, rsize, body, extra
class Probe(TestBase):
def test_probe(self):
data = self.pattern_bytes(self.SECTOR_SIZE, b"PROBE-S0")
open_flags = [
0x1C, 0x00, 0x1F, 0x0E, 0x0C, 0x04, 0x06, 0x02,
0x3E, 0x5E, 0x16, 0x1A, 0x1D, 0x0A, 0x08, 0x20,
0x3C, 0x7E, 0xFE, 0x100, 0x1E, 0x0F, 0x18,
]
# First: opcode 2 (guessed write) across open flags
for oflag in open_flags:
with self.authenticate() as session:
try:
disk = open_rw(session, self.DISK_PATH, oflag)
except Exception as exc:
print(f"OPEN FAIL 0x{oflag:x} {exc}")
continue
rtype, rsize, body, extra = try_io(disk, 2, 0, data)
print(
f" IO op=2 flags=0x{oflag:x} rtype={rtype} "
f"extra={len(extra)} body={body.hex()}")
if rtype == NFC_AIO_MSG_IO:
got = disk.read(0, 1)
print(f" readback match={got==data} {got[:16]!r}")
if got == data:
print("SUCCESS opcode=2")
disk.close()
return
try:
disk.close()
except Exception:
disk._sock.close()
# Then: opcode 1 with ioflags as write bit, open 0x1C and 0x00
for oflag in (0x1C, 0x00, 0x0E):
for opcode, ioflags, send_extra in (
(1, 1, True), (1, 2, True), (2, 1, True),
(4, 0, True), (5, 0, True), (8, 0, True),
(2, 0, True)):
with self.authenticate() as session:
disk = open_rw(session, self.DISK_PATH, oflag)
rtype, rsize, body, extra = try_io(
disk, opcode, ioflags, data, send_extra)
print(
f" IO op={opcode} iofl={ioflags} of=0x{oflag:x} "
f"rtype={rtype} extra={len(extra)} body={body[:16].hex()}")
if rtype == NFC_AIO_MSG_IO:
try:
got = disk.read(0, 1)
print(f" readback match={got==data} {got[:16]!r}")
if got == data:
print("SUCCESS")
disk.close()
return
except Exception as exc:
print(f" readback exc {exc}")
try:
disk.close()
except Exception:
disk._sock.close()
print("NO SUCCESS")
if __name__ == "__main__":
unittest.main()
+173
View File
@@ -0,0 +1,173 @@
#define _GNU_SOURCE
#include <dlfcn.h>
#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <unistd.h>
static FILE *out;
static pthread_mutex_t log_mu = PTHREAD_MUTEX_INITIALIZER;
static int log_fd = -1;
static void init_out(void) {
if (out) {
return;
}
const char *path = getenv("SSLHOOK_LOG");
if (!path) {
path = "/tmp/sslhook-open.log";
}
out = fopen(path, "w");
if (!out) {
out = stderr;
}
log_fd = fileno(out);
setvbuf(out, NULL, _IONBF, 0);
}
static int peer_port(int fd) {
struct sockaddr_storage ss;
socklen_t len = sizeof(ss);
if (getpeername(fd, (struct sockaddr *)&ss, &len) != 0) {
return -1;
}
if (ss.ss_family == AF_INET) {
return ntohs(((struct sockaddr_in *)&ss)->sin_port);
}
if (ss.ss_family == AF_INET6) {
return ntohs(((struct sockaddr_in6 *)&ss)->sin6_port);
}
return -1;
}
static void dump(const char *tag, const void *id, int fd, const void *buf, int num) {
init_out();
pthread_mutex_lock(&log_mu);
fprintf(out, "\n==== %s %p fd=%d port=%d %d ====\n",
tag, id, fd, fd >= 0 ? peer_port(fd) : -1, num);
const unsigned char *p = buf;
for (int i = 0; i < num; i++) {
fprintf(out, "%02x", p[i]);
}
fprintf(out, "\n");
pthread_mutex_unlock(&log_mu);
}
typedef int (*ssl_write_fn)(void *, const void *, int);
typedef int (*ssl_read_fn)(void *, void *, int);
typedef int (*ssl_get_fd_fn)(const void *);
typedef int (*ssl_write_ex_fn)(void *, const void *, size_t, size_t *);
typedef int (*ssl_read_ex_fn)(void *, void *, size_t, size_t *);
static ssl_get_fd_fn real_ssl_get_fd(void) {
static ssl_get_fd_fn fn;
if (!fn) {
fn = (ssl_get_fd_fn)dlsym(RTLD_NEXT, "SSL_get_fd");
}
return fn;
}
int SSL_write(void *ssl, const void *buf, int num) {
static ssl_write_fn real;
if (!real) {
real = (ssl_write_fn)dlsym(RTLD_NEXT, "SSL_write");
}
int fd = real_ssl_get_fd() ? real_ssl_get_fd()(ssl) : -1;
dump("SSL_W", ssl, fd, buf, num);
return real(ssl, buf, num);
}
int SSL_read(void *ssl, void *buf, int num) {
static ssl_read_fn real;
if (!real) {
real = (ssl_read_fn)dlsym(RTLD_NEXT, "SSL_read");
}
int n = real(ssl, buf, num);
if (n > 0) {
int fd = real_ssl_get_fd() ? real_ssl_get_fd()(ssl) : -1;
dump("SSL_R", ssl, fd, buf, n);
}
return n;
}
int SSL_write_ex(void *ssl, const void *buf, size_t num, size_t *written) {
static ssl_write_ex_fn real;
if (!real) {
real = (ssl_write_ex_fn)dlsym(RTLD_NEXT, "SSL_write_ex");
}
int fd = real_ssl_get_fd() ? real_ssl_get_fd()(ssl) : -1;
dump("SSL_WEX", ssl, fd, buf, (int)num);
return real(ssl, buf, num, written);
}
int SSL_read_ex(void *ssl, void *buf, size_t num, size_t *readbytes) {
static ssl_read_ex_fn real;
if (!real) {
real = (ssl_read_ex_fn)dlsym(RTLD_NEXT, "SSL_read_ex");
}
int rc = real(ssl, buf, num, readbytes);
if (rc && readbytes && *readbytes > 0) {
int fd = real_ssl_get_fd() ? real_ssl_get_fd()(ssl) : -1;
dump("SSL_REX", ssl, fd, buf, (int)*readbytes);
}
return rc;
}
static int interesting_fd(int fd) {
if (fd < 0 || fd == log_fd) {
return 0;
}
int port = peer_port(fd);
return port == 902 || port == 9020;
}
ssize_t write(int fd, const void *buf, size_t count) {
static ssize_t (*real)(int, const void *, size_t);
if (!real) {
real = (ssize_t (*)(int, const void *, size_t))dlsym(RTLD_NEXT, "write");
}
if (interesting_fd(fd) && count > 0 && buf) {
dump("WRITE", NULL, fd, buf, (int)count);
}
return real(fd, buf, count);
}
ssize_t send(int fd, const void *buf, size_t len, int flags) {
static ssize_t (*real)(int, const void *, size_t, int);
if (!real) {
real = (ssize_t (*)(int, const void *, size_t, int))dlsym(RTLD_NEXT, "send");
}
if (interesting_fd(fd) && len > 0 && buf) {
dump("SEND", NULL, fd, buf, (int)len);
}
return real(fd, buf, len, flags);
}
ssize_t read(int fd, void *buf, size_t count) {
static ssize_t (*real)(int, void *, size_t);
if (!real) {
real = (ssize_t (*)(int, void *, size_t))dlsym(RTLD_NEXT, "read");
}
ssize_t n = real(fd, buf, count);
if (n > 0 && interesting_fd(fd)) {
dump("READ", NULL, fd, buf, (int)n);
}
return n;
}
ssize_t recv(int fd, void *buf, size_t len, int flags) {
static ssize_t (*real)(int, void *, size_t, int);
if (!real) {
real = (ssize_t (*)(int, void *, size_t, int))dlsym(RTLD_NEXT, "recv");
}
ssize_t n = real(fd, buf, len, flags);
if (n > 0 && interesting_fd(fd)) {
dump("RECV", NULL, fd, buf, (int)n);
}
return n;
}
+235
View File
@@ -0,0 +1,235 @@
#define _GNU_SOURCE
#include <dlfcn.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/uio.h>
#include <unistd.h>
static FILE *out;
static pthread_mutex_t log_mu = PTHREAD_MUTEX_INITIALIZER;
static int log_fd = -1;
static int ready;
static ssize_t (*real_write)(int, const void *, size_t);
static ssize_t (*real_read)(int, void *, size_t);
static ssize_t (*real_send)(int, const void *, size_t, int);
static ssize_t (*real_recv)(int, void *, size_t, int);
static ssize_t (*real_writev)(int, const struct iovec *, int);
static ssize_t (*real_readv)(int, const struct iovec *, int);
static ssize_t (*real_sendmsg)(int, const struct msghdr *, int);
static ssize_t (*real_recvmsg)(int, struct msghdr *, int);
static int (*real_ssl_write)(void *, const void *, int);
static int (*real_ssl_read)(void *, void *, int);
static int (*real_ssl_get_fd)(const void *);
__attribute__((constructor))
static void init_syms(void) {
real_write = dlsym(RTLD_NEXT, "write");
real_read = dlsym(RTLD_NEXT, "read");
real_send = dlsym(RTLD_NEXT, "send");
real_recv = dlsym(RTLD_NEXT, "recv");
real_writev = dlsym(RTLD_NEXT, "writev");
real_readv = dlsym(RTLD_NEXT, "readv");
real_sendmsg = dlsym(RTLD_NEXT, "sendmsg");
real_recvmsg = dlsym(RTLD_NEXT, "recvmsg");
real_ssl_write = dlsym(RTLD_NEXT, "SSL_write");
real_ssl_read = dlsym(RTLD_NEXT, "SSL_read");
real_ssl_get_fd = dlsym(RTLD_NEXT, "SSL_get_fd");
const char *path = getenv("SSLHOOK_LOG");
if (!path) {
path = "/tmp/sslhook-write.log";
}
out = fopen(path, "w");
if (!out) {
out = stderr;
}
log_fd = fileno(out);
setvbuf(out, NULL, _IONBF, 0);
ready = 1;
fprintf(out, "hook loaded write=%p ssl_write=%p\n",
(void *)real_write, (void *)real_ssl_write);
}
static int peer_port(int fd) {
struct sockaddr_storage ss;
socklen_t len = sizeof(ss);
if (getpeername(fd, (struct sockaddr *)&ss, &len) != 0) {
return -1;
}
if (ss.ss_family == AF_INET) {
return ntohs(((struct sockaddr_in *)&ss)->sin_port);
}
if (ss.ss_family == AF_INET6) {
return ntohs(((struct sockaddr_in6 *)&ss)->sin6_port);
}
return -1;
}
static void dump(const char *tag, int fd, const void *buf, int num) {
if (!ready || !out || fd == log_fd || num <= 0 || num > 1024 * 1024) {
return;
}
int port = peer_port(fd);
if (port <= 0 || port == 443) {
return;
}
const unsigned char *p = buf;
/* Skip TLS records. */
if (num >= 3 && p[0] == 0x16 && p[1] == 0x03) {
return;
}
if (num >= 3 && p[0] == 0x17 && p[1] == 0x03) {
return;
}
pthread_mutex_lock(&log_mu);
fprintf(out, "\n==== %s fd=%d port=%d %d ====\n", tag, fd, port, num);
for (int i = 0; i < num; i++) {
fprintf(out, "%02x", p[i]);
}
fprintf(out, "\n");
pthread_mutex_unlock(&log_mu);
}
ssize_t write(int fd, const void *buf, size_t count) {
if (real_write == NULL) {
return syscall(SYS_write, fd, buf, count);
}
if (ready && out && fd != log_fd) {
static int nlogged;
if (nlogged < 40) {
fprintf(out, "write fd=%d port=%d n=%zu\n", fd, peer_port(fd), count);
nlogged++;
}
}
dump("WRITE", fd, buf, (int)count);
return real_write(fd, buf, count);
}
ssize_t read(int fd, void *buf, size_t count) {
if (real_read == NULL) {
return syscall(SYS_read, fd, buf, count);
}
ssize_t n = real_read(fd, buf, count);
if (n > 0) {
dump("READ", fd, buf, (int)n);
}
return n;
}
ssize_t send(int fd, const void *buf, size_t len, int flags) {
if (real_send == NULL) {
return syscall(SYS_sendto, fd, buf, len, flags, NULL, 0);
}
dump("SEND", fd, buf, (int)len);
return real_send(fd, buf, len, flags);
}
ssize_t recv(int fd, void *buf, size_t len, int flags) {
if (real_recv == NULL) {
return syscall(SYS_recvfrom, fd, buf, len, flags, NULL, 0);
}
ssize_t n = real_recv(fd, buf, len, flags);
if (n > 0) {
dump("RECV", fd, buf, (int)n);
}
return n;
}
ssize_t writev(int fd, const struct iovec *iov, int iovcnt) {
if (real_writev == NULL) {
return syscall(SYS_writev, fd, iov, iovcnt);
}
size_t total = 0;
for (int i = 0; i < iovcnt; i++) {
total += iov[i].iov_len;
}
if (total > 0 && total <= 1024 * 1024) {
unsigned char *buf = malloc(total);
if (buf) {
size_t off = 0;
for (int i = 0; i < iovcnt; i++) {
memcpy(buf + off, iov[i].iov_base, iov[i].iov_len);
off += iov[i].iov_len;
}
dump("WRITEV", fd, buf, (int)total);
free(buf);
}
}
return real_writev(fd, iov, iovcnt);
}
int SSL_write(void *ssl, const void *buf, int num) {
if (real_ssl_write == NULL) {
real_ssl_write = dlsym(RTLD_NEXT, "SSL_write");
}
int fd = real_ssl_get_fd ? real_ssl_get_fd(ssl) : -1;
dump("SSL_W", fd, buf, num);
return real_ssl_write(ssl, buf, num);
}
int SSL_read(void *ssl, void *buf, int num) {
if (real_ssl_read == NULL) {
real_ssl_read = dlsym(RTLD_NEXT, "SSL_read");
}
int n = real_ssl_read(ssl, buf, num);
if (n > 0) {
int fd = real_ssl_get_fd ? real_ssl_get_fd(ssl) : -1;
dump("SSL_R", fd, buf, n);
}
return n;
}
static void dump_msghdr(const char *tag, int fd, const struct msghdr *msg) {
if (!msg || !msg->msg_iov) {
return;
}
size_t total = 0;
for (size_t i = 0; i < (size_t)msg->msg_iovlen; i++) {
total += msg->msg_iov[i].iov_len;
}
if (total == 0 || total > 1024 * 1024) {
return;
}
unsigned char *buf = malloc(total);
if (!buf) {
return;
}
size_t off = 0;
for (size_t i = 0; i < (size_t)msg->msg_iovlen; i++) {
memcpy(buf + off, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
off += msg->msg_iov[i].iov_len;
}
dump(tag, fd, buf, (int)total);
free(buf);
}
ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
if (real_sendmsg == NULL) {
real_sendmsg = dlsym(RTLD_NEXT, "sendmsg");
}
if (ready && out && fd != log_fd) {
static int nlogged;
if (nlogged < 20) {
fprintf(out, "sendmsg fd=%d port=%d\n", fd, peer_port(fd));
nlogged++;
}
}
dump_msghdr("SENDMSG", fd, msg);
return real_sendmsg(fd, msg, flags);
}
ssize_t recvmsg(int fd, struct msghdr *msg, int flags) {
if (real_recvmsg == NULL) {
real_recvmsg = dlsym(RTLD_NEXT, "recvmsg");
}
ssize_t n = real_recvmsg(fd, msg, flags);
if (n > 0) {
dump_msghdr("RECVMSG", fd, msg);
}
return n;
}
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/env python3
"""Trace VDDK Open+Read for NFC protocol capture."""
import ctypes
import os
VDDK_DIR = "/home/ubuntu/workspace/vmware_nbd_tests/vddk"
lib = ctypes.CDLL(os.path.join(VDDK_DIR, "libvixDiskLib.so"))
VIXDISKLIB_CRED_UID = 1
VIXDISKLIB_FLAG_OPEN_READ_ONLY = 4
class VixDiskLibUidPasswdCreds(ctypes.Structure):
_fields_ = [
("userName", ctypes.c_char_p),
("password", ctypes.c_char_p),
]
class VixDiskLibSessionIdCreds(ctypes.Structure):
_fields_ = [
("cookie", ctypes.c_char_p),
("userName", ctypes.c_char_p),
("key", ctypes.c_char_p),
]
class VixDiskLibCreds(ctypes.Union):
_fields_ = [
("uid", VixDiskLibUidPasswdCreds),
("sessionId", VixDiskLibSessionIdCreds),
]
class VixDiskLibConnectParams(ctypes.Structure):
_fields_ = [
("vmxSpec", ctypes.c_char_p),
("serverName", ctypes.c_char_p),
("thumbPrint", ctypes.c_char_p),
("privateUse", ctypes.c_longlong),
("credType", ctypes.c_uint32),
("creds", VixDiskLibCreds),
("port", ctypes.c_uint32),
("nfcHostPort", ctypes.c_uint32),
("vimApiVer", ctypes.c_char_p),
]
def check(err, what):
if err != 0:
lib.VixDiskLib_GetErrorText.restype = ctypes.c_void_p
lib.VixDiskLib_GetErrorText.argtypes = [ctypes.c_uint64, ctypes.c_char_p]
msg = lib.VixDiskLib_GetErrorText(err, None)
text = ctypes.cast(msg, ctypes.c_char_p).value
lib.VixDiskLib_FreeErrorText.argtypes = [ctypes.c_char_p]
lib.VixDiskLib_FreeErrorText(ctypes.cast(msg, ctypes.c_char_p))
raise SystemExit(f"{what} failed: {err} {text}")
def main():
os.makedirs("/tmp/vddk-open-trace", exist_ok=True)
config_path = "/tmp/vddk-open-trace/vddk.config"
with open(config_path, "w") as f:
f.write("tmpDirectory=/tmp/vddk-open-trace\n")
f.write("log.fileName=/tmp/vddk-open-trace/vddk.log\n")
f.write("log.fileLevel=verbose\n")
f.write("vixDiskLib.nfc.LogLevel=4\n")
f.write("vixDiskLib.transport.LogLevel=4\n")
lib.VixDiskLib_InitEx.argtypes = [
ctypes.c_uint32, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_char_p, ctypes.c_char_p]
lib.VixDiskLib_InitEx.restype = ctypes.c_uint64
check(lib.VixDiskLib_InitEx(
8, 0, None, None, None, VDDK_DIR.encode(), config_path.encode()),
"InitEx")
params = VixDiskLibConnectParams()
params.vmxSpec = b"<sanitized>"
params.serverName = b"<sanitized>"
params.thumbPrint = b"<sanitized>"
params.credType = VIXDISKLIB_CRED_UID
params.creds.uid.userName = b"<sanitized>"
params.creds.uid.password = b"<sanitized>"
params.port = 443
lib.VixDiskLib_ConnectEx.argtypes = [
ctypes.POINTER(VixDiskLibConnectParams), ctypes.c_char,
ctypes.c_char_p, ctypes.c_char_p, ctypes.POINTER(ctypes.c_void_p)]
lib.VixDiskLib_ConnectEx.restype = ctypes.c_uint64
conn = ctypes.c_void_p()
check(lib.VixDiskLib_ConnectEx(
params, True, b"snapshot-13442", b"nbd", ctypes.byref(conn)),
"ConnectEx")
print("ConnectEx ok", flush=True)
lib.VixDiskLib_Open.argtypes = [
ctypes.c_void_p, ctypes.c_char_p, ctypes.c_uint32,
ctypes.POINTER(ctypes.c_void_p)]
lib.VixDiskLib_Open.restype = ctypes.c_uint64
disk = ctypes.c_void_p()
path = b"[datastore0] test-coriolis-jenkins-rocky9/test-coriolis-jenkins-rocky9-000007.vmdk"
check(lib.VixDiskLib_Open(conn, path, VIXDISKLIB_FLAG_OPEN_READ_ONLY, ctypes.byref(disk)),
"Open")
print("Open ok", flush=True)
buf = ctypes.create_string_buffer(512)
lib.VixDiskLib_Read.argtypes = [
ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_char_p]
lib.VixDiskLib_Read.restype = ctypes.c_uint64
check(lib.VixDiskLib_Read(disk, 0, 1, buf), "Read")
print("Read ok first16", buf.raw[:16].hex(), flush=True)
lib.VixDiskLib_Close.argtypes = [ctypes.c_void_p]
lib.VixDiskLib_Close.restype = ctypes.c_uint64
lib.VixDiskLib_Disconnect.argtypes = [ctypes.c_void_p]
lib.VixDiskLib_Disconnect.restype = ctypes.c_uint64
lib.VixDiskLib_Close(disk)
lib.VixDiskLib_Disconnect(conn)
lib.VixDiskLib_Exit()
if __name__ == "__main__":
main()
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""Trace VDDK Read at several offsets/sizes for NFC IO capture."""
import ctypes
import os
VDDK_DIR = "/home/ubuntu/workspace/vmware_nbd_tests/vddk"
lib = ctypes.CDLL(os.path.join(VDDK_DIR, "libvixDiskLib.so"))
VIXDISKLIB_CRED_UID = 1
VIXDISKLIB_FLAG_OPEN_READ_ONLY = 4
SECTOR = 512
class VixDiskLibUidPasswdCreds(ctypes.Structure):
_fields_ = [
("userName", ctypes.c_char_p),
("password", ctypes.c_char_p),
]
class VixDiskLibSessionIdCreds(ctypes.Structure):
_fields_ = [
("cookie", ctypes.c_char_p),
("userName", ctypes.c_char_p),
("key", ctypes.c_char_p),
]
class VixDiskLibCreds(ctypes.Union):
_fields_ = [
("uid", VixDiskLibUidPasswdCreds),
("sessionId", VixDiskLibSessionIdCreds),
]
class VixDiskLibConnectParams(ctypes.Structure):
_fields_ = [
("vmxSpec", ctypes.c_char_p),
("serverName", ctypes.c_char_p),
("thumbPrint", ctypes.c_char_p),
("privateUse", ctypes.c_longlong),
("credType", ctypes.c_uint32),
("creds", VixDiskLibCreds),
("port", ctypes.c_uint32),
("nfcHostPort", ctypes.c_uint32),
("vimApiVer", ctypes.c_char_p),
]
def check(err, what):
if err != 0:
lib.VixDiskLib_GetErrorText.restype = ctypes.c_void_p
lib.VixDiskLib_GetErrorText.argtypes = [ctypes.c_uint64, ctypes.c_char_p]
msg = lib.VixDiskLib_GetErrorText(err, None)
text = ctypes.cast(msg, ctypes.c_char_p).value
lib.VixDiskLib_FreeErrorText.argtypes = [ctypes.c_char_p]
lib.VixDiskLib_FreeErrorText(ctypes.cast(msg, ctypes.c_char_p))
raise SystemExit(f"{what} failed: {err} {text}")
def main():
os.makedirs("/tmp/vddk-read-trace", exist_ok=True)
config_path = "/tmp/vddk-read-trace/vddk.config"
with open(config_path, "w") as f:
f.write("tmpDirectory=/tmp/vddk-read-trace\n")
f.write("log.fileName=/tmp/vddk-read-trace/vddk.log\n")
f.write("log.fileLevel=verbose\n")
f.write("vixDiskLib.nfc.LogLevel=4\n")
f.write("vixDiskLib.transport.LogLevel=4\n")
lib.VixDiskLib_InitEx.argtypes = [
ctypes.c_uint32, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_char_p, ctypes.c_char_p]
lib.VixDiskLib_InitEx.restype = ctypes.c_uint64
check(lib.VixDiskLib_InitEx(
8, 0, None, None, None, VDDK_DIR.encode(), config_path.encode()),
"InitEx")
params = VixDiskLibConnectParams()
params.vmxSpec = b"<sanitized>"
params.serverName = b"<sanitized>"
params.thumbPrint = b"<sanitized>"
params.credType = VIXDISKLIB_CRED_UID
params.creds.uid.userName = b"<sanitized>"
params.creds.uid.password = b"<sanitized>"
params.port = 443
lib.VixDiskLib_ConnectEx.argtypes = [
ctypes.POINTER(VixDiskLibConnectParams), ctypes.c_char,
ctypes.c_char_p, ctypes.c_char_p, ctypes.POINTER(ctypes.c_void_p)]
lib.VixDiskLib_ConnectEx.restype = ctypes.c_uint64
conn = ctypes.c_void_p()
check(lib.VixDiskLib_ConnectEx(
params, True, b"snapshot-13442", b"nbd", ctypes.byref(conn)),
"ConnectEx")
print("ConnectEx ok", flush=True)
lib.VixDiskLib_Open.argtypes = [
ctypes.c_void_p, ctypes.c_char_p, ctypes.c_uint32,
ctypes.POINTER(ctypes.c_void_p)]
lib.VixDiskLib_Open.restype = ctypes.c_uint64
disk = ctypes.c_void_p()
path = b"[datastore0] test-coriolis-jenkins-rocky9/test-coriolis-jenkins-rocky9-000007.vmdk"
check(lib.VixDiskLib_Open(conn, path, VIXDISKLIB_FLAG_OPEN_READ_ONLY, ctypes.byref(disk)),
"Open")
print("Open ok", flush=True)
lib.VixDiskLib_Read.argtypes = [
ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_char_p]
lib.VixDiskLib_Read.restype = ctypes.c_uint64
reads = [
(0, 1),
(0, 2),
(1, 1),
(8, 8),
(0, 128),
(0, 129),
(256, 64),
]
for start, n in reads:
buf = ctypes.create_string_buffer(n * SECTOR)
check(lib.VixDiskLib_Read(disk, start, n, buf), f"Read {start}+{n}")
nz = sum(1 for b in buf.raw if b)
print(f"Read start={start} n={n} first16={buf.raw[:16].hex()} nonzero={nz}",
flush=True)
lib.VixDiskLib_Close.argtypes = [ctypes.c_void_p]
lib.VixDiskLib_Close.restype = ctypes.c_uint64
lib.VixDiskLib_Disconnect.argtypes = [ctypes.c_void_p]
lib.VixDiskLib_Disconnect.restype = ctypes.c_uint64
lib.VixDiskLib_Close(disk)
lib.VixDiskLib_Disconnect(conn)
lib.VixDiskLib_Exit()
if __name__ == "__main__":
main()
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env python3
"""One-off: VDDK write with verbose NFC logs. Not part of the library."""
import os
import sys
import unittest
sys.path.insert(0, "/home/ubuntu/workspace/vmware_nbd_tests")
os.environ.pop("LD_PRELOAD", None)
os.environ["LD_LIBRARY_PATH"] = (
"/home/ubuntu/workspace/vmware_nbd_tests/.vddk:"
+ os.environ.get("LD_LIBRARY_PATH", ""))
from tests.integration.base import TestBase
from tests.integration import vixdisklib
class _T(TestBase):
@classmethod
def setUpClass(cls):
cls.require_vddk()
super().setUpClass()
def test_write(self):
handle = vixdisklib.VixDiskLibHandle(
vixdisklib_compatibility_version="8.0",
config_path="/tmp/vddk_nfc.conf")
buf = vixdisklib.get_buffer(self.SECTOR_SIZE)
expected = self.pattern_bytes(self.SECTOR_SIZE, b"TRACE-S0")
buf[:self.SECTOR_SIZE] = expected
with handle.connect(**self.vixdisklib_connect_kwargs()) as conn:
with handle.open(conn, self.DISK_PATH, flags=0) as disk:
handle.write(disk, 0, 1, buf)
handle.read(disk, 0, 1, buf)
print("DISK_PATH", self.DISK_PATH, "ok", buf.raw[:8])
if __name__ == "__main__":
unittest.main()