Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-10

lNet getting the local IP

22 messages · 11 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

hello,

I am searching for a way to get the local IP. I already found examples with winsock, synapse and indy. Does anyone know how to do that with lNet?

thanks,

Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho
to silvioprog

Hello,

Actually it uses both synapse (under unix) and winsock (under Windows).

What should one put in the parameter AHTTPSend: THTTPSend ? Where is this type declared?

thanks,

Felipe Monteiro de Carvalho
Andrew Brunner
to Felipe Monteiro de Carvalho: I am searching for a way to get the local IP. I already found examples with winsock,…

I just read the first line in /etc/hosts file. The first entry is the IPv4.

Felipe Monteiro de Carvalho wrote 13 lines
hello, I am searching for a way to get the local IP. I already found examples with winsock, synapse and indy. Does anyone know how to do that with lNet? thanks, -- Felipe Monteiro de Carvalho _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Sven Barth
to Andrew Brunner
Andrew Brunner wrote 11 lines
I just read the first line in /etc/hosts file. The first entry is the IPv4. On Tue, Oct 5, 2010 at 3:04 PM, Felipe Monteiro de Carvalho wrote: > hello, > > I am searching for a way to get the local IP. I already found examples > with winsock, synapse and indy. Does anyone know how to do that with > lNet? > > thanks,

Huh?! O.o

You'll only find "127.0.0.1" for my computer there... I don't think that this is a very good solution.

Regards,
Sven

Felipe Monteiro de Carvalho
to Sven Barth

Ok, thanks everyone, it seams that I managed to extract a function from Silvio's code which doesn't use Synapse. I only tested in Windows so far:

unit chesstcputils;
{$mode objfpc}{$H+}
interface
uses
  {$IFDEF MSWINDOWS}
  Winsock,
  {$ENDIF}
  Classes, SysUtils;
function ChessGetLocalIP(): string;
implementation
const
  CFormatIPMask = '%d.%d.%d.%d';
function ChessGetLocalIP(): string;
var
  I, VAttempt: Integer;
  VStrTemp, VSitesToTry: TStringList;
{$IFDEF UNIX}
  VProcess: TProcess;
{$ENDIF}
{$IFDEF MSWINDOWS}
var
  VWSAData: TWSAData;
  VHostEnt: PHostEnt;
  VName: string;
{$ENDIF}
begin
  Result := '';
{$IFDEF UNIX}
      VStrTemp := TStringList.Create;
      VProcess := TProcess.Create(nil);
      try
        VProcess.CommandLine :=
          'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"';
        VProcess.Options := [poWaitOnExit, poUsePipes];
        VProcess.Execute;
        VStrTemp.LoadFromStream(VProcess.Output);
        Result := Trim(VStrTemp.Text);
      finally
        VStrTemp.Free;
        VProcess.Free;
      end;
{$ENDIF}
{$IFDEF MSWINDOWS}
{$HINTS OFF}
      WSAStartup(2, VWSAData);
{$HINTS ON}
      SetLength(VName, 255);
      GetHostName(PChar(VName), 255);
      SetLength(VName, StrLen(PChar(VName)));
      VHostEnt := GetHostByName(PChar(VName));
      with VHostEnt^ do
        Result := Format(CFormatIPMask, [Byte(h_addr^[0]), Byte(h_addr^[1]),
          Byte(h_addr^[2]), Byte(h_addr^[3])]);
      WSACleanup;
{$ENDIF}
end;
end.
Felipe Monteiro de Carvalho
Andrew Brunner
to Sven Barth: Huh?! O.o You'll only find "127.0.0.1" for my computer there... I don't think that this…
Sven Barth wrote
You'll only find "127.0.0.1" for my computer there... I don't think that this is a very good solution.

Oh well. That makes sense b/c these are servers that I have obtaining the same IP over DHCP.
On clients when DHCP is being used with dynamic IPs the host file may not be of much use or may require more parsing for the host name.

But from a file based solution you just need to read in the /etc/hostname file. That is the name of the box.
With the host name, ust search the /etc/hosts file for the IP matching that name.
It's similar to the ifconfig command with parsing of eth0 which by the way if there are more than 1 nick, could be problematic.

Is there an Gnome or KDE API we could use to officially get NIC related info like iphlpapi.dll API under Windows?

Marco van de Voort
to Felipe Monteiro de Carvalho: Ok, thanks everyone, it seams that I managed to extract a function from Silvio's code…

In our previous episode, Felipe Monteiro de Carvalho said:

function ChessGetLocalIP(): string; VProcess.CommandLine := 'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"';

Fails if eth0 is not the primary NIC. Doesn't work on non-linux (that use other ethernet naming schemes)

A safe solution will probably boil down to walking the list of ethernet adapters and routes to find the default route on *nix.

