Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/platform/ethernet/gige/GVCPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ SOCKET GVCPClient::openClientSocket(SOCKADDR_IN addr) {
#if(defined(__linux__) || defined(OS_IOS) || defined(OS_MACOS) || defined(__ANDROID__))
//addr.sin_addr.s_addr = inet_addr("0.0.0.0");
#endif
LOG_INTVL(LOG_INTVL_OBJECT_TAG + "GVCP bind", MAX_LOG_INTERVAL, spdlog::level::debug, "bind {}:{}", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
LOG_INTVL(LOG_INTVL_OBJECT_TAG + "GVCP bind", MAX_LOG_INTERVAL, spdlog::level::debug, "bind {}:{}", std::string(inet_ntoa(addr.sin_addr)), ntohs(addr.sin_port));
err = bind(sock, (SOCKADDR *)&addr, sizeof(SOCKADDR));
if(err == SOCKET_ERROR) {
return 0;
Expand Down
108 changes: 66 additions & 42 deletions src/platform/ethernet/socket/VendorTCPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,57 +48,81 @@ VendorTCPClient::VendorTCPClient(std::string localAddress, std::string localMac,
}

void VendorTCPClient::checkLocalIP() {
#if(defined(WIN32) || defined(_WIN32) || defined(WINCE))
unsigned int a, b, c, d;
if(sscanf(localAddress_.c_str(), "%u.%u.%u.%u", &a, &b, &c, &d) == 4) {
if((a == 10) || // 10.0.0.0 - 10.255.255.255
(a == 172 && b >= 16 && b <= 31) || // 172.16.0.0 - 172.31.255.255
(a == 192 && b == 168)) { // 192.168.0.0 - 192.168.255.255
isValidIP_ = true;
}
}
#if (defined(WIN32) || defined(_WIN32) || defined(WINCE))
// If we already have a private localAddress_ provided, try to keep it
auto isPrivate = [](const std::string &ip) -> bool {
unsigned a,b,c,d;
if (sscanf(ip.c_str(), "%u.%u.%u.%u", &a,&b,&c,&d) != 4) return false;
return (a == 10) || (a == 172 && b >= 16 && b <= 31) || (a == 192 && b == 168);
};

// Parse destination IP for subnet matching
in_addr destAddr{};
bool hasDest = (inet_pton(AF_INET, address_.c_str(), &destAddr) == 1);

// Enumerate adapter by MAC and pick the right IP
IP_ADAPTER_INFO adapterInfo[16];
DWORD bufLen = sizeof(adapterInfo);
DWORD dwRetVal = GetAdaptersInfo(adapterInfo, &bufLen);
if (dwRetVal == ERROR_SUCCESS) {
PIP_ADAPTER_INFO pAdapterInfo = adapterInfo;
while (pAdapterInfo) {
// Build MAC string for comparison
std::ostringstream oss;
for (int i = 0; i < 6; ++i) {
if (i > 0) oss << ":";
oss << std::setw(2) << std::setfill('0') << std::hex << (int)pAdapterInfo->Address[i];
}
std::string currentMac = oss.str();

if (currentMac == localMac_) {
// First: if caller-specified localAddress_ exists on this adapter, keep it
if (!localAddress_.empty()) {
for (PIP_ADDR_STRING p = &pAdapterInfo->IpAddressList; p; p = p->Next) {
if (localAddress_ == p->IpAddress.String) {
isValidIP_ = isPrivate(localAddress_);
return; // keep caller-provided address
}
}
}

if(!isValidIP_) {
localAddress_ = "";
IP_ADAPTER_INFO adapterInfo[16]; // Buffer to hold adapter info
DWORD bufLen = sizeof(adapterInfo);

// Get the network adapter information
DWORD dwRetVal = GetAdaptersInfo(adapterInfo, &bufLen);
if(dwRetVal == ERROR_SUCCESS) {
// Loop through all the adapters
PIP_ADAPTER_INFO pAdapterInfo = adapterInfo;
while(pAdapterInfo) {
// Convert MAC address to string format
std::ostringstream oss;
for(int i = 0; i < 6; ++i) {
if(i > 0)
oss << ":";
oss << std::setw(2) << std::setfill('0') << std::hex << (int)pAdapterInfo->Address[i];
// Second: try to pick an IP on same subnet as destination
if (hasDest) {
for (PIP_ADDR_STRING p = &pAdapterInfo->IpAddressList; p; p = p->Next) {
in_addr ip{}, mask{};
if (inet_pton(AF_INET, p->IpAddress.String, &ip) != 1) continue;
if (inet_pton(AF_INET, p->IpMask.String, &mask) != 1) continue;
if ( (ip.S_un.S_addr & mask.S_un.S_addr) == (destAddr.S_un.S_addr & mask.S_un.S_addr) ) {
localAddress_ = p->IpAddress.String;
isValidIP_ = isPrivate(localAddress_);
return;
}
}
}

// Compare MAC address with the input MAC address
std::string currentMac = oss.str();
if(currentMac == localMac_) {
// If MAC matches, get the associated IP address (return the first one)
PIP_ADDR_STRING pIpAddr = &pAdapterInfo->IpAddressList;
if(pIpAddr) {
localAddress_ = pIpAddr->IpAddress.String; // Return the first IP address
// Third: fallback to the first private IPv4 on this adapter
for (PIP_ADDR_STRING p = &pAdapterInfo->IpAddressList; p; p = p->Next) {
if (isPrivate(p->IpAddress.String)) {
localAddress_ = p->IpAddress.String;
isValidIP_ = true;
return;
}
break; // If no IP address found, break out of the loop
}
pAdapterInfo = pAdapterInfo->Next;
}
}

if(sscanf(localAddress_.c_str(), "%u.%u.%u.%u", &a, &b, &c, &d) == 4) {
if((a == 10) || // 10.0.0.0 - 10.255.255.255
(a == 172 && b >= 16 && b <= 31) || // 172.16.0.0 - 172.31.255.255
(a == 192 && b == 168)) { // 192.168.0.0 - 192.168.255.255
isValidIP_ = true;
// No suitable IP; clear to let OS decide
localAddress_.clear();
isValidIP_ = false;
return;
}
pAdapterInfo = pAdapterInfo->Next;
}
}

// Adapter not found or error: if caller provided a private IP, keep it; otherwise clear
isValidIP_ = isPrivate(localAddress_);
if (!isValidIP_) localAddress_.clear();
#else
// Non-Windows: keep current behavior (if any)
#endif
}

Expand Down