ISCSIHDDCore.cpp revision cffec623de1226ac1585b317a8816635e71cb11a
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * iSCSI initiator driver, VD backend.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Copyright (C) 2006-2009 Sun Microsystems, Inc.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * available from http://www.virtualbox.org. This file is free software;
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * General Public License (GPL) as published by the Free Software
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * additional information or have any questions.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/*******************************************************************************
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync* Header Files *
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync*******************************************************************************/
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync#define VBOX_VDICORE_VD /* Signal that the header is included from here. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/*******************************************************************************
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync* Defined Constants And Macros *
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync*******************************************************************************/
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Default port number to use for iSCSI. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Converts a number in the range of 0 - 15 into the corresponding hex char. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync#define NUM_2_HEX(b) ('0' + (b) + (((b) > 9) ? 39 : 0))
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Converts a hex char into the corresponding number in the range 0-15. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync#define HEX_2_NUM(c) (((c) <= '9') ? ((c) - '0') : (((c - 'A' + 10) & 0xf)))
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/* Converts a base64 char into the corresponding number in the range 0-63. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync#define B64_2_NUM(c) ((c >= 'A' && c <= 'Z') ? (c - 'A') : (c >= 'a' && c <= 'z') ? (c - 'a' + 26) : (c >= '0' && c <= '9') ? (c - '0' + 52) : (c == '+') ? 62 : (c == '/') ? 63 : -1)
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Minumum CHAP_MD5 challenge length in bytes. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Maximum CHAP_MD5 challenge length in bytes. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * SCSI peripheral device type. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** direct-access device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** sequential-access device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** printer device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** processor device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** write-once device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** CD/DVD device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** scanner device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** optical memory device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** medium changer. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** communications device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** storage array controller device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** enclosure services device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** simplified direct-access device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** optical card reader/writer device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** bridge controller device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** object-based storage device. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Mask for extracting the SCSI device type out of the first byte of the INQUIRY response. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Maximum PDU payload size we can handle in one piece. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Maximum PDU size we can handle in one piece. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync#define ISCSI_RECV_PDU_BUFFER_SIZE (ISCSI_DATA_LENGTH_MAX + ISCSI_BHS_SIZE)
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Version of the iSCSI standard which this initiator driver can handle. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Length of ISCSI basic header segment. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** Reserved task tag value. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * iSCSI opcodes. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** NOP-Out. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** SCSI command. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** SCSI task management request. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** Login request. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** Text request. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** SCSI Data-Out. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** Logout request. */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** SNACK request. */
} ISCSIOPCODE;
typedef enum ISCSILOGINSTATUSCLASS
typedef enum ISCSISTATE
/** Not having a connection/session at all. */
} ISCSISTATE;
typedef struct ISCSIIMAGE
const char *pszFilename;
char *pszInitiatorName;
char *pszTargetName;
char *pszTargetAddress;
char *pszInitiatorUsername;
char *pszTargetUsername;
unsigned uOpenFlags;
/** Current state of the connection/session. */
bool FirstRecvPDU;
void *pvRecvPDUBuf;
char *pszHostname;
bool fHostIP;
typedef enum SCSIXFER
SCSIXFER_NONE = 0,
typedef struct SCSIREQ
void *pvCmd;
const void *pcvI2TData;
void *pvT2IData;
void *pvSense;
typedef struct ISCSIPARAMETER
const char *pszParamName;
const char *pszParamValue;
static int iscsiTextAddKeyValue(uint8_t *pbBuf, size_t cbBuf, size_t *pcbBufCurr, const char *pcszKey, const char *pcszValue, size_t cbValue);
static int iscsiTextGetKeyValue(const uint8_t *pbBuf, size_t cbBuf, const char *pcszKey, const char **ppcszValue);
#ifdef IMPLEMENT_TARGET_AUTH
static void chap_md5_compute_response(uint8_t *pbResponse, uint8_t id, const uint8_t *pbChallenge, size_t cbChallenge,
const char *pszFormat, ...)
return rc;
char *pDst;
rc = pImage->pInterfaceNetCallbacks->pfnClientConnect(pImage->pszHostname, pImage->uPort, &pImage->Socket);
cbToRead = 0;
if (cMilliesRemaining <= 0)
if (cbActuallyRead == 0)
if (cbToRead == 0)
if (cbToRead == 0)
if (cbToRead == 0)
if (residual == 0)
if (i >= cnResponse)
for (i++; i < cnResponse; i++)
return rc;
LogFlow(("drvISCSITransportTcpWrite: cnRequest=%d (%s:%d)\n", cnRequest, pImage->pszHostname, pImage->uPort));
rc = pImage->pInterfaceNetCallbacks->pfnClientConnect(pImage->pszHostname, pImage->uPort, &pImage->Socket);
for (i = 0; i < cnRequest; i++)
&pad,
return rc;
char *pszPortEnd;
pcszPort++;
pcszPort++;
pcszPort++;
return rc;
int rc;
return rc;
int rc;
bool transit;
char *pszNext;
bool fParameterNeg = true;;
csg = 0;
nsg = 0;
substate = 0;
transit = false;
cbBuf = 0;
goto out;
rc = iscsiTextAddKeyValue(bBuf, sizeof(bBuf), &cbBuf, "InitiatorName", pImage->pszInitiatorName, 0);
goto out;
goto out;
goto out;
transit = true;
goto out;
goto out;
goto out;
rc = iscsiTextAddKeyValue(bBuf, sizeof(bBuf), &cbBuf, "CHAP_R", (const char *)aResponse, RTMD5HASHSIZE);
goto out;
transit = true;
if (fParameterNeg)
goto out;
fParameterNeg = false;
transit = true;
cnISCSIReq = 0;
cnISCSIReq++;
cnISCSIReq++;
cnISCSIRes = 0;
cnISCSIRes++;
cnISCSIRes++;
switch (loginStatusClass)
bool targetTransit;
const char *pcszAuthMethod;
transit = true;
substate = 0;
substate++;
const char *pcszChapAuthMethod;
const char *pcszChapIdxTarget;
const char *pcszChapChallengeStr;
substate++;
transit = true;
substate = 0;
substate = 0;
substate = 0;
const char *pcszTargetRedir;
goto restart;
goto out;
AssertMsgFailed(("%s: ignoring unexpected PDU with first word = %#08x\n", __FUNCTION__, RT_N2H_U32(aResBHS[0])));
out:
LogRel(("iSCSI: login to target %s %s\n", pImage->pszTargetName, RT_SUCCESS(rc) ? "successful" : "failed"));
return rc;
int rc;
cnISCSIReq++;
return VINF_SUCCESS;
int rc;
bool final = false;
Assert(pRequest->enmXfer != SCSIXFER_TO_FROM_TARGET); /**< @todo not yet supported, would require AHS. */
goto out;
cbData = 0;
aReqBHS[1] = RT_H2N_U32(0x00000000 | ((uint32_t)pRequest->cbI2TData & 0xffffff)); /* TotalAHSLength=0 */
cnISCSIReq++;
cnISCSIReq++;
goto out_release;
cbBufLength = 0;
cnISCSIRes++;
if (cbBufLength != 0 &&
cnISCSIRes++;
cnISCSIRes++;
if (!final || ((RT_N2H_U32(aResBHS[0]) & 0x0000ff00) != 0) || (RT_N2H_U32(aResBHS[6]) != pImage->ExpStatSN - 1))
memcpy((char *)pRequest->pvSense + aISCSIRes[1].cbSeg, aISCSIRes[2].pvSeg, cbStat - aISCSIRes[1].cbSeg - 2);
ExpDataSN++;
out:
return rc;
uint32_t i;
* needs cleaning up of timeout/disconnect handling a bit, as otherwise
return rc;
uint32_t i;
* the iSCSI connection/session. */
switch (cmd)
case ISCSIOP_SCSI_RES:
case ISCSIOP_SCSI_DATA_IN:
case ISCSIOP_R2T:
case ISCSIOP_ASYN_MSG:
case ISCSIOP_TEXT_RES:
case ISCSIOP_LOGIN_RES:
case ISCSIOP_LOGOUT_RES:
case ISCSIOP_REJECT:
case ISCSIOP_NOP_IN:
uint32_t i;
for (i = 0; i < cnRes; i++)
cbSeg = 0;
if (cbSeg != 0)
for (i++; i < cnRes; i++)
cnISCSIReq = 0;
cnISCSIReq++;
return rc;
* Check the static (not dependent on the connection/session state) validity of an iSCSI response PDU.
case ISCSIOP_NOP_IN:
return VERR_PARSE_ERROR;
case ISCSIOP_SCSI_RES:
| ISCSI_RESIDUAL_OVFL_BIT))))
return VERR_PARSE_ERROR;
case ISCSIOP_LOGIN_RES:
return VERR_PARSE_ERROR;
case ISCSIOP_TEXT_RES:
return VERR_PARSE_ERROR;
case ISCSIOP_SCSI_DATA_IN:
return VERR_PARSE_ERROR;
case ISCSIOP_LOGOUT_RES:
return VERR_PARSE_ERROR;
case ISCSIOP_ASYN_MSG:
return VERR_PARSE_ERROR;
case ISCSIOP_R2T:
case ISCSIOP_REJECT:
LogFlow(("drvISCSIValidatePDU: ignore unhandled PDU, first word %#08x\n", RT_N2H_U32(pcrgResBHS[0])));
return VERR_PARSE_ERROR;
return VERR_PARSE_ERROR;
return VINF_SUCCESS;
* Appends a key-value pair to the buffer. Normal ASCII strings (cbValue == 0) and large binary values
* of a given length (cbValue > 0) are directly supported. Other value types must be converted to ASCII
static int iscsiTextAddKeyValue(uint8_t *pbBuf, size_t cbBuf, size_t *pcbBufCurr, const char *pcszKey,
if (cbValue == 0)
return VERR_BUFFER_OVERFLOW;
if (cbValue == 0)
uint8_t b;
b = pcszValue[i];
return VINF_SUCCESS;
static int iscsiTextGetKeyValue(const uint8_t *pbBuf, size_t cbBuf, const char *pcszKey, const char **ppcszValue)
while (cbBuf != 0)
return VINF_SUCCESS;
return VERR_INVALID_NAME;
return VERR_PARSE_ERROR;
return VERR_PARSE_ERROR;
switch (*pcszValue++)
cbValue--;
if (cbValue == 0)
return VERR_BUFFER_OVERFLOW;
return VERR_PARSE_ERROR;
return VERR_PARSE_ERROR;
cbValue--;
return VERR_PARSE_ERROR;
if (cbValue == 0)
return VERR_BUFFER_OVERFLOW;
if ((c1 < 'A' || c1 > 'Z') && (c1 < 'a' || c1 >'z') && (c1 < '0' || c1 > '9') && (c1 != '+') && (c1 != '/'))
return VERR_PARSE_ERROR;
if ((c2 < 'A' || c2 > 'Z') && (c2 < 'a' || c2 >'z') && (c2 < '0' || c2 > '9') && (c2 != '+') && (c2 != '/'))
return VERR_PARSE_ERROR;
if ((c3 < 'A' || c3 > 'Z') && (c3 < 'a' || c3 >'z') && (c3 < '0' || c3 > '9') && (c3 != '+') && (c3 != '/') && (c3 != '='))
return VERR_PARSE_ERROR;
|| ((c4 < 'A' || c4 > 'Z') && (c4 < 'a' || c4 >'z') && (c4 < '0' || c4 > '9') && (c4 != '+') && (c4 != '/') && (c4 != '=')))
return VERR_PARSE_ERROR;
return VERR_PARSE_ERROR;
cbValue--;
return VERR_PARSE_ERROR;
return VERR_BUFFER_OVERFLOW;
return VERR_BUFFER_OVERFLOW;
return VERR_PARSE_ERROR;
return VINF_SUCCESS;
int rc;
return VERR_PARSE_ERROR;
return VERR_PARSE_ERROR;
return VERR_PARSE_ERROR;
if (pcszMaxBurstLength)
if (pcszFirstBurstLength)
return VINF_SUCCESS;
#ifdef IMPLEMENT_TARGET_AUTH
static void chap_md5_compute_response(uint8_t *pbResponse, uint8_t id, const uint8_t *pbChallenge, size_t cbChallenge,
int rc;
bool fLunEncoded = false;
bool fHostIPDef = 0;
goto out;
goto out;
pImage->ISID = 0x800000000000ULL | 0x001234560000ULL | (0x00000000cba0ULL + ASMAtomicIncU32(&s_u32iscsiID));
goto out;
goto out;
"TargetName\0InitiatorName\0LUN\0TargetAddress\0InitiatorUsername\0InitiatorSecret\0TargetUsername\0TargetSecret\0Timeout\0HostIPStack\0"))
rc = iscsiError(pImage, VERR_VD_ISCSI_UNKNOWN_CFG_VALUES, RT_SRC_POS, N_("iSCSI: configuration error: unknown configuration keys present"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetName as string"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorName as string"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read LUN as string"));
goto out;
fLunEncoded = true;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to convert LUN to integer"));
goto out;
if (!fLunEncoded)
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: LUN number out of range (0-16383)"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetAddress as string"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorUsername as string"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorSecret as byte string"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetUsername as string"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetSecret as byte string"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read Timeout as U32"));
goto out;
rc = iscsiError(pImage, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read HostIPStack as boolean"));
goto out;
LogFunc(("Not opening the transport connection as IntNet IP stack is not available. Will return dummies\n"));
goto out;
goto out;
return rc;
LogRel(("iSCSI: Unsupported SCSI peripheral device type %d for target %s\n", data8[0] & SCSI_DEVTYPE_MASK, pImage->pszTargetName));
goto out;
goto out;
goto out;
LogRel(("iSCSI: Could not get MODE SENSE info for target %s, rc=%Rrc\n", pImage->pszTargetName, rc));
goto out;
RT_SRC_POS, N_("iSCSI: target address %s, target name %s, SCSI LUN %lld reports media sector count=%lu sector size=%lu"),
goto out;
LogRel(("iSCSI: Could not check write cache of target %s, rc=%Rrc, got mode page %#x\n", pImage->pszTargetName, rc,aCachingModePage[0] & 0x3f));
out:
return rc;
return rc;
void **ppBackendData)
LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
int rc;
goto out;
|| !*pszFilename
goto out;
if (!pImage)
goto out;
out:
LogFlowFunc(("target %s cVolume %d, cbSector %d\n", pImage->pszTargetName, pImage->cVolume, pImage->cbSector));
LogRel(("iSCSI: target address %s, target name %s, SCSI LUN %lld\n", pImage->pszTargetAddress, pImage->pszTargetName, pImage->LUN));
return rc;
void **ppBackendData)
LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
return rc;
return rc;
if (pImage)
return rc;
LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
int rc;
|| cbToRead == 0)
goto out;
*pcbActuallyRead = 0;
out:
return rc;
LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
int rc;
goto out;
*pcbPreRead = 0;
*pcbPostRead = 0;
*pcbWriteProcess = 0;
out:
return rc;
int rc;
return rc;
if (pImage)
if (pImage)
int rc;
if (pImage)
LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
return rc;
LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
int rc;
if (pImage)
goto out;
out:
return rc;
int rc;
if (pImage)
LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
return rc;
unsigned uImageFlags;
return uImageFlags;
unsigned uOpenFlags;
if (pImage)
uOpenFlags = 0;
return uOpenFlags;
int rc;
goto out;
out:
return rc;
LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
int rc;
if (pImage)
goto out;
out:
return rc;
LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
if (pImage)
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: cVolume=%u\n", pImage->cVolume);
return rc;
return rc;
return rc;
return rc;
return rc;
int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget);
rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress);
return rc;
int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget);
rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress);
return rc;
sizeof(VBOXHDDBACKEND),
NULL,
NULL,
NULL,
NULL,