Henry Vermaak
to Felipe Monteiro de Carvalho: Ok, thanks everyone, it seams that I managed to extract a function from Silvio's code…
Felipe Monteiro de Carvalho wrote 44 lines
Ok, thanks everyone, it seams that I managed to extract a function from Silvio's code which doesn't use Synapse. I only tested in Windows so far: unit chesstcputils; {$mode objfpc}{$H+} interface uses {$IFDEF MSWINDOWS} Winsock, {$ENDIF} Classes, SysUtils; function ChessGetLocalIP(): string; implementation const CFormatIPMask = '%d.%d.%d.%d'; function ChessGetLocalIP(): string; var I, VAttempt: Integer; VStrTemp, VSitesToTry: TStringList; {$IFDEF UNIX} VProcess: TProcess; {$ENDIF} {$IFDEF MSWINDOWS} var VWSAData: TWSAData; VHostEnt: PHostEnt; VName: string; {$ENDIF} begin Result := ''; {$IFDEF UNIX} VStrTemp := TStringList.Create; VProcess := TProcess.Create(nil); try VProcess.CommandLine := 'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"';

Yuck. This doesn't work on my system (debian). If you really want the least effort, you may have more luck with simply parsing `hostname -I` somehow. The right way to do this is with an ioctl, I believe (SIOCGIFCONF). Look here:

http://www.kernel.org/doc/man-pages/online/pages/man7/netdevice.7.html

