• Status: Solved
• Priority: Medium
• Security: Public
• Views: 2046

# IP to Decimal and Decimal to IP

Does anyone have a function that converts an IP to Decimal and a function that converts the decimal back to IP

Thanks

0
alspivey
• 8
• 7
• 3
• +6
1 Solution

Commented:
What is an IP?

mlmcc
0

Author Commented:
0

Commented:
perl -e "print unpack'N',pack'C*',split/\./,shift" 192.168.0.1
perl -e "print join'.',unpack'C*',pack'N',shift" 3232235521
0

Commented:
in C/C++ try inet_aton:
inet_aton() converts the Internet host address cp from the standard numbers-and-dots notation into  binary  data  and
stores it in the structure that inp points to. inet_aton returns nonzero if the address is valid, zero if not.

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int inet_aton(const char *cp, struct in_addr *inp);
0

Commented:
heres an ip to decimal delphi function i made some time ago. Tho i dont quite know how to reverse it :P

var
Dec   : Array[1..4] of integer = (16777216,65536,256,1);

procedure ip2dec(ip:string; decimal: int64);
VAR ip             : Array[1..4] of Int64;
IPCut          : string;
Poz, i         : integer;
total          : int64;

begin
IPCut := ipstr;

i := 1;
While Pos('.', IPCut) > 0 Do
Begin
Poz := Pos('.', IPCut);
ip[i] := StrToInt( Copy(IPCut,1,Poz - 1));
Delete(IPCut, 1, Poz);
inc(i);
end;
ip[4] := StrToInt(IPCut);

Total := 0;
i := 1;
While i <= 4 do
begin
total := Total + ip[i] * dec[i];
inc(i);
end;
decimal := total;
end;
0

Commented:
Delphi code:

type
// since IPv4 address consists of four octets or simply dword
TIPv4 = record
a,b,c,d: byte;
end;

function IPv4ToInt(const IP: string): dword;
var
c, i, l: integer;
ba: array [0..3] of byte;
s: string;
begin
c := 0;
l := Length(IP);
for i := 1 to l do begin
if IP[i] <> '.' then
s := s + IP[i];
if (IP[i] = '.') or (i = l) then begin
ba[c] := StrToInt(s);
s := '';
inc(c);
end;
end;
Move(ba, Result, 4);
end;

function IntToIPv4(const IntIP: dword): string;
begin
with TIPv4(IntIP) do
Result := Format('%d.%d.%d.%d', [a, b, c, d]);
end;

wbr, mo.
0

Author Commented:
0

Commented:
IPv4ToInt('192.168.0.1') will be 16820416.
IPv4 is in format xxx.xxx.xxx.xxx
where xxx is 8bit number (octet)

wbr, mo.
0

Commented:
done?
0

Commented:
I think, first you must specify what language you are using ;-). The following example (in Delphi) I used for my own needs:

uses
Splitter;

type
TIPAddress = packed record // IP-Ã Ã¤Ã°Ã¥Ã±
case Integer of
1: (A4, A3, A2, A1: Byte);
2: (A: Cardinal);
end;

var
Splitter: TSplitter;
Code, A: Integer;
label 1;
begin
Result.A := 0;
Splitter := TSplitter.Create(S, '.', True);
if Splitter.Src = '' then Goto 1;
if Splitter.Count <> 4 then Goto 1;
if Splitter.S[0] = '*' then IP.A1 := 255 else
begin
Val(Splitter.S[0], A, Code);
if (Code <> 0) or (A < 0) or (A > 255) then Goto 1;
IP.A1 := A;
end;
if Splitter.S[1] = '*' then IP.A2 := 255 else
begin
Val(Splitter.S[1], A, Code);
if (Code <> 0) or (A < 0) or (A > 255) then Goto 1;
IP.A2 := A;
end;
if Splitter.S[2] = '*' then IP.A3 := 255 else
begin
Val(Splitter.S[2], A, Code);
if (Code <> 0) or (A < 0) or (A > 255) then Goto 1;
IP.A3 := A;
end;
if Splitter.S[3] = '*' then IP.A4 := 255 else
begin
Val(Splitter.S[3], A, Code);
if (Code <> 0) or (A < 0) or (A > 255) then Goto 1;
IP.A4 := A;
end;
Result := IP;
1:
Splitter.Free;
end;

