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?
- Can you 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?.