robertw
robertw

Reputation: 734

How to get IP which is using for internet connection in Delphi

I have a few network adapters in my system:

When I'm only connected to WiFI - my IP address is 192.168.1.101 (gateway 192.168.1.1) Activating VPN connections brings me next IP's (ex. (PPTP) 192.168.90.101, (OpenVPN) 10.9.0.6)

Question is: How to determine which IP address is "default" for internet connection?

Scenarios:

No 1 - only WiFi - ER (Expected Result): 192.168.1.101

No 2 - WiFi + PPTP (with "Use default gateway on remote network") - ER: 192.168.90.101

No 3 - WiFi + PPTP (without "Use default gateway on remote network") - ER: 192.168.1.101

No 4 - WiFi + OpenVPN - ER: 192.168.1.101

And so on...

Btw. IP from OpenVPN is never returned. This network doesn't route internet connections.

When I use tracert - I can read this information looking on what is first entry in result. But I have to get this information using Delphi or external library used from Delphi app.

I'm using Delphi XE3.

Any ideas? Thanks for help!

PS. Get information about the installed network adapters I tried this solution, but there is no info that NIC is default for internet.

Best regards, Robert

Upvotes: 3

Views: 3620

Answers (3)

Ashley West
Ashley West

Reputation: 53

Open a TidUDPClient and TidUDPServer both with broadcast enabled and with the same port number. Send out a recognizable message on 255.255.255.255 and when it bounces back read the PeerIP from the returned TidSocketHandle.

Upvotes: 2

Sir Rufo
Sir Rufo

Reputation: 19096

You can retrieve the routing information by route print from the command prompt.

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0     192.168.69.1    192.168.69.15     20
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    306
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    306
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    306
     192.168.69.0    255.255.255.0         On-link     192.168.69.15    276
    192.168.69.15  255.255.255.255         On-link     192.168.69.15    276
   192.168.69.255  255.255.255.255         On-link     192.168.69.15    276
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    306
        224.0.0.0        240.0.0.0         On-link     192.168.69.15    276
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    306
  255.255.255.255  255.255.255.255         On-link     192.168.69.15    276

The "internet" has network destination 0.0.0.0. So you just have to lookup, which interface and gateway is resposible for that destination (here 192.168.69.15 via 192.168.69.1).

This information can also be retrieved by WMI Win32_IP4RouteTable.

A good starting point for WMI queries with delphi is WMI Delphi Code Creator

Upvotes: 0

fvu
fvu

Reputation: 32953

You could use this class that implements traceroute, as except for what traceroute does using ICMP (ping) packets, consulting an external service is the only reliable option I know of. If your version of Indy doesn't have TIdTraceRoute yet, you can use this code that just needs basic ICMP :

unit TraceRt; 
interface 
// ===========================================================================
// TRACEROUTE Class
// Mike Heydon Dec 2003
//
// Method
// Trace(IpAddress : string; ResultList : TStrings)
//             Returns semi-colon delimited list of ip routes to target
//             format .. IP ADDRESS; PING TIME MS; TIME TO LIVE; STATUS
//
// Properties
//             IcmpTimeOut : integer (Default = 5000ms)
//             IcmpMaxHops : integer (Default = 40)
// ===========================================================================
uses Forms, Windows, Classes, SysUtils, IdIcmpClient; 
type 
     TTraceRoute = class(TObject) 
     protected 
       procedure ProcessResponse(Status : TReplyStatus); 
       procedure AddRoute(AResponseTime : DWORD; 
                          AStatus: TReplyStatus; const AInfo: string ); 
     private 
       FIcmpTimeOut, 
       FIcmpMaxHops : integer; 
       FResults : TStringList; 
       FICMP : TIdIcmpClient; 
       FPingStart : cardinal; 
       FCurrentTTL : integer; 
       procedure PingTarget; 
     public 
       constructor Create; 
       procedure Trace(const AIpAddress : string; AResultList : TStrings); 
       property IcmpTimeOut : integer read FIcmpTimeOut write FIcmpTimeOut; 
       property IcmpMaxHops : integer read FIcmpMaxHops write FIcmpMaxHops; 
     end; 
// ---------------------------------------------------------------------------
implementation 
// ========================================
// Create the class and set defaults
// ========================================
constructor TTraceRoute.Create; 
begin 
  IcmpTimeOut := 5000; 
  IcmpMaxHops := 40; 
end; 
// =============================================
// Use Indy component to ping hops to target
// =============================================
procedure TTraceRoute.PingTarget; 
var wOldMode : DWORD; 
begin 
  Application.ProcessMessages; 
  inc(FCurrentTTL); 
  if FCurrentTTL < FIcmpMaxHops then begin 
    FICMP.TTL  := FCurrentTTL; 
    FICMP.ReceiveTimeout := FIcmpTimeOut; 
    FPingStart := GetTickCount; 
    wOldMode := SetErrorMode(SEM_FAILCRITICALERRORS); 
    try 
      FICMP.Ping; 
      ProcessResponse(FICMP.ReplyStatus); 
    except 
      FResults.Add('0.0.0.0;0;0;ERROR'); 
    end; 
    SetErrorMode(wOldMode); 
  end 
  else 
    FResults.Add('0.0.0.0;0;0;MAX HOPS EXCEEDED'); 
end; 
// ============================================================
// Add the ping reply status data to the returned stringlist
// ============================================================
procedure TTraceRoute.AddRoute(AResponseTime : DWORD; 
                               AStatus: TReplyStatus; 
                               const AInfo: string ); 
begin 
  FResults.Add(AStatus.FromIPAddress + ';' + 
               IntToStr(GetTickCount - AResponseTime) + ';' + 
               IntToStr(AStatus.TimeToLive) + ';' + AInfo); 
end; 
// ============================================================
// Process the ping reply status record and add to stringlist
// ============================================================
procedure TTraceRoute.ProcessResponse(Status : TReplyStatus); 
begin 
  case Status.ReplyStatusType of 
    // Last Leg - Terminate Trace
    rsECHO : AddRoute(FPingStart,Status,'OK'); 
    // More Hops to go - Continue Pinging
    rsErrorTTLExceeded :  begin 
                            AddRoute(FPingStart,Status,'OK'); 
                            PingTarget; 
                          end; 
    // Error conditions - Terminate Trace
    rsTimeOut : AddRoute(FPingStart,Status,'TIMEOUT'); 
    rsErrorUnreachable : AddRoute(FPingStart,Status,'UNREACHABLE'); 
    rsError : AddRoute(FPingStart,Status,'ERROR'); 
  end; 
end; 
// ======================================================
// Trace route to target IP address
// Results returned in semi-colon delimited stringlist
// IP; TIME MS; TIME TO LIVE; STATUS
// ======================================================
procedure TTraceRoute.Trace(const AIpAddress : string; 
                            AResultList : TStrings); 
begin 
  FICMP := TIdIcmpClient.Create(nil); 
  FICMP.Host := AIpAddress; 
  FResults := TStringList(AResultList); 
  FResults.Clear; 
  FCurrentTTL := 0; 
  PingTarget; 
  FICMP.Free; 
end; 
{eof} 
end.

Upvotes: 1

Related Questions