begin
Result := IntToStr(IP.A1) + '.' + IntToStr(IP.A2) + '.' + IntToStr(IP.A3) +
'.' + IntToStr(IP.A4);
end;

If you are using WinSock API you may prefer WinSock API native functions inet_addr and inet_ntoa (given C++ syntax):

char FAR * inet_ntoa (
);

const char   FAR *cp
);

See Platform SDK: Windows Sockets (MSDN) for details.
0

Commented:
i think he should choose the SHORT solution :P
0

Author Commented:
Hi mocarts,

Your 2 functions work great. What I'm trying to do is calculate how many ip's are contained in a range of 2 address i.e 192.168.0.8 - 192.168.1.255. And I was thinking that converting them to decimal would alow me to subtract them to get the total count. (How wrong I was)
I also was trying to step through the IP's one by one by adding 1 to the decimal and then convert it back, but that want work. Any ideas on how to do something this.

p.s msa2003 I'm using Delphi
0

Commented:
u shud have specified the language of ur choice.. else everyday u'll get a solution in different programming language
0

Commented:
that's very simple.
example with functions provided above by me:

function CountIPs(const ipFrom, ipTo: string): int64;
var
ipf, ipt: TIPv4;
begin
Result := 0;
ipf := TIPv4(IPv4ToInt(ipFrom));
ipt := TIPv4(IPv4ToInt(ipTo));
Result := ((ipt.a-ipf.a)*16777216) + ((ipt.b-ipf.b)*65536)
+ ((ipt.c-ipf.c)*256) + (ipt.d-ipf.d) {+ 1};
// +1 - if you want to include ipFrom in range
end;

and function to increment by one IP:
procedure IncIPv4(var IP: TIPv4);
begin
if IP.d < 255 then Inc(IP.d)
else begin
IP.d := 0;
if IP.c < 255 then Inc(IP.c)
else begin
IP.c := 0;
if IP.b < 255 then Inc(IP.b)
else begin
IP.b := 0;
if IP.a < 255 then Inc(IP.a)
else IP.a := 0;
end;
end;
end;
end;

wbr, mo.
0

Commented:
Whacko: my solution is not big. It is universal. Because I used it to work with real sets of IP addresses.

You should use my unit the next way:

Count := Abs(GetIPFromString('192.168.0.8').A - GetIPFromString('192.168.1.255').A);

Very simple, isn't it ;-) ?

Mocart: Don't you think that there is no need to get values by multiplication? I think that the better way (which does exactly the same, but much faster) is to use packed record to set a byte of a double word ;-).

The shorter example (excluding masking and error checking) of GetIPFromString:

var
Splitter: TSplitter;
Code: Integer;
begin
Splitter := TSplitter.Create(S, '.', True);
Val(Splitter.S[0], Result.A1, Code);
Val(Splitter.S[1], Result.A2, Code);
Val(Splitter.S[2], Result.A3, Code);
Val(Splitter.S[3], Result.A4, Code);
Splitter.Free;
end;
0

Commented:
And what is really better:

uses
WinSock;

function CountIPs(const ipFrom, ipTo: String): Integer;
begin
end;

The only one line of code ;-)

Whi don't I use Int64 - because IPv4 IP address is 32-bit!

htonl and inet_addr are WinSock API functions. inet_addr gets an IP address from it's string representation in reverse byte order. htonl converts it to normal byte order.
0

Commented:
Sorry,

uses
WinSock;