I'm sure there's some code floating around, but it probably means that you have to translate some headers :(.

Henry

Brian Winfrey
Show quoted text 388 lines
Send fpc-pascal mailing list submissions to         To subscribe or unsubscribe via the World Wide Web, visit        http://lists.freepascal.org/mailman/listinfo/fpc-pascal or, via email, send a message with subject or body 'help' to         You can reach the person managing the list at         When replying, please edit your Subject line so it is more specific than "Re: Contents of fpc-pascal digest..." Today's Topics:   1. Re:  GetTempFileName in Linux (Michael Van Canneyt)   2. Re:  GetTempFileName in Linux (Jonas Maebe)   3. Re:  lNet getting the local IP (Andrew Brunner)   4. Re:  lNet getting the local IP (Sven Barth)   5. Re:  lNet getting the local IP (Felipe Monteiro de Carvalho)   6. Re:  lNet getting the local IP (Andrew Brunner)   7. Re:  lNet getting the local IP (Marco van de Voort)   8. Re:  lNet getting the local IP (Henry Vermaak) ---------------------------------------------------------------------- Message: 1 Date: Wed, 6 Oct 2010 11:59:53 +0200 (CEST) From: Michael Van Canneyt Subject: Re: [fpc-pascal] GetTempFileName in Linux To: FPC-Pascal users discussions Message-ID: Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed On Wed, 6 Oct 2010, Jonas Maebe wrote: > > On 06 Oct 2010, at 11:05, Michael Van Canneyt wrote: > >> On Wed, 6 Oct 2010, Jonas Maebe wrote: >> >>> On 06 Oct 2010, at 09:41, Michael Van Canneyt wrote: >>> >>>> This is always true on Unix, the only way to make sure is to have the >>>> kernel >>>> create the temporary name and file for you. Unix - to my knowledge - does >>>> not have a way to create and lock a file in one atomic operation; There >>>> are >>>> always 2 operations involved, and so anything can happen between the 2 >>>> calls. >>> >>> You can at least open a file with O_CREAT|O_EXCL|O_NOFOLLOW to make sure >>> that it does not yet exist at the point that you create it (and that it's >>> not a symlink either). >> >> This is correct, but doesn't lock the file, > > Locking is always advisory on Unix, so that doesn't matter anyway. > >> and so it doesn't prevent >> someone from 'stealing' the file before the lock is applied. > > Nobody else can steal the file once you have created it, because they won't > be the owner nor have the necessary permissions. That is the main security > risk and it is solved by this approach. The fact that another process running > under your login not using O_EXCL could overwrite it is not an extra security > risk (if you have a rogue process running under your login, nothing that you > do is safe because it can use ptrace to modify any process in any way it sees > fit anyway). And that is why I think the whole point is hugely exaggerated :-) But it doesn't mean we shouldn't do our best to make it minimally safe. Michael. ------------------------------ Message: 2 Date: Wed, 6 Oct 2010 12:57:02 +0200 From: Jonas Maebe Subject: Re: [fpc-pascal] GetTempFileName in Linux To: FPC-Pascal users discussions Message-ID: Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes On 06 Oct 2010, at 11:59, Michael Van Canneyt wrote: > On Wed, 6 Oct 2010, Jonas Maebe wrote: > >> Nobody else can steal the file once you have created it, because >> they won't be the owner nor have the necessary permissions. That is >> the main security risk and it is solved by this approach. The fact >> that another process running under your login not using O_EXCL >> could overwrite it is not an extra security risk (if you have a >> rogue process running under your login, nothing that you do is safe >> because it can use ptrace to modify any process in any way it sees >> fit anyway). > > And that is why I think the whole point is hugely exaggerated :-) It's not, because currently a process from *another* user can trivially intercept your temporary files. If you have a daemon running as root, that is a major security concern. Jonas ------------------------------ Message: 3 Date: Wed, 6 Oct 2010 07:49:42 -0500 From: Andrew Brunner Subject: Re: [fpc-pascal] lNet getting the local IP To: FPC-Pascal users discussions Message-ID:         Content-Type: text/plain; charset=ISO-8859-1 I just read the first line in /etc/hosts file.  The first entry is the IPv4. On Tue, Oct 5, 2010 at 3:04 PM, Felipe Monteiro de Carvalho wrote: > hello, > > I am searching for a way to get the local IP. I already found examples > with winsock, synapse and indy. Does anyone know how to do that with > lNet? > > thanks, > -- > Felipe Monteiro de Carvalho > _______________________________________________ > fpc-pascal maillist  -   > http://lists.freepascal.org/mailman/listinfo/fpc-pascal > ------------------------------ Message: 4 Date: Wed, 06 Oct 2010 14:55:21 +0200 From: Sven Barth Subject: Re: [fpc-pascal] lNet getting the local IP To: Message-ID: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Am 06.10.2010 14:49, schrieb Andrew Brunner: > I just read the first line in /etc/hosts file.  The first entry is the IPv4. > > On Tue, Oct 5, 2010 at 3:04 PM, Felipe Monteiro de Carvalho >  wrote: >> hello, >> >> I am searching for a way to get the local IP. I already found examples >> with winsock, synapse and indy. Does anyone know how to do that with >> lNet? >> >> thanks, Huh?! O.o You'll only find "127.0.0.1" for my computer there... I don't think that this is a very good solution. Regards, Sven ------------------------------ Message: 5 Date: Wed, 6 Oct 2010 15:27:30 +0200 From: Felipe Monteiro de Carvalho Subject: Re: [fpc-pascal] lNet getting the local IP To: FPC-Pascal users discussions Message-ID:         Content-Type: text/plain; charset=ISO-8859-1 Ok, thanks everyone, it seams that I managed to extract a function from Silvio's code which doesn't use Synapse. I only tested in Windows so far: unit chesstcputils; {$mode objfpc}{$H+} interface uses  {$IFDEF MSWINDOWS}  Winsock,  {$ENDIF}  Classes, SysUtils; function ChessGetLocalIP(): string; implementation const  CFormatIPMask = '%d.%d.%d.%d'; function ChessGetLocalIP(): string; var  I, VAttempt: Integer;  VStrTemp, VSitesToTry: TStringList; {$IFDEF UNIX}  VProcess: TProcess; {$ENDIF} {$IFDEF MSWINDOWS} var  VWSAData: TWSAData;  VHostEnt: PHostEnt;  VName: string; {$ENDIF} begin  Result := ''; {$IFDEF UNIX}      VStrTemp := TStringList.Create;      VProcess := TProcess.Create(nil);      try        VProcess.CommandLine :=          'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"';        VProcess.Options := [poWaitOnExit, poUsePipes];        VProcess.Execute;        VStrTemp.LoadFromStream(VProcess.Output);        Result := Trim(VStrTemp.Text);      finally        VStrTemp.Free;        VProcess.Free;      end; {$ENDIF} {$IFDEF MSWINDOWS} {$HINTS OFF}      WSAStartup(2, VWSAData); {$HINTS ON}      SetLength(VName, 255);      GetHostName(PChar(VName), 255);      SetLength(VName, StrLen(PChar(VName)));      VHostEnt := GetHostByName(PChar(VName));      with VHostEnt^ do        Result := Format(CFormatIPMask, [Byte(h_addr^[0]), Byte(h_addr^[1]),          Byte(h_addr^[2]), Byte(h_addr^[3])]);      WSACleanup; {$ENDIF} end; end. -- Felipe Monteiro de Carvalho ------------------------------ Message: 6 Date: Wed, 6 Oct 2010 08:51:32 -0500 From: Andrew Brunner Subject: Re: [fpc-pascal] lNet getting the local IP To: FPC-Pascal users discussions Message-ID:         Content-Type: text/plain; charset=ISO-8859-1 On Wed, Oct 6, 2010 at 7:55 AM, Sven Barth wrote: > You'll only find "127.0.0.1" for my computer there... I don't think that > this is a very good solution. Oh well.  That makes sense b/c these are servers that I have obtaining the same IP over DHCP. On clients when DHCP is being used with dynamic IPs the host file may not be of much use or may require more parsing for the host name. But from a file based solution you just need to read in the /etc/hostname file.  That is the name of the box. With the host name, ust search the /etc/hosts file for the IP matching that name.  It's similar to the ifconfig command with parsing of eth0 which by the way if there are more than 1 nick, could be problematic. Is there an Gnome or KDE API we could use to officially get NIC related info like iphlpapi.dll API under Windows? ------------------------------ Message: 7 Date: Wed, 6 Oct 2010 16:06:54 +0200 (CEST) From: (Marco van de Voort) Subject: Re: [fpc-pascal] lNet getting the local IP To: FPC-Pascal users discussions Message-ID: Content-Type: text/plain; charset="US-ASCII" In our previous episode, Felipe Monteiro de Carvalho said: > function ChessGetLocalIP(): string; >         VProcess.CommandLine := >           'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"'; Fails if eth0 is not the primary NIC. Doesn't work on non-linux (that use other ethernet naming schemes) A safe solution will probably boil down to walking the list of ethernet adapters and routes to find the default route on *nix. ------------------------------ Message: 8 Date: Wed, 06 Oct 2010 15:09:29 +0100 From: Henry Vermaak Subject: Re: [fpc-pascal] lNet getting the local IP To: FPC-Pascal users discussions Message-ID: Content-Type: text/plain; charset=ISO-8859-1; format=flowed On 06/10/10 14:27, Felipe Monteiro de Carvalho wrote: > Ok, thanks everyone, it seams that I managed to extract a function > from Silvio's code which doesn't use Synapse. I only tested in Windows > so far: > > unit chesstcputils; > > {$mode objfpc}{$H+} > > interface > > uses >    {$IFDEF MSWINDOWS} >    Winsock, >    {$ENDIF} >    Classes, SysUtils; > > function ChessGetLocalIP(): string; > > implementation > > const >    CFormatIPMask = '%d.%d.%d.%d'; > > function ChessGetLocalIP(): string; > var >    I, VAttempt: Integer; >    VStrTemp, VSitesToTry: TStringList; > {$IFDEF UNIX} >    VProcess: TProcess; > {$ENDIF} > {$IFDEF MSWINDOWS} > var >    VWSAData: TWSAData; >    VHostEnt: PHostEnt; >    VName: string; > {$ENDIF} > begin >    Result := ''; > {$IFDEF UNIX} >        VStrTemp := TStringList.Create; >        VProcess := TProcess.Create(nil); >        try >          VProcess.CommandLine := >            'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"'; Yuck.  This doesn't work on my system (debian).  If you really want the least effort, you may have more luck with simply parsing `hostname -I` somehow.  The right way to do this is with an ioctl, I believe (SIOCGIFCONF).  Look here: http://www.kernel.org/doc/man-pages/online/pages/man7/netdevice.7.html I'm sure there's some code floating around, but it probably means that you have to translate some headers :(. Henry

Re: [fpc-pascal] lNet getting the local IP

I found an example for linux on stack overflow that was in c http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer

- here is a rough translation:

program GetPrimaryIpAddress;
{$mode objfpc}

uses
baseunix,
unixtype,
sockets,

  SysUtils;
procedure Get(var buf: array of char; const len: longint);
const
  CN_GDNS_ADDR = '8.8.8.8';
  CN_GDNS_PORT = 53;
var
  s: string;
  sock: longint;
  err: longint;
  HostAddr: TSockAddr;
  l: Integer;
  UnixAddr: TInetSockAddr;
begin
  err := 0;
  Assert(len >= 16);
  sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  assert(sock  -1);
  UnixAddr.family := AF_INET;
  UnixAddr.port := htons(CN_GDNS_PORT);
  UnixAddr.addr := StrToHostAddr(CN_GDNS_ADDR).s_addr;
  if (fpConnect(sock,@UnixAddr,SizeOf(UnixAddr)) = 0) then
  begin
    try
      l := SizeOf(HostAddr);
      if (fpgetsockname(sock, @HostAddr, @l) = 0) then
      begin
        s := NetAddrToStr(HostAddr.sin_addr);
        StrPCopy(PChar(Buf), s);
      end
      else
      begin
        err:=socketError;
      end;
    finally
      if (fpclose(sock)  0) then
      begin
        err := socketError;
      end;
    end;
  end
  else
  begin
    err:=socketError;
  end;
  if (err  0) then
  begin
    // report error
  end;
end;
var
  ipbuf: array[0..255] of char;
begin
  system.FillChar(ipbuf, sizeOf(ipBuf), #0);
  Get(ipbuf, system.SizeOf(ipbuf));
  WriteLn(StrPas(ipbuf));
end.

BrianW

silvioprog
to Brian Winfrey: On Wed, Oct 6, 2010 at 7:09 AM, Re: [fpc-pascal] lNet getting the local IP I found an…

Wow, worked perfectely in Ubuntu-10.04, Mandriva-2010 and openSUSE-11.2.

Thanks for the exelent solutions. :)

2010/10/7 Brian Winfrey

Show quoted text 80 lines
I found an example for linux on stack overflow that was in c http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer - here is a rough translation: program GetPrimaryIpAddress; {$mode objfpc} uses baseunix, unixtype, sockets, SysUtils; procedure Get(var buf: array of char; const len: longint); const CN_GDNS_ADDR = '8.8.8.8'; CN_GDNS_PORT = 53; var s: string; sock: longint; err: longint; HostAddr: TSockAddr; l: Integer; UnixAddr: TInetSockAddr; begin err := 0; Assert(len >= 16); sock := fpsocket(AF_INET, SOCK_DGRAM, 0); assert(sock -1); UnixAddr.family := AF_INET; UnixAddr.port := htons(CN_GDNS_PORT); UnixAddr.addr := StrToHostAddr(CN_GDNS_ADDR).s_addr; if (fpConnect(sock,@UnixAddr,SizeOf(UnixAddr)) = 0) then begin try l := SizeOf(HostAddr); if (fpgetsockname(sock, @HostAddr, @l) = 0) then begin s := NetAddrToStr(HostAddr.sin_addr); StrPCopy(PChar(Buf), s); end else begin err:=socketError; end; finally if (fpclose(sock) 0) then begin err := socketError; end; end; end else begin err:=socketError; end; if (err 0) then begin // report error end; end; var ipbuf: array[0..255] of char; begin system.FillChar(ipbuf, sizeOf(ipBuf), #0); Get(ipbuf, system.SizeOf(ipbuf)); WriteLn(StrPas(ipbuf)); end. BrianW
Silvio Clécio, *programmer* *ObjectPascal*
Luca Olivetti
to Marco van de Voort: In our previous episode, Brian Winfrey said: Compiles on FreeBSD and the result looks…

En/na Marco van de Voort ha escrit:

Show quoted text 7 lines
In our previous episode, Brian Winfrey said: > I found an example for linux on stack overflow that was in c > http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer Compiles on FreeBSD and the result looks sane (but on a system that has a routable address)

I didn't try it, but I see that it tries to connect to google's dns server, so it'd fail miserably if the computer has no internet access.

Bye

Luca
bwCode4U

Choose a different address that would not fail in a specific situation. For example, one could read their /etc/resolve file to get the dns server.

Brian Winfrey
~~~~~~~~~~
Important Note:
Code provide as an example. There could be errors or risks in using it. There is no warranty implied or implicit, it may not even work.

Frank Church
to silvioprog

I am developing for an embedded system and found out that 'nmap --iflist' does a faily good job of this if the output is examined and parsed properly. If it is suitable and you can possibly extract the code (if you are prepared to go that far) it might help you. It is also cross platform

silvioprog wrote 21 lines
2010/10/7 Luca Olivetti > I didn't try it, but I see that it tries to connect to google's dns > server, so it'd fail miserably if the computer has no internet access. > > Bye > -- > Luca > I tested, without web access does not work. :o -- Silvio Clécio, *programmer* *ObjectPascal* _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Frank Church ======================= http://devblog.brahmancreations.com
Brian Winfrey
Show quoted text 11 lines
> > I didn't try it, but I see that it tries to connect to google's dns serve= r, > so it'd fail miserably if the computer has no internet access. > > Bye > -- > Luca > I tested, without web access does not work. :o

A hard coded address will of course fail if it cannot be reached. The code was an example, you should use it as such. I substituted my router's ip for google's and it works.;)

