Skip to content

Commit

Permalink
new GetLocalIpAddress() function
Browse files Browse the repository at this point in the history
- used also to implement GetLocalMacAddress() on POSIX systems
  • Loading branch information
Arnaud Bouchez committed Nov 30, 2023
1 parent 4129224 commit e4fa1f3
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/mormot.commit.inc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
'2.1.6337'
'2.1.6338'
34 changes: 29 additions & 5 deletions src/net/mormot.net.sock.pas
Original file line number Diff line number Diff line change
Expand Up @@ -574,13 +574,18 @@ function GetMacAddressesText(WithoutName: boolean = true;
// on POSIX, implementing ARP sadly requires root rights
// - return the MAC address as a 12 hexa chars ('0050C204C80A' e.g.)
function GetRemoteMacAddress(const IP: RawUtf8): RawUtf8;
{$endif OSWINDOWS}

/// get the local MAC address used to reach a computer, from its IP Address
/// get the local MAC address used to reach a computer, from its IP or Host name
// - return the local interface as a TMacAddress, with all its available info
// - only works under Windows, which features a GetBestInterface() API
function GetLocalMacAddress(const IP: RawUtf8;
var Mac: TMacAddress): boolean;
{$endif OSWINDOWS}
// - under Windows, will call the GetBestInterface() API
// - on POSIX, calls GetLocalIpAddress() then create and discard a SOCK_DGRAM
function GetLocalMacAddress(const Remote: RawUtf8; var Mac: TMacAddress): boolean;

/// get the local IP address used to reach a computer, from its IP Address
// - will create a SOCK_DGRAM socket over the supplied IP, and check
// the local socket address created
function GetLocalIpAddress(const IP: RawUtf8): RawUtf8;

/// retrieve all DNS (Domain Name Servers) addresses known by the Operating System
// - on POSIX, return "nameserver" from /etc/resolv.conf unless usePosixEnv is set
Expand Down Expand Up @@ -3156,6 +3161,25 @@ function _GetSystemMacAddress: TRawUtf8DynArray;
SetLength(result, n);
end;

function GetLocalIpAddress(const IP: RawUtf8): RawUtf8;
var
addr: TNetAddr;
sock: TNetSocket;
begin
result := '';
if addr.SetFrom(IP, '9', nlUdp) <> nrOk then // discard port
exit;
sock := addr.NewSocket(nlUdp);
if sock <> nil then
try
if (connect(sock.Socket, @addr, addr.Size) = NO_ERROR) and
(sock.GetName(addr) = nrOk) then
addr.IP(result);
finally
sock.Close;
end;
end;

var
DnsCache: record
Safe: TLightLock;
Expand Down
20 changes: 20 additions & 0 deletions src/net/mormot.net.sock.posix.inc
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,26 @@ end;

{$endif USE_IFADDRS}

function GetLocalMacAddress(const IP: RawUtf8; var Mac: TMacAddress): boolean;
var
local: RawUtf8;
all: TMacAddressDynArray;
i: PtrInt;
begin
result := false;
local := GetLocalIpAddress(IP);
if local = '' then
exit;
all := GetMacAddresses;
for i := 0 to high(all) do
if all[i].IP = local then
begin
mac := all[i];
result := true;
break;
end;
end;

function _GetDnsAddresses(usePosixEnv, getAD: boolean): TRawUtf8DynArray;
var
resolv, one: RawUtf8;
Expand Down
20 changes: 11 additions & 9 deletions src/net/mormot.net.sock.windows.inc
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,7 @@ type

var
iphlpapiDll: THandle;

// some iphlpapi.dll late-binded API via DelayedProc()
GetIpAddrTable: function (pIpAddrTable: PMIB_IPADDRTABLE;
var pdwSize: DWORD; bOrder: BOOL): DWORD; stdcall;
Expand Down Expand Up @@ -736,10 +737,11 @@ const
GAA_FLAG_SKIP_DNS_SERVER = $8;
GAA_FLAG_INCLUDE_PREFIX = $10;
GAA_FLAG_SKIP_FRIENDLY_NAME = $20;
// Vista+
// below flags are only available on Windows Vista and later
GAA_FLAG_INCLUDE_WINS_INFO = $40;
GAA_FLAG_INCLUDE_GATEWAYS = $80;
GAA_FLAG_INCLUDE_ALL_INTERFACES = $100;

IfOperStatusUp = 1;
IfOperStatusDown = 2;
IF_TYPE_SOFTWARE_LOOPBACK = 24;
Expand Down Expand Up @@ -867,18 +869,14 @@ type
end;
PFIXED_INFO = ^FIXED_INFO;


var
// some iphlpapi.dll late-binded APIs via DelayedProc()
// some iphlpapi.dll late-binded API via DelayedProc()
GetAdaptersAddresses: function(Family: ULONG; Flags: DWORD; Reserved: pointer;
pAdapterAddresses: PIP_ADAPTER_ADDRESSES; pOutBufLen: PULONG): DWORD; stdcall;

pAdapterAddresses: PIP_ADAPTER_ADDRESSES; pOutBufLen: PULONG): DWORD; stdcall;
SendARP: function(DestIp: DWORD; srcIP: DWORD; pMacAddr: pointer;
PhyAddrLen: Pointer): DWORD; stdcall;

GetNetworkParams: function(pFixedInfo: PFIXED_INFO;
pOutBufLen: PULONG): DWORD; stdcall;

GetBestInterface: function(dwDestAddrIPv4: cardinal;
var pdwBestIfIndex: DWORD): DWORD; stdcall;

Expand Down Expand Up @@ -1034,15 +1032,19 @@ begin
until p = nil;
end;

function GetLocalMacAddress(const IP: RawUtf8;
function GetLocalMacAddress(const Remote: RawUtf8;
var Mac: TMacAddress): boolean;
var
addr: TNetAddr;
dwRemoteIP, ifIndex: DWORD;
all: TMacAddressDynArray;
i: PtrInt;
begin
result := false;
if NetIsIP4(pointer(IP), @dwRemoteIP) and
if not addr.SetFromIP4(Remote, {nolookup=}false) then
exit;
dwRemoteIP := addr.IP4;
if (dwRemoteIP <> 0) and
DelayedProc(GetBestInterface, iphlpapiDll,
'iphlpapi.dll', 'GetBestInterface') and
(GetBestInterface(dwRemoteIP, ifIndex) = NO_ERROR) then
Expand Down

0 comments on commit e4fa1f3

Please sign in to comment.