Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

IP address to binary conversion

1,057 views
Skip to first unread message

Jeroen Wolff

unread,
Jun 13, 2001, 2:52:48 PM6/13/01
to
Hi,

Can somebody help me (a newbee) to convert an ip address to is 32 bits
representation?

i would like to store these 32bits interger into a MYSQL database
together with the mask.

Jeroen

Rikard Bosnjakovic

unread,
Jun 13, 2001, 7:58:50 PM6/13/01
to
Jeroen Wolff wrote:

> Can somebody help me (a newbee) to convert an ip address to is 32 bits
> representation?

Lucky you, I had exactly that problem yesterday and hacked this
solution:


------------------[snip]------------------
import socket, struct

# return true if a string could be a pure ip address (4 dotted)
def is_ipaddress(str):
if str.count(".") != 3:
return 0
for i in str.split("."):
if not i.isdigit():
return 0
i = int(i)
if i>255 or i<0:
return 0
return 1

def interpret_addr(str):
host = None
if is_ipaddress(str):
res = socket.inet_aton(str)
else:
try:
host = socket.gethostbyname(str)
except:
print "Can't resolve '%s'" %(str)
return 0

if host:
res = socket.inet_aton(host)

res = struct.unpack("!l", res)[0]

if res == -1:
return 0

return res

>>> interpret_addr("10.30.40.50")
169748530
>>> interpret_addr("www.hotmail.com")
1074015239
------------------[snip]------------------


--
Rikard Bosnjakovic - http://bos.hack.org/cv/ - ICQ: 1158217

Anyone sending unwanted advertising e-mail to my address will be
charged $250 for network traffic and computing time. By extracting my
address from this message or its header, you agree to these terms.

Rikard Bosnjakovic

unread,
Jun 13, 2001, 8:01:14 PM6/13/01
to
Here's a solution for the reverse:

>>> socket.inet_ntoa(struct.pack("!I", long(1074015239)))
'64.4.44.7'

Jeroen Wolff

unread,
Jun 14, 2001, 1:14:07 AM6/14/01
to
On Thu, 14 Jun 2001 02:01:14 +0200, Rikard Bosnjakovic <b...@hack.org>
wrote:

>Here's a solution for the reverse:
>
>>>> socket.inet_ntoa(struct.pack("!I", long(1074015239)))
>'64.4.44.7'

Thanks for the solution!

But when i try: interpret_addr("195.7.145.2") --> -1022914302
the result is an signed long.
So the way back is not good....

Is there a way to make it unsigned? ( a 32 bits unsigned value needed)

Jeroen

Rikard Bosnjakovic

unread,
Jun 14, 2001, 2:29:41 AM6/14/01
to
Jeroen Wolff wrote:

> Is there a way to make it unsigned? ( a 32 bits unsigned value needed)

Change "l" to "I" or "L" in the struct.unpack(), then you will get a
Python long integer.

Greg Jorgensen

unread,
Jun 14, 2001, 4:19:57 AM6/14/01
to
"Jeroen Wolff" <jwo...@ision.nl> wrote in message
news:tedfit8li6m4i5gkn...@4ax.com...

> Hi,
>
> Can somebody help me (a newbee) to convert an ip address to is 32 bits
> representation?

Each of the four numbers in the dotted-quad IP address is the decimal
version of a hex pair. It's already a 32-bit number, you just have to do a
little bit of work.

One way is to simply multiply the address out. For example, given the IP
address 192.168.2.1, the 32-bit equivalent is:

192 * 256^3 + 186 * 256^2 + 2 * 256 + 1 = 3232236033 (0xC0A80201)

Here's one Python solution. Note the long integers: Python's regular signed
integers aren't big enough.

>>> ip = "192.168.2.1"
>>> q = ip.split(".")
>>> n = reduce(lambda a,b: long(a)*256 + long(b), q)
>>> n
3232236033L

The reduce() is equivalent to:

>>> n = long(q[0]) * 256**3 + long(q[1]) * 256**2 + long(q[2]) * 256 +
long(q[3])

You can get a mask m bits long like this:

>>> mask = (long(2)**m) - 1

Now you can simply AND these together to get the network and host portions
of the address:

>>> host = n & mask
>>> net = n - host

Use the %x (or %X) format conversion to see the result in hex:

>>> print "net: %X host: %X" % (net, host)
net: C0000000 host: A80201


Here's a trickier way to convert a decimal dotted-quad IP address to a hex
string and then to a decimal integer:

>>> # change each decimal portion of IP address to hex pair
>>> hexn = ''.join(["%02X" % long(i) for i in ip.split('.')])
>>> long(hexn, 16)
3232236033L


Enjoy.

Greg Jorgensen
PDXperts LLC
Portland, Oregon USA
gr...@pdxperts.com

Jeroen Wolff

unread,
Jun 15, 2001, 2:31:18 AM6/15/01
to

>
>>>> host = n & mask
>>>> net = n - host

>>>> print "net: %X host: %X" % (net, host)
>net: C0000000 host: A80201
>
Is there a way back to present the calculated results in a doted
decimal notation?

Jeroen

Rikard Bosnjakovic

unread,
Jun 15, 2001, 2:57:47 AM6/15/01
to
Jeroen Wolff wrote:

> Is there a way back to present the calculated results in a doted
> decimal notation?

Greg's code:

>>> import socket, struct


>>> ip = "192.168.2.1"
>>> q = ip.split(".")
>>> n = reduce(lambda a,b: long(a)*256 + long(b), q)
>>> n
3232236033L

Back to dotted:

>>> socket.inet_ntoa(struct.pack('!I', n))
'192.168.2.1'

Alex Martelli

unread,
Jun 15, 2001, 6:15:54 AM6/15/01
to
"Jeroen Wolff" <jwo...@ision.nl> wrote in message
news:vqajitkao6tvll7ad...@4ax.com...

>>> import socket, struct
>>> print socket.inet_ntoa(struct.pack("!L",host))
0.168.2.1
>>>


Alex

Greg Jorgensen

unread,
Jun 16, 2001, 5:22:06 AM6/16/01
to
"Jeroen Wolff" <jwo...@ision.nl> wrote in message
news:vqajitkao6tvll7ad...@4ax.com...

The posted solutions using socket/struct are fine. Here's another way:

---
def numToDottedQuad(n):
"convert long int to dotted quad string"

d = 256 * 256 * 256
q = []
while d > 0:
m,n = divmod(n,d)
q.append(str(m))
d = d/256

return '.'.join(q)
---

Greg Jorgensen
PDXperts LLC
Portland, OR, USA
gr...@pdxperts.com

al.al...@gmail.com

unread,
May 8, 2020, 8:19:33 PM5/8/20
to

Just for the records and to have a fully working bidirectional solution:

>>> ip
'10.44.32.0'
>>> struct.unpack('L', socket.inet_aton(ip))[0]
2108426
>>> socket.inet_ntoa(struct.pack('<L', 2108426))
'10.44.32.0'
>>>

Good luck ;-)

Alan Bawden

unread,
May 9, 2020, 1:07:28 AM5/9/20
to
This will not work as expected on a big-endian machine, because 'L' means
_native_ byte order, but '<L' means little-endian byte order. Better to
use exactly the same format argument for both packing and unpacking. I
would use '!L' for both, since inet_ntoa and inet_aton are defined to work
with IPv4 addresses in _network_ byte order.

--
Alan Bawden

al.al...@gmail.com

unread,
May 9, 2020, 12:23:22 PM5/9/20
to
Hi Alan,

Yes, agreed that any '!I' or '!L' combination will work on different type of platforms in a consistent manner, when applied in both directions.

I was referring to Alex Martelli's output, where the conversion back to IP seems to be reversed, even with '!L', which means that he's already with a little-endian byte order and using 'L' or '<L' for the unpacking...

A more detailed example:
>>> ip = '1.2.168.0'
>>> struct.unpack('L', socket.inet_aton(ip))[0]
11010561
>>> struct.unpack('<L', socket.inet_aton(ip))[0]
11010561
>>> struct.unpack('!L', socket.inet_aton(ip))[0]
16951296
>>>
>>> socket.inet_ntoa(struct.pack('!L',11010561))
'0.168.2.1'
>>> socket.inet_ntoa(struct.pack('<L',11010561)) <-- for that specific case
'1.2.168.0'
>>> socket.inet_ntoa(struct.pack('!L',16951296))
'1.2.168.0'
>>>


Greets,
Alex
0 new messages