Choose a different address that would not fail in a specific situation.

As another example, one could read their /etc/resolve file to get the dns server that is assigned.

Brian Winfrey

Brian Winfrey
to Brian Winfrey: On Wed, Oct 6, 2010 at 7:09 AM, Re: [fpc-pascal] lNet getting the local IP I found an…
Show quoted text 140 lines
> On 06/10/10 14:27, Felipe Monteiro de Carvalho wrote: >> Ok, thanks everyone, it seams that I managed to extract a function >> from Silvio's code which doesn't use Synapse. I only tested in Windows >> so far: >> >> unit chesstcputils; >> >> {$mode objfpc}{$H+} >> >> interface >> >> uses >>    {$IFDEF MSWINDOWS} >>    Winsock, >>    {$ENDIF} >>    Classes, SysUtils; >> >> function ChessGetLocalIP(): string; >> >> implementation >> >> const >>    CFormatIPMask = '%d.%d.%d.%d'; >> >> function ChessGetLocalIP(): string; >> var >>    I, VAttempt: Integer; >>    VStrTemp, VSitesToTry: TStringList; >> {$IFDEF UNIX} >>    VProcess: TProcess; >> {$ENDIF} >> {$IFDEF MSWINDOWS} >> var >>    VWSAData: TWSAData; >>    VHostEnt: PHostEnt; >>    VName: string; >> {$ENDIF} >> begin >>    Result := ''; >> {$IFDEF UNIX} >>        VStrTemp := TStringList.Create; >>        VProcess := TProcess.Create(nil); >>        try >>          VProcess.CommandLine := >>            'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"'; > > Yuck.  This doesn't work on my system (debian).  If you really want the > least effort, you may have more luck with simply parsing `hostname -I` > somehow.  The right way to do this is with an ioctl, I believe > (SIOCGIFCONF).  Look here: > > http://www.kernel.org/doc/man-pages/online/pages/man7/netdevice.7.html > > I'm sure there's some code floating around, but it probably means that > you have to translate some headers :(. > > Henry > Re: [fpc-pascal] lNet getting the local IP > I found an example for linux on stack overflow that was in c http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer - here is a rough translation: program GetPrimaryIpAddress; {$mode objfpc} uses  baseunix,  unixtype,  sockets,  SysUtils; procedure Get(var buf: array of char; const len: longint); const  CN_GDNS_ADDR = '8.8.8.8';  CN_GDNS_PORT = 53; var  s: string;  sock: longint;  err: longint;  HostAddr: TSockAddr;  l: Integer;  UnixAddr: TInetSockAddr; begin  err := 0;  Assert(len >= 16);  sock := fpsocket(AF_INET, SOCK_DGRAM, 0);  assert(sock -1);  UnixAddr.family := AF_INET;  UnixAddr.port := htons(CN_GDNS_PORT);  UnixAddr.addr := StrToHostAddr(CN_GDNS_ADDR).s_addr;  if (fpConnect(sock,@UnixAddr,SizeOf(UnixAddr)) = 0) then  begin    try      l := SizeOf(HostAddr);      if (fpgetsockname(sock, @HostAddr, @l) = 0) then      begin        s := NetAddrToStr(HostAddr.sin_addr);        StrPCopy(PChar(Buf), s);      end      else      begin        err:=socketError;      end;    finally      if (fpclose(sock) 0) then      begin        err := socketError;      end;    end;  end  else  begin    err:=socketError;  end;  if (err 0) then  begin    // report error  end; end; var  ipbuf: array[0..255] of char; begin  system.FillChar(ipbuf, sizeOf(ipBuf), #0);  Get(ipbuf, system.SizeOf(ipbuf));  WriteLn(StrPas(ipbuf)); end. BrianW

