VOID CNdasIXServer::OnIXUsageRequest( CLpxDatagramSocket& sock, CONST SOCKADDR_LPX* pRemoteAddr, CONST LSINFOX_NDASDEV_USAGE_REQUEST* pData) { NDAS_UNITDEVICE_ID unitDeviceId = { { pData->NetDiskNode[0], pData->NetDiskNode[1], pData->NetDiskNode[2], pData->NetDiskNode[3], pData->NetDiskNode[4], pData->NetDiskNode[5] }, pData->UnitDiskNo }; XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_RESERVED6, "LSINFOX_PRIMARY_USAGE_MESSAGE: %02X:%02X:%02X:%02X:%02X:%02X@%d\n", pData->NetDiskNode[0], pData->NetDiskNode[1], pData->NetDiskNode[2], pData->NetDiskNode[3], pData->NetDiskNode[4], pData->NetDiskNode[5], pData->UnitDiskNo); CNdasLogicalDevicePtr pLogDevice = pGetNdasLogicalDevice(unitDeviceId); if (CNdasLogicalDeviceNullPtr == pLogDevice) { // Discard message return; } switch (pLogDevice->GetStatus()) { case NDAS_LOGICALDEVICE_STATUS_MOUNTED: case NDAS_LOGICALDEVICE_STATUS_MOUNT_PENDING: case NDAS_LOGICALDEVICE_STATUS_UNMOUNT_PENDING: break; default: // // Otherwise, discard message // return; } ACCESS_MASK mountedAcces = pLogDevice->GetMountedAccess(); CONST DWORD cbPacket = sizeof(LSINFOX_HEADER) + sizeof(LSINFOX_NDASDEV_USAGE_REPLY) + NDASIX_MAX_HOSTNAME_LEN * sizeof(WCHAR); BYTE pbPacket[cbPacket] = {0}; PLSINFOX_HEADER pHeader = reinterpret_cast<PLSINFOX_HEADER>(pbPacket); PLSINFOX_NDASDEV_USAGE_REPLY pUsageReply = reinterpret_cast<PLSINFOX_NDASDEV_USAGE_REPLY>( pbPacket + sizeof(LSINFOX_HEADER)); // // Header // CONST BYTE NdasIxProtocolName[] = INFOX_DATAGRAM_PROTOCOL; ::CopyMemory( pHeader->Protocol, NdasIxProtocolName, sizeof(NdasIxProtocolName)); pHeader->LSInfoXMajorVersion = INFOX_DATAGRAM_MAJVER; pHeader->LSInfoXMinorVersion = INFOX_DATAGRAM_MINVER; pHeader->OsMajorType = OSTYPE_WINDOWS; DWORD dwOSMajorVersion, dwOSMinorVersion; pGetOSVersion(&dwOSMajorVersion, &dwOSMinorVersion); USHORT usLfsOsMinorType = pInfoXGetOSType(dwOSMajorVersion, dwOSMinorVersion); pHeader->OsMinorType = usLfsOsMinorType; pHeader->Type = LSINFOX_PRIMARY_UPDATE_MESSAGE | LSINFOX_TYPE_REPLY; pHeader->MessageSize = cbPacket; // // Body // LPX_ADDRESS localLpxAddress = sock.GetBoundAddr()->LpxAddress; pUsageReply->HostLanAddr.AddressType = LSNODE_ADDRTYPE_ETHER; pUsageReply->HostLanAddr.AddressLen = LPXADDR_NODE_LENGTH; ::CopyMemory( pUsageReply->HostLanAddr.Address, localLpxAddress.Node, LPXADDR_NODE_LENGTH); WCHAR wszHostName[MAX_HOSTNAME_LEN] = {0}; USHORT hostNameType = LSNODENAME_DNSFULLYQ; DWORD cchHostName = MAX_HOSTNAME_LEN; BOOL fSuccess = ::GetComputerNameExW( ComputerNameDnsFullyQualified, wszHostName, &cchHostName); if (!fSuccess) { hostNameType = LSNODENAME_NETBOIS; cchHostName = MAX_HOSTNAME_LEN; fSuccess = ::GetComputerNameExW( ComputerNameNetBIOS, wszHostName, &cchHostName); } if (!fSuccess) { hostNameType = LSNODENAME_UNKNOWN; cchHostName = 0; } pUsageReply->HostNameType = hostNameType; pUsageReply->HostNameLength = static_cast<USHORT>(cchHostName); ::CopyMemory( pUsageReply->HostName, wszHostName, cchHostName * sizeof(WCHAR)); // // LPX Address.Node is an adapter address. // const DWORD cbAdapterAddress = 6; BYTE pAdapterAddress[cbAdapterAddress] = {0}; ::CopyMemory(pAdapterAddress, localLpxAddress.Node, 6); DWORD cbIpAddress = 14; // TODO: why is this 14? BYTE pPrimaryIpAddress[14] = {0}; fSuccess = pGetAdapterPrimaryIpAddress( cbAdapterAddress, pAdapterAddress, &cbIpAddress, pPrimaryIpAddress); fSuccess = FALSE; if (!fSuccess) { XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_WARNING, "Getting Primary IP Address failed, if=%s, error=0x%X\n", CSockLpxAddr(sock.GetBoundAddr()).ToStringA(), GetLastError()); pUsageReply->HostWanAddr.AddressLen = 0; pUsageReply->HostWanAddr.AddressType = LSNODE_ADDRTYPE_IP; ::ZeroMemory(pUsageReply->HostWanAddr.Address, LSNODE_ADDR_LENGTH); } else { pUsageReply->HostWanAddr.AddressLen = (USHORT) cbIpAddress; pUsageReply->HostWanAddr.AddressType = LSNODE_ADDRTYPE_IP; XTLASSERT(cbIpAddress <= LSNODE_ADDR_LENGTH); ::CopyMemory( pUsageReply->HostWanAddr.Address, pPrimaryIpAddress, cbIpAddress); } // // Software Versions, status, etc // if (mountedAcces & GENERIC_READ) { pUsageReply->AccessRight |= LSSESSION_ACCESS_READ; } if (mountedAcces & GENERIC_WRITE) { pUsageReply->AccessRight |= LSSESSION_ACCESS_WRITE; } pUsageReply->NetDiskPort = NDAS_DEVICE_LPX_PORT; pUsageReply->UnitDiskNo = static_cast<USHORT>(unitDeviceId.UnitNo); pUsageReply->UsageID = 0; pUsageReply->SWMajorVersion = NDASIX_VERSION_MAJOR; pUsageReply->SWMinorVersion = NDASIX_VERSION_MINOR; pUsageReply->SWBuildNumber = NDASIX_VERSION_BUILD; pUsageReply->NDFSCompatVersion = m_NDFSVersion.wMajor; pUsageReply->NDFSVersion = m_NDFSVersion.wMinor; DWORD cbSent = 0; fSuccess = sock.SendToSync(pRemoteAddr, cbPacket, pbPacket, 0, &cbSent); if (!fSuccess) { XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_ERROR, "SendToSync failed, bytes=%d, error=0x%X\n", cbPacket, GetLastError()); return; } return; }
BOOL CNdasIXBcast::BroadcastStatus() { NDASSCSI_QUERY_INFO_DATA NdasScsiQuery; NDSCIOCTL_PRIMUNITDISKINFO LurInformation; CNdasLogicalDeviceManager& manager = pGetNdasLogicalDeviceManager(); CNdasLogicalDeviceVector logDevices; manager.Lock(); manager.GetItems(logDevices); manager.Unlock(); for (CNdasLogicalDeviceVector::const_iterator itr = logDevices.begin(); itr != logDevices.end(); ++itr) { CNdasLogicalDevicePtr pLogDevice = *itr; if (NDAS_LOGICALDEVICE_STATUS_MOUNTED != pLogDevice->GetStatus()) { continue; } CONST NDAS_LOCATION& location = pLogDevice->GetNdasLocation(); NdasScsiQuery.InfoClass = NdscPrimaryUnitDiskInformation; NdasScsiQuery.Length = sizeof(NDASSCSI_QUERY_INFO_DATA); NdasScsiQuery.NdasScsiAddress.SlotNo = location; NdasScsiQuery.QueryDataLength = 0; XTL::AutoFileHandle handle = pOpenStorageDeviceByNumber( pLogDevice->GetDeviceNumberHint(), GENERIC_WRITE|GENERIC_READ); BOOL fSuccess = NdasPortCtlQueryInformation( handle, &NdasScsiQuery, sizeof(NDASSCSI_QUERY_INFO_DATA), &LurInformation, sizeof(NDSCIOCTL_PRIMUNITDISKINFO)); if (!fSuccess) { XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_ERROR, "LanscsiQueryInformation failed, slot=%d, error=0x%X\n", location, GetLastError()); continue; } // // Broadcast a primary write access status // if (LurInformation.Lur.DeviceMode == DEVMODE_SHARED_READWRITE && !(LurInformation.Lur.EnabledFeatures & NDASFEATURE_SECONDARY)) { const DWORD cbBuffer = sizeof(LSINFOX_HEADER) + sizeof(LSINFOX_PRIMARY_UPDATE); BYTE lpbBuffer[cbBuffer] = {0}; PLSINFOX_HEADER pixHeader = reinterpret_cast<PLSINFOX_HEADER>(lpbBuffer); PLSINFOX_DATA pixData = reinterpret_cast<PLSINFOX_DATA>(lpbBuffer + sizeof(LSINFOX_HEADER)); // // CAUTION: InfoExchange Protocol uses little-endian (Intel) // // // Header // UCHAR ixProtocolName[4] = INFOX_DATAGRAM_PROTOCOL; ::CopyMemory(pixHeader->Protocol, ixProtocolName, 4); pixHeader->LSInfoXMajorVersion = INFOX_DATAGRAM_MAJVER; pixHeader->LSInfoXMinorVersion = INFOX_DATAGRAM_MINVER; pixHeader->OsMajorType = OSTYPE_WINDOWS; DWORD dwOSMajorVersion, dwOSMinorVersion; pGetOSVersion(&dwOSMajorVersion, &dwOSMinorVersion); USHORT usLfsOsMinorType = pInfoXGetOSType(dwOSMajorVersion, dwOSMinorVersion); pixHeader->OsMinorType = usLfsOsMinorType; pixHeader->Type = LSINFOX_PRIMARY_UPDATE_MESSAGE; pixHeader->MessageSize = cbBuffer; // // Data // // primary node is dependent to each interface pixData->Update.PrimaryNode; pixData->Update.PrimaryPort = LPXRP_LFS_PRIMARY; pixData->Update.SWMajorVersion = NDASIX_VERSION_MAJOR; // TODO: Change these values pixData->Update.SWMinorVersion = NDASIX_VERSION_MINOR; pixData->Update.SWBuildNumber = NDASIX_VERSION_BUILD; pixData->Update.NDFSCompatVersion = m_NDFSVersion.wMajor; pixData->Update.NDFSVersion = m_NDFSVersion.wMinor; // // NetDisk Node is a property of each unit device // pixData->Update.NetDiskNode; // // We have fixed the port // (CNdasDevice does not store Port Number internally) // Do not try to retrieve from GetRemoteLpxAddress() // pixData->Update.NetDiskPort = NDAS_DEVICE_LPX_PORT; // // Unit Disk Number is a property of each unit device // pixData->Update.UnitDiskNo; // // pLogDevice->GetStatus() // for (DWORD n = 0; n < pLogDevice->GetUnitDeviceCount(); ++n) { // // Actually, we should traverse the real entry // from the device registrar. // However, here we do the shortcut for using NDAS device id // and fixed NetDiskPort, etc. // NDAS_UNITDEVICE_ID unitDeviceId = pLogDevice->GetUnitDeviceID(n); C_ASSERT(sizeof(pixData->Update.NetDiskNode) == sizeof(unitDeviceId.DeviceId.Node)); ::CopyMemory( pixData->Update.NetDiskNode, unitDeviceId.DeviceId.Node, sizeof(pixData->Update.NetDiskNode)); pixData->Update.UnitDiskNo = static_cast<USHORT>(unitDeviceId.UnitNo); // // Broadcast the data to every interface // for (DWORD i = 0; i < MAX_SOCKETLPX_INTERFACE; ++i) { if (INVALID_SOCKET != (SOCKET) m_senders[i]) { // // Fill the Primary Node (LPX Address Node) // LPX_ADDRESS localLpxAddress = m_senders[i].GetBoundAddr()->LpxAddress; C_ASSERT(sizeof(pixData->Update.PrimaryNode) == sizeof(localLpxAddress.Node)); ::CopyMemory( pixData->Update.PrimaryNode, localLpxAddress.Node, sizeof(pixData->Update.PrimaryNode)); // // Send the data // DWORD cbSent = 0; BOOL fSuccess = m_senders[i].SendToSync( &NDASIX_BCAST_ADDR, cbBuffer, lpbBuffer, 0, &cbSent); if (!fSuccess) { XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_ERROR, "SendToSync failed, bytes=%d, error=0x%X\n", cbBuffer, GetLastError()); } } // end if } // for each local LPX address } // for each unit device } // if the logical device has a primary write access. } // for each logical device return TRUE; }
BOOL CNdasIXBcast::BroadcastStatus() { BUSENUM_QUERY_INFORMATION BusEnumQuery; BUSENUM_INFORMATION BusEnumInformation; CNdasLogicalDeviceManager* pLdm = pGetNdasLogicalDeviceManager(); CNdasLogicalDeviceCollection coll; pLdm->Lock(); pLdm->GetItems(coll); pLdm->Unlock(); for (CNdasLogicalDeviceCollection::const_iterator itr = coll.begin(); itr != coll.end(); ++itr) { CNdasLogicalDevice* pLogDevice = *itr; if (NDAS_LOGICALDEVICE_STATUS_MOUNTED != pLogDevice->GetStatus()) { continue; } CONST NDAS_SCSI_LOCATION& location = pLogDevice->GetNdasScsiLocation(); BusEnumQuery.InfoClass = INFORMATION_PDO; BusEnumQuery.Size = sizeof(BUSENUM_QUERY_INFORMATION); BusEnumQuery.SlotNo = location.SlotNo; BOOL fSuccess = LsBusCtlQueryInformation( &BusEnumQuery, sizeof(BUSENUM_QUERY_INFORMATION), &BusEnumInformation, sizeof(BUSENUM_INFORMATION)); if (!fSuccess) { DPErrorEx(_FT("LanscsiQueryInformation failed at slot %d: "), location.SlotNo); continue; } // // Broadcast a primary write access status // if (ND_ACCESS_ISRW(BusEnumInformation.PdoInfo.GrantedAccess)) { const DWORD cbBuffer = sizeof(LSINFOX_HEADER) + sizeof(LSINFOX_PRIMARY_UPDATE); BYTE lpbBuffer[cbBuffer] = {0}; PLSINFOX_HEADER pixHeader = reinterpret_cast<PLSINFOX_HEADER>(lpbBuffer); PLSINFOX_DATA pixData = reinterpret_cast<PLSINFOX_DATA>(lpbBuffer + sizeof(LSINFOX_HEADER)); // // CAUTION: InfoExchange Protocol uses little-endian (Intel) // // // Header // UCHAR ixProtocolName[4] = INFOX_DATAGRAM_PROTOCOL; ::CopyMemory(pixHeader->Protocol, ixProtocolName, 4); pixHeader->LSInfoXMajorVersion = INFOX_DATAGRAM_MAJVER; pixHeader->LSInfoXMinorVersion = INFOX_DATAGRAM_MINVER; pixHeader->OsMajorType = OSTYPE_WINDOWS; DWORD dwOSMajorVersion, dwOSMinorVersion; pGetOSVersion(&dwOSMajorVersion, &dwOSMinorVersion); USHORT usLfsOsMinorType = pInfoXGetOSType(dwOSMajorVersion, dwOSMinorVersion); pixHeader->OsMinorType = usLfsOsMinorType; pixHeader->Type = LSINFOX_PRIMARY_UPDATE_MESSAGE; pixHeader->MessageSize = cbBuffer; // // Data // // primary node is dependent to each interface pixData->Update.PrimaryNode; pixData->Update.PrimaryPort = LPXRP_LFS_PRIMARY; pixData->Update.SWMajorVersion = NDASIX_VERSION_MAJOR; // TODO: Change these values pixData->Update.SWMinorVersion = NDASIX_VERSION_MINOR; pixData->Update.SWBuildNumber = NDASIX_VERSION_BUILD; pixData->Update.NDFSCompatVersion = m_NDFSVersion.wMajor; pixData->Update.NDFSVersion = m_NDFSVersion.wMinor; // // NetDisk Node is a property of each unit device // pixData->Update.NetDiskNode; // // We have fixed the port // (CNdasDevice does not store Port Number internally) // Do not try to retrieve from GetRemoteLpxAddress() // pixData->Update.NetDiskPort = NDAS_DEVICE_LPX_PORT; // // Unit Disk Number is a property of each unit device // pixData->Update.UnitDiskNo; // // pLogDevice->GetStatus() // for (DWORD n = 0; n < pLogDevice->GetUnitDeviceCount(); ++n) { // // Actually, we should traverse the real entry // from the device registrar. // However, here we do the shortcut for using NDAS device id // and fixed NetDiskPort, etc. // NDAS_UNITDEVICE_ID unitDeviceId = pLogDevice->GetUnitDeviceID(n); _ASSERTE(sizeof(pixData->Update.NetDiskNode) == sizeof(unitDeviceId.DeviceId)); ::CopyMemory( pixData->Update.NetDiskNode, unitDeviceId.DeviceId.Node, sizeof(pixData->Update.NetDiskNode)); pixData->Update.UnitDiskNo = unitDeviceId.UnitNo; // // Broadcast the data to every interface // for (DWORD i = 0; i < MAX_SOCKETLPX_INTERFACE; ++i) { if (INVALID_SOCKET != (SOCKET) m_senders[i]) { // // Fill the Primary Node (LPX Address Node) // LPX_ADDRESS localLpxAddress = m_senders[i].GetBoundAddr()->LpxAddress; _ASSERTE(sizeof(pixData->Update.PrimaryNode) == sizeof(localLpxAddress.Node)); ::CopyMemory( pixData->Update.PrimaryNode, localLpxAddress.Node, sizeof(pixData->Update.PrimaryNode)); // // Send the data // DWORD cbSent = 0; BOOL fSuccess = m_senders[i].SendToSync( &NDASIX_BCAST_ADDR, cbBuffer, lpbBuffer, 0, &cbSent); if (!fSuccess) { DPWarningEx(_FT("Sending a packet failed: ")); } } // end if } // for each local LPX address } // for each unit device } // if the logical device has a primary write access. } // for each logical device return TRUE; }