I l@ve RuBoard

Credit: Alex Martelli, Greg Jorgensen

#### 10.6.1 Problem

You need to convert IP addresses from dotted quads to long integers and back, and extract network and host portions of such addresses.

#### 10.6.2 Solution

The socket and struct modules let you easily convert long integers to dotted quads and back:

```import socket, struct

"convert decimal dotted quad string to long integer"
return struct.unpack('>L',socket.inet_aton(ip))[0]

"convert long int to dotted quad string"
return socket.inet_ntoa(struct.pack('>L',n))```

To split an IP address into network and host portions, we just need to apply a suitable binary mask to the long integer form of the IP address:

```def makeMask(n):
"return a mask of n bits as a long integer"
return (2L<<n-1)-1

# by Greg Jorgensen

host = n & m
net = n - host

#### 10.6.3 Discussion

The format we use for the struct.pack and struct.unpack calls must start with a '>', which specifies big-endian byte order. This is the network byte order used by the socket.inet_aton and socket.inet_ntoa functions. If you omit the '>', struct instead uses the native byte order of the machine the code is running on, while the socket module still uses big-endian byte order.

The network part of an IP address used to be expressed as an explicit bit mask (generally also in dotted-quad form) such as:

`'192.168.23.0/255.255.255.0'`

However, the bit mask invariably had a certain number (N) bits that were 1 followed by 32-N bits that were 0. The current form, which is much more compact and readable, is therefore structured like:

`'192.168.23.0/24'`

The part after the / is just N: the number of bits that must be 1 in the mask. If you know about a network that is expressed in this form, you can use the functions in this recipe to check if a host is within that network:

```def isHostInNet(host_ip, net_ip_with_slash):