I have tried this code with multiple scenarios.

if interfaces are down, no ip address is returned. I would say that is expected as there is no network.
ifconfig will return same. only lo has an address 127.0.0.1.

Otherwise I get the primary ip address as long as routing is used.

if connecting to 0.0.0.0, 127.0.0.1 is returned

Use 127.0.0.1 and the primary is returned.

Run some tests and let me know what you find.

silvioprog
to Brian Winfrey

Hi Brian,

I tested again, and discovered that's not is necessary a connection to a web.
I changed to 0.0.0.0 and returned 127.0.0.1, perfect! :)

I will use this function. Thanks very much again. :)

2010/10/7 Brian Winfrey

Show quoted text 154 lines
>> On 06/10/10 14:27, Felipe Monteiro de Carvalho wrote: >>> Ok, thanks everyone, it seams that I managed to extract a function >>> from Silvio's code which doesn't use Synapse. I only tested in Windows >>> so far: >>> >>> unit chesstcputils; >>> >>> {$mode objfpc}{$H+} >>> >>> interface >>> >>> uses >>> {$IFDEF MSWINDOWS} >>> Winsock, >>> {$ENDIF} >>> Classes, SysUtils; >>> >>> function ChessGetLocalIP(): string; >>> >>> implementation >>> >>> const >>> CFormatIPMask = '%d.%d.%d.%d'; >>> >>> function ChessGetLocalIP(): string; >>> var >>> I, VAttempt: Integer; >>> VStrTemp, VSitesToTry: TStringList; >>> {$IFDEF UNIX} >>> VProcess: TProcess; >>> {$ENDIF} >>> {$IFDEF MSWINDOWS} >>> var >>> VWSAData: TWSAData; >>> VHostEnt: PHostEnt; >>> VName: string; >>> {$ENDIF} >>> begin >>> Result := ''; >>> {$IFDEF UNIX} >>> VStrTemp := TStringList.Create; >>> VProcess := TProcess.Create(nil); >>> try >>> VProcess.CommandLine := >>> 'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"'; >> >> Yuck. This doesn't work on my system (debian). If you really want the >> least effort, you may have more luck with simply parsing `hostname -I` >> somehow. The right way to do this is with an ioctl, I believe >> (SIOCGIFCONF). Look here: >> >> http://www.kernel.org/doc/man-pages/online/pages/man7/netdevice.7.html >> >> I'm sure there's some code floating around, but it probably means that >> you have to translate some headers :(. >> >> Henry >> > Re: [fpc-pascal] lNet getting the local IP >> > > I found an example for linux on stack overflow that was in c > http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer > > - here is a rough translation: > > program GetPrimaryIpAddress; > {$mode objfpc} > > uses > baseunix, > unixtype, > sockets, > SysUtils; > > procedure Get(var buf: array of char; const len: longint); > const > CN_GDNS_ADDR = '8.8.8.8'; > CN_GDNS_PORT = 53; > var > s: string; > sock: longint; > err: longint; > HostAddr: TSockAddr; > l: Integer; > UnixAddr: TInetSockAddr; > > begin > err := 0; > Assert(len >= 16); > > sock := fpsocket(AF_INET, SOCK_DGRAM, 0); > assert(sock -1); > > UnixAddr.family := AF_INET; > UnixAddr.port := htons(CN_GDNS_PORT); > UnixAddr.addr := StrToHostAddr(CN_GDNS_ADDR).s_addr; > > if (fpConnect(sock,@UnixAddr,SizeOf(UnixAddr)) = 0) then > begin > try > l := SizeOf(HostAddr); > if (fpgetsockname(sock, @HostAddr, @l) = 0) then > begin > s := NetAddrToStr(HostAddr.sin_addr); > StrPCopy(PChar(Buf), s); > end > else > begin > err:=socketError; > end; > finally > if (fpclose(sock) 0) then > begin > err := socketError; > end; > end; > end > else > begin > err:=socketError; > end; > > if (err 0) then > begin > // report error > end; > end; > > var > ipbuf: array[0..255] of char; > > begin > system.FillChar(ipbuf, sizeOf(ipBuf), #0); > Get(ipbuf, system.SizeOf(ipbuf)); > WriteLn(StrPas(ipbuf)); > end. > > BrianW > I have tried this code with multiple scenarios. if interfaces are down, no ip address is returned. I would say that is expected as there is no network. ifconfig will return same. only lo has an address 127.0.0.1. Otherwise I get the primary ip address as long as routing is used. if connecting to 0.0.0.0, 127.0.0.1 is returned Use 127.0.0.1 and the primary is returned. Run some tests and let me know what you find.
Silvio Clécio, *programmer* *ObjectPascal*
Brian Winfrey
to silvioprog

