IPv4 Address
Introduction
Here are a few programs to help us understand IPv4 addresses.
Prefix Notation
You may see “CIDR” notation in the literature. The CIDR notation and the
prefix notation are the same notation, i.e., the notation of ip address/prefix
length
. Given this notation, we can obtain the network number, the host
number, and the broadcast address for the network. Below is the program
(ipv4netbrdfromprefix.py
) that obtains the network number and the broadcast
address from a prefix notation of an IPv4 address.
import sys
import socket
def get_netnum_brdaddr(addr, plen):
netnumi = int.from_bytes(addr, byteorder='big') >> (32 - plen) << (32 - plen)
nmaski = 0xffffffff >> plen
brdaddri = netnumi | nmaski
netnum = netnumi.to_bytes(4, byteorder='big')
brdaddr = brdaddri.to_bytes(4, byteorder='big')
return netnum,brdaddr
def usage(prog):
print('Usage: ' + prog + ' ipv4address/prefix', file=sys.stderr)
def main(argv):
if len(argv) < 2:
usage(argv[0])
sys.exit(1)
addrp,plenp = sys.argv[1].split('/')
addr = socket.inet_pton(socket.AF_INET, addrp)
plen = int(plenp)
netnum,brdaddr = get_netnum_brdaddr(addr, plen)
print(netnum, socket.inet_ntop(socket.AF_INET, netnum))
print(brdaddr, socket.inet_ntop(socket.AF_INET, brdaddr))
# to run as a script
if __name__ == '__main__':
main(sys.argv)
Network Mask Notation
Network mask is a concept predates the CIDR or the prefix notation. Commonly,
we choose a network mask whose binary representation consits of consecutieve 1’s
followed by consecutive 0’s. In this case, there is a equivalent prefix
notation with the prefix length as the number of the consecutive 1’s. However,
it is we who impose such a restriction on network masks when we select one, and
although uncommon, we can legitimately select a network mask that doesn’t have
consecutive 1’s, e.g. 255.0.255.0 (in the dotted decimal notation). Below is a
program (ipv4netbrdfrommask.py
) that obtains the network number and the
broadcast address from an address with its network mask.
import sys
import socket
def get_netnum_brdaddr(addr, mask):
netl = []
brdl = []
for a,m in zip(addr,mask):
netl.append(a & m)
brdl.append(a | (~m & 0xff))
netnum = bytes(netl)
brdaddr = bytes(brdl)
return netnum,brdaddr
def usage(prog):
print('Usage: ' + prog + ' ipv4address ipv4netmask', file=sys.stderr)
def main(argv):
if len(argv) < 3:
usage(argv[0])
sys.exit(1)
addr = socket.inet_pton(socket.AF_INET, argv[1])
mask = socket.inet_pton(socket.AF_INET, argv[2])
netnum,brdaddr = get_netnum_brdaddr(addr, mask)
print(netnum, socket.inet_ntop(socket.AF_INET, netnum))
print(brdaddr, socket.inet_ntop(socket.AF_INET, brdaddr))
# to run as a script
if __name__ == '__main__':
main(sys.argv)
Exercises and Exploration
Let’s consider the following questions.
- When we run
ipv4netbrdfromprefix.py
as the following example,$ python ipv4netbrdfromprefix.py 192.168.7.101/23 b'\xc0\xa8\x06\x00' 192.168.6.0 b'\xc0\xa8\x07\xff' 192.168.7.255
It is correctly to state that
192.168.6.0
is the network number and192.168.7.255
is the broadcast address for192.168.7.101/23
? - We make a comment in the above that a network mask does not have to be in the form of consecutive 1’s followed by consecutive 0’s. However, in practive, we almost always do. Why?
- Write a program (or a few programs) to report the type of an IPv4 address, i.e., whether the address is a unicast address, a broadcast address, a multicast address, a Document address, or a reserved address and if it is a unicast address, whether it is a private network address, a link-local address, a loop back address, or a global unicast address?