errno_t iSCSIDCreateArrayofActivePortalsForTarget(int fd,struct iSCSIDCmdCreateArrayOfActivePortalsForTarget * cmd) { CFArrayRef sessionIds = iSCSICreateArrayOfSessionIds(); CFIndex sessionCount = CFArrayGetCount(sessionIds); // Prepare an array to hold our targets CFMutableArrayRef activeTargets = CFArrayCreateMutable(kCFAllocatorDefault, sessionCount, &kCFTypeArrayCallBacks); // Get target object for each active session and add to array for(CFIndex idx = 0; idx < sessionCount; idx++) { iSCSITargetRef target = iSCSICreateTargetForSessionId((SID)CFArrayGetValueAtIndex(sessionIds,idx)); CFArrayAppendValue(activeTargets,target); iSCSITargetRelease(target); } // Serialize and send array CFDataRef data = CFPropertyListCreateData(kCFAllocatorDefault, (CFPropertyListRef) activeTargets, kCFPropertyListBinaryFormat_v1_0,0,NULL); CFRelease(activeTargets); // Send response header struct iSCSIDRspCreateArrayOfActiveTargets rsp = iSCSIDRspCreateArrayOfActiveTargetsInit; if(data) rsp.dataLength = (UInt32)CFDataGetLength(data); else rsp.dataLength = 0; if(send(fd,&rsp,sizeof(rsp),0) != sizeof(rsp)) { if(data) CFRelease(data); return EAGAIN; } if(data) { if(send(fd,CFDataGetBytePtr(data),rsp.dataLength,0) != rsp.dataLength) { CFRelease(data); return EAGAIN; } CFRelease(data); } return 0; }
/*! 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; }
errno_t iSCSIDLogout(int fd,struct iSCSIDCmdLogout * cmd) { // Grab objects from stream iSCSITargetRef target = iSCSIDCreateObjectFromSocket(fd,cmd->targetLength, (void *(* )(CFDataRef))&iSCSITargetCreateWithData); iSCSIPortalRef portal = iSCSIDCreateObjectFromSocket(fd,cmd->portalLength, (void *(* )(CFDataRef))&iSCSIPortalCreateWithData); SID sessionId = kiSCSIInvalidSessionId; CID connectionId = kiSCSIInvalidConnectionId; enum iSCSILogoutStatusCode statusCode = kiSCSILogoutInvalidStatusCode; // Error code to return to daemon's client errno_t errorCode = 0; // Synchronize property list iSCSIPLSynchronize(); // See if there exists an active session for this target if((sessionId = iSCSIGetSessionIdForTarget(iSCSITargetGetIQN(target))) == kiSCSIInvalidSessionId) { //iSCSICtlDisplayError("The specified target has no active session."); errorCode = EINVAL; } // See if there exists an active connection for this portal if(!errorCode && portal) connectionId = iSCSIGetConnectionIdForPortal(sessionId,portal); // If the portal was specified and a connection doesn't exist for it... if(!errorCode && portal && connectionId == kiSCSIInvalidConnectionId) { //iSCSICtlDisplayError("The specified portal has no active connections."); errorCode = EINVAL; } // At this point either the we logout the session or just the connection // associated with the specified portal, if one was specified if(!errorCode) { if(!portal) errorCode = iSCSILogoutSession(sessionId,&statusCode); else errorCode = iSCSILogoutConnection(sessionId,connectionId,&statusCode); /* if(!error) iSCSICtlDisplayLogoutStatus(statusCode,target,portal); else iSCSICtlDisplayError(strerror(error));*/ } if(portal) iSCSIPortalRelease(portal); iSCSITargetRelease(target); // Compose a response to send back to the client struct iSCSIDRspLogout rsp = iSCSIDRspLogoutInit; rsp.errorCode = errorCode; rsp.statusCode = statusCode; if(send(fd,&rsp,sizeof(rsp),0) != sizeof(rsp)) return EAGAIN; return 0; }