I think you want to use 127.0.0.1 to return the actual address.

In my case I would

const
  CN_GDNS_ADDR = '127.0.0.1';

run the progarm and the output would be 192.168.1.5 as long as there is an active interface.

silvioprog wrote 171 lines
Hi Brian, I tested again, and discovered that's not is necessary a connection to a web. I changed to 0.0.0.0 and returned 127.0.0.1, perfect! :) I will use this function. Thanks very much again. :) 2010/10/7 Brian Winfrey > > >> On 06/10/10 14:27, Felipe Monteiro de Carvalho wrote: > >>> Ok, thanks everyone, it seams that I managed to extract a function > >>> from Silvio's code which doesn't use Synapse. I only tested in Windows > >>> so far: > >>> > >>> unit chesstcputils; > >>> > >>> {$mode objfpc}{$H+} > >>> > >>> interface > >>> > >>> uses > >>>    {$IFDEF MSWINDOWS} > >>>    Winsock, > >>>    {$ENDIF} > >>>    Classes, SysUtils; > >>> > >>> function ChessGetLocalIP(): string; > >>> > >>> implementation > >>> > >>> const > >>>    CFormatIPMask = '%d.%d.%d.%d'; > >>> > >>> function ChessGetLocalIP(): string; > >>> var > >>>    I, VAttempt: Integer; > >>>    VStrTemp, VSitesToTry: TStringList; > >>> {$IFDEF UNIX} > >>>    VProcess: TProcess; > >>> {$ENDIF} > >>> {$IFDEF MSWINDOWS} > >>> var > >>>    VWSAData: TWSAData; > >>>    VHostEnt: PHostEnt; > >>>    VName: string; > >>> {$ENDIF} > >>> begin > >>>    Result := ''; > >>> {$IFDEF UNIX} > >>>        VStrTemp := TStringList.Create; > >>>        VProcess := TProcess.Create(nil); > >>>        try > >>>          VProcess.CommandLine := > >>>            'sh -c "ifconfig eth0 | awk ''/inet end/ {print $3}''"'; > >> > >> Yuck.  This doesn't work on my system (debian).  If you really want the > >> least effort, you may have more luck with simply parsing `hostname -I` > >> somehow.  The right way to do this is with an ioctl, I believe > >> (SIOCGIFCONF).  Look here: > >> > >> http://www.kernel.org/doc/man-pages/online/pages/man7/netdevice.7.html > >> > >> I'm sure there's some code floating around, but it probably means that > >> you have to translate some headers :(. > >> > >> Henry > >> > > Re: [fpc-pascal] lNet getting the local IP > >> > > > > I found an example for linux on stack overflow that was in c > > > > http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer > > > > - here is a rough translation: > > > > program GetPrimaryIpAddress; > > {$mode objfpc} > > > > uses > >  baseunix, > >  unixtype, > >  sockets, > >  SysUtils; > > > > procedure Get(var buf: array of char; const len: longint); > > const > >  CN_GDNS_ADDR = '8.8.8.8'; > >  CN_GDNS_PORT = 53; > > var > >  s: string; > >  sock: longint; > >  err: longint; > >  HostAddr: TSockAddr; > >  l: Integer; > >  UnixAddr: TInetSockAddr; > > > > begin > >  err := 0; > >  Assert(len >= 16); > > > >  sock := fpsocket(AF_INET, SOCK_DGRAM, 0); > >  assert(sock -1); > > > >  UnixAddr.family := AF_INET; > >  UnixAddr.port := htons(CN_GDNS_PORT); > >  UnixAddr.addr := StrToHostAddr(CN_GDNS_ADDR).s_addr; > > > >  if (fpConnect(sock,@UnixAddr,SizeOf(UnixAddr)) = 0) then > >  begin > >    try > >      l := SizeOf(HostAddr); > >      if (fpgetsockname(sock, @HostAddr, @l) = 0) then > >      begin > >        s := NetAddrToStr(HostAddr.sin_addr); > >        StrPCopy(PChar(Buf), s); > >      end > >      else > >      begin > >        err:=socketError; > >      end; > >    finally > >      if (fpclose(sock) 0) then > >      begin > >        err := socketError; > >      end; > >    end; > >  end > >  else > >  begin > >    err:=socketError; > >  end; > > > >  if (err 0) then > >  begin > >    // report error > >  end; > > end; > > > > var > >  ipbuf: array[0..255] of char; > > > > begin > >  system.FillChar(ipbuf, sizeOf(ipBuf), #0); > >  Get(ipbuf, system.SizeOf(ipbuf)); > >  WriteLn(StrPas(ipbuf)); > > end. > > > > BrianW > > > I have tried this code with multiple scenarios. > > if interfaces are down, no ip address is returned. I would say that is > expected as there is no network. > ifconfig will return same. only lo has an address 127.0.0.1. > > Otherwise I get the primary ip address as long as routing is used. > > if connecting to 0.0.0.0, 127.0.0.1 is returned > > Use 127.0.0.1 and the primary is returned. > > Run some tests and let me know what you find. -- Silvio Clécio, programmer ObjectPascal _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Brian Winfrey
to Brian Winfrey

