Returns MAC address by: - search local interfaces, or - send UDP packed that does not need linux privilege, then search local cache
solve https://bugs.winehq.org/show_bug.cgi?id=9418
files updated - /dlls/iphlpapi/iphlpapi_main.c - /dlls/iphlpapi/tests/iphlpapi.c
-- v10: iphlpapi.c: Add SendARP
From: thi garlet <galet at gmail>
Returns MAC address by: search local interfaces, or send UDP packed that does not need linux privilege, then search local cache solves https://bugs.winehq.org/show_bug.cgi?id=9418
files updated /dlls/iphlpapi/iphlpapi_main.c /dlls/iphlpapi/tests/iphlpapi.c --- dlls/iphlpapi/iphlpapi_main.c | 115 +++++++++++++++++++++++++++++++-- dlls/iphlpapi/tests/iphlpapi.c | 31 +++++++++ 2 files changed, 140 insertions(+), 6 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 172afbd62b8..cf216c27a93 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -3964,15 +3964,118 @@ DWORD WINAPI NotifyUnicastIpAddressChange(ADDRESS_FAMILY family, PUNICAST_IPADDR * RETURNS * Success: NO_ERROR * Failure: error code from winerror.h - * - * FIXME - * Stub, returns ERROR_NOT_SUPPORTED. */ DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen) { - FIXME("(DestIP 0x%08lx, SrcIP 0x%08lx, pMacAddr %p, PhyAddrLen %p): stub\n", - DestIP, SrcIP, pMacAddr, PhyAddrLen); - return ERROR_NOT_SUPPORTED; + int i=3, time_out=420; + ULONG size=16000; + struct sockaddr_in dst, src; + struct WSAData wd; + SOCKET s; + MIB_IPNETTABLE *table = NULL; + PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; + PIP_ADAPTER_ADDRESSES pInterfaces = NULL, pCurrInterface = NULL; + + if( DestIP == 0 ) + return ERROR_INVALID_PARAMETER; + if( pMacAddr == NULL || PhyAddrLen == NULL ) + return ERROR_INVALID_USER_BUFFER; + if( (*PhyAddrLen) < 6 ) + return ERROR_BUFFER_OVERFLOW; + + // copy DestIP to MAC, in case MAC cant be found + (*PhyAddrLen) = 6; + memcpy(pMacAddr, &DestIP, 4); + memcpy(pMacAddr+1, &DestIP, 2); + + + // first, check if DestIP is a local adapter + do + { + pInterfaces = (IP_ADAPTER_ADDRESSES *) heap_alloc_zero(size); + if (pInterfaces == NULL) + { + ERR("Memory allocation failed for IP_ADAPTER_ADDRESSES struct"); + return ERROR_BUFFER_OVERFLOW; + } + + i = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST + GAA_FLAG_SKIP_MULTICAST + + GAA_FLAG_SKIP_DNS_SERVER + GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, pInterfaces, &size); + + if (i == NO_ERROR ) + { + pCurrInterface = pInterfaces; + while ( pCurrInterface ) + { + + pUnicast = pCurrInterface->FirstUnicastAddress; + while ( pUnicast ) + { + if ( DestIP == ((struct sockaddr_in *) + pUnicast->Address.lpSockaddr)->sin_addr.s_addr ) + { + memcpy(pMacAddr, pCurrInterface->PhysicalAddress, 6); + heap_free(pInterfaces); + return NO_ERROR; // 0 + } + pUnicast = pUnicast->Next; + } + pCurrInterface = pCurrInterface->Next; + } + } + heap_free(pInterfaces); + + } while ( i == ERROR_BUFFER_OVERFLOW && i-- > 0 ); + + + // prepare config, to send an UDP packed instead of privileged ARP + src.sin_family = AF_INET; + src.sin_addr.s_addr = SrcIP; + src.sin_port = 10123; + dst.sin_family = AF_INET; + dst.sin_addr.s_addr = DestIP; + dst.sin_port = 10123; + + // send UDP + if( WSAStartup( MAKEWORD( 2, 2 ), &wd ) != 0 ) + return ERROR_NOT_SUPPORTED; + s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + bind( s, (SOCKADDR *) &src, sizeof(src) ); + i = sendto( s, (const char *) &time_out, 4, 0, (SOCKADDR *) &dst, sizeof(dst) ); + closesocket(s); + WSACleanup(); + if( i == SOCKET_ERROR ) // -1 + return ERROR_GEN_FAILURE; // 31 + + + // search cached arp table + size = 16000; + while( time_out-- > 0 ) + { + table = heap_alloc_zero(size); + if( table == NULL ) + { + ERR("Memory allocation failed for IpNetTable struct"); + return ERROR_BUFFER_OVERFLOW; + } + + if( GetIpNetTable( table, &size, 0 ) == NO_ERROR ) + { + for (i = 0; i < table->dwNumEntries; ++i) + { + if( table->table[i].dwAddr == DestIP ) + { + memcpy(pMacAddr, table->table[i].bPhysAddr, 6); + heap_free(table); + return NO_ERROR; // 0 + } + } + } + Sleep(1); + heap_free(table); + } + + return ERROR_NOT_FOUND; // 1168 }
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index da3a06d54ca..1903527edf5 100644 --- a/dlls/iphlpapi/tests/iphlpapi.c +++ b/dlls/iphlpapi/tests/iphlpapi.c @@ -3098,6 +3098,36 @@ static void test_compartments(void) ok(id == NET_IF_COMPARTMENT_ID_PRIMARY, "got %u\n", id); }
+static void test_SendARP(void) +{ + DWORD apiReturn; + ULONG dwSize = 0; + ULONG MacAddr[2]={0,0}; + + apiReturn = SendARP( 0, 0, MacAddr, &dwSize); + if (apiReturn == ERROR_NOT_SUPPORTED) { + skip("SendARP is not supported\n"); + return; + } + ok(apiReturn == ERROR_INVALID_PARAMETER, + "SendARP(inet_addr('255.255.255.255'), 0, MacAddr, &dwSize) returned %ld, expected ERROR_INVALID_PARAMETER\n", + apiReturn); + + apiReturn = SendARP( inet_addr("255.255.255.255"), 0, MacAddr, &dwSize); + ok(apiReturn == ERROR_BUFFER_OVERFLOW, + "SendARP(inet_addr('255.255.255.255'), 0, MacAddr, &dwSize=0) returned %ld, expected ERROR_BUFFER_OVERFLOW\n", + apiReturn); + + dwSize = 6; + apiReturn = SendARP( inet_addr("255.255.255.255"), 0, MacAddr, &dwSize); + if (apiReturn == ERROR_NOT_FOUND) { + trace( "SendARP(inet_addr('255.255.255.255'), 0, MacAddr, &dwSize) did not found a mac address\n" ); + } else { + trace( "SendARP(inet_addr('255.255.255.255'), 0, MacAddr, &dwSize) returned '%lu' backwarded mac: %lx%lX\n", + apiReturn, MacAddr[1], MacAddr[0] ); + } +} + START_TEST(iphlpapi) { WSADATA wsa_data; @@ -3139,6 +3169,7 @@ START_TEST(iphlpapi) test_NotifyUnicastIpAddressChange(); test_ConvertGuidToString(); test_compartments(); + test_SendARP(); freeIPHlpApi(); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150108
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: win.c:4070: Test failed: Expected active window 000000000262016E, got 0000000000000000. win.c:4071: Test failed: Expected focus window 000000000262016E, got 0000000000000000.
Please remove the c++ stlye comments and change them to c style comments.