3

I want to kind of implement my own struct.pack specific function to pack an IP string (i.e. "192.168.0.1") to a 32-bit packed value, without using the socket.inet_aton built in method.

I got so far:

ip = "192.168.0.1"
hex_list = map(hex, map(int, ip.split('.')))
# hex list now is : ['0xc0', '0xa8', '0x0', '0x01']

My question is: How do I get from that ['0xc0', '0xa8', '0x0', '0x01'] to '\xc0\xa8\x00\x01', (this is what I'm getting from socket.inet_aton(ip)?

(And also - How is it possible that there is a NUL (\x00) in the middle of that string? I think I lack some understanding of the \x format)

3 Answers 3

2

You can use string comprehension to format as you like:

ip = "192.168.0.1"
hex_list = map(int, ip.split('.'))
hex_string = ''.join(['\\x%02x' % x for x in hex_list])

or as a one liner:

hex_string = ''.join(['\\x%02x' % int(x) for x in ip.split('.')])
Sign up to request clarification or add additional context in comments.

5 Comments

I tried that, but I get '\\xc0\\xa8\\x00\\x01' which is not equal to '\xc0\xa8\x00\x01' . Is it the same?
the \\ is just Python's way of showing you a single \ . change the '\\x%02x' to r'\x%02x' and note that you get the same result.
I know that, but will it be the same when I send this address over? Will it be the same as the value recieved by socket.inet_aton?
escaping strings is somewhat of a black art. the answer is: it depends. Every step along the way you have the potential for someone to interpret the string and thus need some sort of escaping. I was simply answering your question of how to get the indicated string.
Thanks for your answer!
2

An alternative:

Can you use ipaddress and to_bytes (python 3.2)?

>>> import ipaddress
>>> address = ipaddress.IPv4Address('192.168.0.1')
>>> address_as_int = int(address)
>>> address_as_int.to_bytes(4, byteorder='big')
b'\xc0\xa8\x00\x01'

Note that you may actually only need the integer.

Can be shorter obviously, but wanted to show all steps clearly :)

Comments

1

Based loosely off @Stephen's answer but returns a string with the actual bytes rather than a string with literal slashes:

def pack_ip(ip):
    num_list = map(int, ip.split('.'))
    return bytearray(num_list)

src_ip = pack_ip('127.0.0.255')
print(repr(src_ip))

Works in Python 2 and 3. Returns a b'' rather than a string, matching best practice for Python3.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.