function CountIPs(const ipFrom, ipTo: String): Integer;
begin
end;
0

Commented:
you are right msa2003! I have to change order of elements in my TIPv4 record.
there will be complete solution to convert to dword and back IP string.

type
{\$IFOPT R-}
{\$DEFINE RANGEOFF}
{\$ENDIF}
EInvalidIPString = class(Exception)
end;

TIPv4 = record
d,c,b,a: byte;
end;

function IPv4ToInt(const IP: string): dword;
var
c, i, l: integer;
ba: array [0..3] of byte;
s: string;
begin
c := 3;
l := Length(IP);
if l = 0 then raise EInvalidIPString.Create('Zero IP string length.');
try
for i := 1 to l do begin
if IP[i] <> '.' then
s := s + IP[i];
if (IP[i] = '.') or (i = l) then begin
{\$IFDEF RANGEOFF} {\$R+} {\$ENDIF}
ba[c] := StrToInt(s);
{\$IFDEF RANGEOFF} {\$R-} {\$UNDEF RANGEOFF} {\$ENDIF}
s := '';
dec(c);
end;
end;
except
raise EInvalidIPString.Create('Invalid IP string format.');
end;
if c <> -1 then
raise EInvalidIPString.Create('Invalid IP string format.');
Move(ba, Result, 4);
end;

function IntToIPv4(const IntIP: dword): string;
begin
with TIPv4(IntIP) do
Result := Format('%d.%d.%d.%d', [a, b, c, d]);
end;

to get count:
Count := IPv4ToInt(sIpTo) - IPv4ToInt(sIpFrom);

to increment:
IntToIPv4(IPv4ToInt(sIP)+1);

wbr, mo.
0

Commented:
Don't you think that alltrhough usage of WinSock unit (which is shipped with Delphi) is better:

To get a string from IP (now Delphi syntax):

To get an IP from string:

function inc_ip(ip: string): string;
var
begin
end;
0

Commented:
no, cos if there's an old, or no winsock installed you might get errors :P also its always better to use code instead of (third party) components, because:
2. easier to debug cos you still know what you did.
3. users of your app wouldbt have to install extra dll's etc, just because you wanted to make an app the easy way.

if its only for personal use... just see for yourself, but i can recommend this to anyone who wants to "master" a programming language
0

Commented:
Yes, but i think different:
1. It is usefull to learn more about WinSock API, cos it is a native TCP/IP API
2. You still know what you did - dll's are already debugged :P
3. winsock32.dll is allwais provided with ANY 32-bit Windows system. If your system is not 32-bit, all these examples wouldn't work :P

Of course, the ways could be different. I think I provided both :-) So there is something to choose from ;-)

P. S. I could provide access to full code of my Utils unit (Splitter is just a part). This code provides extended functionality such as IP masked compare, IP sets, configuration and user management utilities etc. As a kernel it uses the functions provided ahead.
0

Commented:
since I use dword as result - function will work on 16, 32, 64 etc. bit systems.
of course Winsock is another way how to do it, but if you don't need Winsock why compile unit in app?
wbr, mo.
0

Commented:
mocarts: I noted that I had provided two different solutions. The first (with Splitter unit) doesn't use WinSock and is a part of a real billing system which is extremely stable and processes thowsands IP's every day ;-). Another solution uses functions already provided with Windows system.

Your solution will not work in 16-bit system ;-). Simoly bacause Delphi from version 2 generates ONLY 32-bit code ;-). Delphi (1) generates 16-bit code but doesn't has rather different syntax ;-).

There are the details. In the matter of fact there is not a market but a place where experts must exchange ;-).
0

Commented:
why did you think, code will not work on 16bit system? dword is 32bit on 16bit or on 32bit system it doesn't matter..
wbr, mo.
0

Commented:
0

Commented:
No thanx...
0

## Featured Post

• 8
• 7
• 3
• +6
Tackle projects and never again get stuck behind a technical roadblock.