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
-- v11: 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..8d48289a27c 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; + } + 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 ) + return ERROR_GEN_FAILURE; + + + /* 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; + } + } + } + Sleep(1); + heap_free(table); + } + + return ERROR_NOT_FOUND; }
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index da3a06d54ca..05ef0727ba7 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=150130
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000002DF0102, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032