I don't know if you noticed, but it appears that code has some depracated properties that should be changed.

Here are the modifications I made in exploring this issue:

program GetPrimaryIpAddress;
{$mode objfpc}

uses
baseunix,
unixtype,
sockets,

  SysUtils;
procedure Get(out AddrOut: string);
const
  CN_GDNS_ADDR = '127.0.0.1';
  CN_GDNS_PORT = 53;
var
  sock: longint;
  err: longint;
  UnixAddr: TInetSockAddr;
  HostAddr: TSockAddr;
  len: Integer;
begin
  err := 0;
  sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  assert(sock  -1);
// changed because previous properties were deprecated
  UnixAddr.sin_family := AF_INET;
  UnixAddr.sin_port := htons(CN_GDNS_PORT);
  UnixAddr.sin_addr := StrToHostAddr(CN_GDNS_ADDR);
  if (fpConnect(sock, @UnixAddr, SizeOf(UnixAddr)) = 0) then
  begin
    try
      len := SizeOf(HostAddr);
      if (fpgetsockname(sock, @HostAddr, @len) = 0) then
      begin
        AddrOut := NetAddrToStr(HostAddr.sin_addr);
      end
      else
      begin
        err:=socketError;
      end;
    finally
      if (fpclose(sock)  0) then
      begin
        err := socketError;
      end;
    end;
  end
  else
  begin
    err:=socketError;
  end;
  if (err  0) then
  begin
    // report error
  end;
end;
var
  strAddr: string;
begin
  Get(strAddr);
  WriteLn('ip : ',strAddr);
end.
Boris Samorodov
to Brian Winfrey
Here are the modifications I made in exploring this issue:

It works on:
-----
% uname -a
FreeBSD host.ipt.ru 9.0-CURRENT FreeBSD 9.0-CURRENT #3 r213198M: Mon Sep 27 15:43:54 MSD 2010 i386 -----

WBR, Boris Samorodov (bsam) Research Engineer, http://www.ipt.ru Telephone & Internet SP FreeBSD Committer, http://www.FreeBSD.org The Power To Serve