/*! Gets whether a portal has an active session. * @param target the target to test for an active session. * @param portal the portal to test for an active connection. * @return true if the is an active connection for the portal; false otherwise. */ Boolean iSCSIDaemonIsPortalActive(iSCSIDaemonHandle handle, iSCSITargetRef target, iSCSIPortalRef portal) { if(handle < 0 || !target || !portal) return false; CFDataRef targetData = iSCSITargetCreateData(target); CFDataRef portalData = iSCSIPortalCreateData(portal); iSCSIDMsgIsPortalActiveCmd cmd = iSCSIDMsgIsPortalActiveCmdInit; cmd.targetLength = (UInt32)CFDataGetLength(targetData); cmd.portalLength = (UInt32)CFDataGetLength(portalData); errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd, targetData,portalData,NULL); CFRelease(targetData); CFRelease(portalData); if(error) return false; iSCSIDMsgIsPortalActiveRsp rsp; if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp)) return false; if(rsp.funcCode != kiSCSIDIsPortalActive) return false; return rsp.active; }
/*! Logs into a target using a specific portal or all portals in the database. * If an argument is supplied for portal, login occurs over the specified * portal. Otherwise, the daemon will attempt to login over all portals. * @param handle a handle to a daemon connection. * @param authorization an authorization for the right kiSCSIAuthModifyLogin * @param target specifies the target and connection parameters to use. * @param portal specifies the portal to use (use NULL for all portals). * @param statusCode iSCSI response code indicating operation status. * @return an error code indicating whether the operation was successful. */ errno_t iSCSIDaemonLogin(iSCSIDaemonHandle handle, AuthorizationRef authorization, iSCSITargetRef target, iSCSIPortalRef portal, enum iSCSILoginStatusCode * statusCode) { if(handle < 0 || !target || !authorization || !statusCode) return EINVAL; CFDataRef targetData = iSCSITargetCreateData(target); CFDataRef portalData = NULL; iSCSIDMsgLoginCmd cmd = iSCSIDMsgLoginCmdInit; cmd.authLength = kAuthorizationExternalFormLength; cmd.targetLength = (UInt32)CFDataGetLength(targetData); cmd.portalLength = 0; if(portal) { portalData = iSCSIPortalCreateData(portal); cmd.portalLength = (UInt32)CFDataGetLength(portalData); } AuthorizationExternalForm authExtForm; AuthorizationMakeExternalForm(authorization,&authExtForm); CFDataRef authData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8*)&authExtForm.bytes, kAuthorizationExternalFormLength, kCFAllocatorDefault); errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd, authData,targetData,portalData,NULL); if(portal) CFRelease(portalData); CFRelease(targetData); if(error) return error; iSCSIDMsgLoginRsp rsp; if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp)) return EIO; if(rsp.funcCode != kiSCSIDLogin) return EIO; // At this point we have a valid response, process it *statusCode = rsp.statusCode; return rsp.errorCode; }
/*! Sets or updates a shared secret. * @param handle a handle to a daemon connection. * @param authorization an authorization for the right kiSCSIAuthModifyRights. * @param nodeIQN the node iSCSI qualified name. * @param sharedSecret the secret to set. * @return an error code indicating whether the operating was successful. */ errno_t iSCSIDaemonSetSharedSecret(iSCSIDaemonHandle handle, AuthorizationRef authorization, CFStringRef nodeIQN, CFStringRef sharedSecret) { // Validate inputs if(handle < 0 || !authorization || !nodeIQN || !sharedSecret) return EINVAL; AuthorizationExternalForm authExtForm; AuthorizationMakeExternalForm(authorization,&authExtForm); CFDataRef authData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8*)&authExtForm.bytes, kAuthorizationExternalFormLength, kCFAllocatorDefault); CFDataRef nodeIQNData = CFStringCreateExternalRepresentation(kCFAllocatorDefault,nodeIQN,kCFStringEncodingASCII,0); CFDataRef sharedSecretData = CFStringCreateExternalRepresentation(kCFAllocatorDefault,sharedSecret,kCFStringEncodingASCII,0); iSCSIDMsgSetSharedSecretCmd cmd = iSCSIDMsgSetSharedSecretCmdInit; cmd.authorizationLength = (UInt32)CFDataGetLength(authData); cmd.nodeIQNLength = (UInt32)CFDataGetLength(nodeIQNData); cmd.secretLength = (UInt32)CFDataGetLength(sharedSecretData); errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd, authData,nodeIQNData,sharedSecretData,NULL); if(nodeIQNData) CFRelease(nodeIQNData); if(sharedSecretData) CFRelease(sharedSecretData); if(error) return error; iSCSIDMsgSetSharedSecretRsp rsp; if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp)) return EIO; if(rsp.funcCode != kiSCSIDSetSharedSecret) return EIO; return rsp.errorCode; }
/*! Retrieves a list of targets available from a give portal. * @param handle a handle to a daemon connection. * @param portal the iSCSI portal to look for targets. * @param authMethod the preferred authentication method. * @param statusCode iSCSI response code indicating operation status. * @return an error code indicating whether the operation was successful. */ errno_t iSCSIDaemonQueryTargetForAuthMethod(iSCSIDaemonHandle handle, iSCSIPortalRef portal, CFStringRef targetIQN, enum iSCSIAuthMethods * authMethod, enum iSCSILoginStatusCode * statusCode) { // Validate inputs if(handle < 0 || !portal || !targetIQN || !authMethod || !statusCode) return EINVAL; // Setup a target object with the target name iSCSIMutableTargetRef target = iSCSITargetCreateMutable(); iSCSITargetSetIQN(target,targetIQN); // Generate data to transmit (no longer need target object after this) CFDataRef targetData = iSCSITargetCreateData(target); iSCSITargetRelease(target); CFDataRef portalData = iSCSIPortalCreateData(portal); // Create command header to transmit iSCSIDMsgQueryTargetForAuthMethodCmd cmd = iSCSIDMsgQueryTargetForAuthMethodCmdInit; cmd.portalLength = (UInt32)CFDataGetLength(portalData); cmd.targetLength = (UInt32)CFDataGetLength(targetData); if(iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd,targetData,portalData,NULL)) { CFRelease(portalData); CFRelease(targetData); return EIO; } CFRelease(portalData); CFRelease(targetData); iSCSIDMsgQueryTargetForAuthMethodRsp rsp; if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp)) return EIO; *authMethod = rsp.authMethod; *statusCode = rsp.statusCode; return rsp.errorCode; }
/*! Logs out of the target or a specific portal, if specified. * @param handle a handle to a daemon connection. * @param target the target to logout. * @param portal the portal to logout. If one is not specified, * @param statusCode iSCSI response code indicating operation status. */ errno_t iSCSIDaemonLogout(iSCSIDaemonHandle handle, iSCSITargetRef target, iSCSIPortalRef portal, enum iSCSILogoutStatusCode * statusCode) { if(handle < 0 || !target || !statusCode) return EINVAL; CFDataRef targetData = iSCSITargetCreateData(target); CFDataRef portalData = NULL; iSCSIDMsgLogoutCmd cmd = iSCSIDMsgLogoutCmdInit; cmd.targetLength = (UInt32)CFDataGetLength(targetData); cmd.portalLength = 0; if(portal) { portalData = iSCSIPortalCreateData(portal); cmd.portalLength = (UInt32)CFDataGetLength(portalData); } errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd, targetData,portalData,NULL); if(portal) CFRelease(portalData); CFRelease(targetData); if(error) return error; iSCSIDMsgLogoutRsp rsp; if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp)) return EIO; if(rsp.funcCode != kiSCSIDLogout) return EIO; // At this point we have a valid response, process it *statusCode = rsp.statusCode; return rsp.errorCode; }
/*! Semaphore that allows a client exclusive accesss to the property list * that contains iSCSI configuraiton parameters and targets. Forces the provided * preferences object to synchronize with property list on the disk. * @param handle a handle to a daemon connection. * @param authorization an authorization for the right kiSCSIAuthModifyRights * @param preferences the preferences to be synchronized * @return an error code indicating whether the operating was successful. */ errno_t iSCSIDaemonPreferencesIOLockAndSync(iSCSIDaemonHandle handle, AuthorizationRef authorization, iSCSIPreferencesRef preferences) { // Validate inputs if(handle < 0 || !authorization || !preferences) return EINVAL; // Send in authorization and acquire lock AuthorizationExternalForm authExtForm; AuthorizationMakeExternalForm(authorization,&authExtForm); CFDataRef authData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8*)authExtForm.bytes, kAuthorizationExternalFormLength, kCFAllocatorDefault); iSCSIDMsgPreferencesIOLockAndSyncCmd cmd = iSCSIDMsgPreferencesIOLockAndSyncCmdInit; cmd.authorizationLength = (UInt32)CFDataGetLength(authData); errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd,authData,NULL); if(error) return error; iSCSIDMsgPreferencesIOLockAndSyncRsp rsp; if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp)) return EIO; if(rsp.funcCode != kiSCSIDPreferencesIOLockAndSync) return EIO; if(rsp.errorCode == 0) { // Force preferences to synchronize after obtaining lock // (this ensures that the client has the most up-to-date preferences data) iSCSIPreferencesUpdateWithAppValues(preferences); } return rsp.errorCode; }
/*! Creates a dictionary of connection parameters for the connection associated * with the specified target and portal, if one exists. * @param handle a handle to a daemon connection. * @param target the target associated with the the specified portal. * @param portal the portal to check for active connections to generate * a dictionary of connection parameters. * @return a dictionary of connection properties. */ CFDictionaryRef iSCSIDaemonCreateCFPropertiesForConnection(iSCSIDaemonHandle handle, iSCSITargetRef target, iSCSIPortalRef portal) { // Validate inputs if(handle < 0 || !target || !portal) return NULL; CFDictionaryRef properties = NULL; CFDataRef targetData = iSCSITargetCreateData(target); CFDataRef portalData = iSCSIPortalCreateData(portal); // Send command to daemon iSCSIDMsgCreateCFPropertiesForConnectionCmd cmd = iSCSIDMsgCreateCFPropertiesForConnectionCmdInit; cmd.targetLength = (UInt32)CFDataGetLength(targetData); cmd.portalLength = (UInt32)CFDataGetLength(portalData); errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd, targetData,portalData,NULL); CFRelease(targetData); CFRelease(portalData); iSCSIDMsgCreateCFPropertiesForConnectionRsp rsp; if(!error) error = iSCSIDaemonRecvMsg(handle,(iSCSIDMsgGeneric*)&rsp,NULL); if(!error) { CFDataRef data = NULL; error = iSCSIDaemonRecvMsg(handle,0,&data,rsp.dataLength,NULL); if(!error && data) { CFPropertyListFormat format; properties = CFPropertyListCreateWithData(kCFAllocatorDefault,data,0,&format,NULL); CFRelease(data); } } return properties; }
/*! Synchronizes cached preference changes to disk and releases the locked * semaphore, allowing other clients to make changes. If the prefereneces * parameter is NULL, then no changes are made to disk and the semaphore is * unlocked. * @param handle a handle to a daemon connection. * @param preferences the preferences to be synchronized * @return an error code indicating whether the operating was successful. */ errno_t iSCSIDaemonPreferencesIOUnlockAndSync(iSCSIDaemonHandle handle, iSCSIPreferencesRef preferences) { // Validate inputs if(handle < 0) return EINVAL; CFDataRef preferencesData = NULL; iSCSIDMsgPreferencesIOUnlockAndSyncCmd cmd = iSCSIDMsgPreferencesIOUnlockAndSyncCmdInit; if(preferences) { preferencesData = iSCSIPreferencesCreateData(preferences); cmd.preferencesLength = (UInt32)CFDataGetLength(preferencesData); } else cmd.preferencesLength = 0; errno_t error = iSCSIDaemonSendMsg(handle,(iSCSIDMsgGeneric *)&cmd,preferencesData,NULL); if(preferencesData) CFRelease(preferencesData); if(error) return error; iSCSIDMsgPreferencesIOUnlockAndSyncRsp rsp; if(recv(handle,&rsp,sizeof(rsp),0) != sizeof(rsp)) return EIO; if(rsp.funcCode != kiSCSIDPreferencesIOUnlockAndSync) return EIO; return rsp.errorCode; }