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)

David Silveiro
  • 1,515
  • 1
  • 15
  • 23
Ofer Arial
  • 1,129
  • 1
  • 10
  • 25

3 Answers3

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 :)

Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
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('.')])
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
  • 1
    I tried that, but I get '\\xc0\\xa8\\x00\\x01' which is not equal to '\xc0\xa8\x00\x01' . Is it the same? – Ofer Arial Jan 15 '17 at 17:54
  • 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. – Stephen Rauch Jan 15 '17 at 17:57
  • 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`? – Ofer Arial Jan 15 '17 at 18:01
  • 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. – Stephen Rauch Jan 15 '17 at 18:08
  • Thanks for your answer! – Ofer Arial Jan 17 '17 at 19:05
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.

jtpereyda
  • 6,987
  • 10
  • 51
  • 80