I leave notes here that I find particularly worth remembering myself.
CIDR to Netmask conversion with Python (convert short netmask to long, dotted format)
Tags linux, networking, python
When you write scripts dealing with setting up or analyzing network interfaces you will eventually run into the task of converting a netmask from one format into another.
Typically, the setup of an ethernet TCP/IP network interface consists of an IP address, a netmask, and a broadcast address. Unfortunately for you as a novice, the two tools ifconfig and ip show the same (or similar) information in a different format.
Here, ifconfig says "addr:146.112.129.3 ... Mask:255.255.224.0", ...
... whereas ip addr spits out "146.112.129.3/19" for one and the same network interface. I usually refer to the above output as "dotted notation" and the latter one as the "short netmask", officially called "CIDR format" to my knowledge, which is practically the number of 1's (0-32) in the binary netmask.
If your software expects a dotted notation, but all you get from the source you analyze is the short CIDR number, go and convert it. But how?
Some Python code to make you happy
Don't be surprised, I've found no small and easy-to-grasp code snippet on the Internet, you won't probably either. That's a bit strange, especially because in the end a simple solution is not that difficult to implement. Here is my approach using Python:
The main idea is: The binary netmask contains all 1-bits on the left side, and all 0-bits on the right side - no mixing -, and the CIDR number counts those 1-bits. So, from left to right, ...
Of course, you can implement this simple algorithm in any other language you like. All by yourself, naturally.
Side note
Note in the above sample output of ifconfig and ip that ip lists an additional network interface as compared to ifconfig. Both commands have been executed on one and the same machine, directly one after the other.
The reason for this may be one of the reasons you may start considering ip as a tool over ipconfig for some tasks, as I did: ip also list interfaces that are not active or configured. With ip -o link, for example, you can get the MAC addresses of all available interfaces (in a single-line format convenient for post-processing), regardless to whether they are already configured or not.
References
Typically, the setup of an ethernet TCP/IP network interface consists of an IP address, a netmask, and a broadcast address. Unfortunately for you as a novice, the two tools ifconfig and ip show the same (or similar) information in a different format.
Quote:
$ /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 00:d0:c9:a5:99:f4
inet addr:146.112.129.3 Bcast:146.112.159.255 Mask:255.255.224.0
inet6 addr: fe80::2d0:c9ff:fea5:99f4/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:14706157 errors:0 dropped:0 overruns:0 frame:0
TX packets:11728631 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:3127295322 (2.9 GiB) TX bytes:984587855 (938.9 MiB)
Memory:fd8e0000-fd900000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:890946 errors:0 dropped:0 overruns:0 frame:0
TX packets:890946 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:433573498 (413.4 MiB) TX bytes:433573498 (413.4 MiB)
eth0 Link encap:Ethernet HWaddr 00:d0:c9:a5:99:f4
inet addr:146.112.129.3 Bcast:146.112.159.255 Mask:255.255.224.0
inet6 addr: fe80::2d0:c9ff:fea5:99f4/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:14706157 errors:0 dropped:0 overruns:0 frame:0
TX packets:11728631 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:3127295322 (2.9 GiB) TX bytes:984587855 (938.9 MiB)
Memory:fd8e0000-fd900000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:890946 errors:0 dropped:0 overruns:0 frame:0
TX packets:890946 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:433573498 (413.4 MiB) TX bytes:433573498 (413.4 MiB)
Quote:
$ /sbin/ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 100
link/ether 00:d0:c9:a5:99:f4 brd ff:ff:ff:ff:ff:ff
inet 146.112.129.3/19 brd 146.112.159.255 scope global eth0
inet6 fe80::2d0:c9ff:fea5:99f4/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 00:d0:c9:a5:99:f5 brd ff:ff:ff:ff:ff:ff
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 100
link/ether 00:d0:c9:a5:99:f4 brd ff:ff:ff:ff:ff:ff
inet 146.112.129.3/19 brd 146.112.159.255 scope global eth0
inet6 fe80::2d0:c9ff:fea5:99f4/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 00:d0:c9:a5:99:f5 brd ff:ff:ff:ff:ff:ff
If your software expects a dotted notation, but all you get from the source you analyze is the short CIDR number, go and convert it. But how?
Some Python code to make you happy
Don't be surprised, I've found no small and easy-to-grasp code snippet on the Internet, you won't probably either. That's a bit strange, especially because in the end a simple solution is not that difficult to implement. Here is my approach using Python:
Code:
# CIDR to Netmask conversion # (c) 2010 Peter Bittner, http://linux.bittner.it/blog # # Tip for an excellent background read: "IP subnetting made easy" # http://articles.techrepublic.com.com/5100-10878_11-6089187.html def len2mask(len): """Convert a bit length to a dotted netmask (aka. CIDR to netmask)""" mask = '' if not isinstance(len, int) or len < 0 or len > 32: print "Illegal subnet length: %s (which is a %s)" % (str(len), type(len).__name__) return None for t in range(4): if len > 7: mask += '255.' else: dec = 255 - (2**(8 - len) - 1) mask += str(dec) + '.' len -= 8 if len < 0: len = 0 return mask[:-1] # Example for len in range(32,-1,-1): print '/%d = %s' % (len, len2mask(len))
- As long as we can subtract 8 bits we have a byte full of ones, which corresponds to '255' in decimal. Dot (full stop).
- As soon as we hit zero all other pieces in the dotted format will be '0'.
- The tricky part comes when the CIDR netmask is not a multiple of 8, then we must calculate the power of the remainder (= CIDR number modulo 8) to the base of 2 - BUT: the 1-bits in the binary string are on the wrong side here, beware! That's how we arrive at: 255 - (2^(8 - remainder) - 1)
Of course, you can implement this simple algorithm in any other language you like. All by yourself, naturally.
Side note
Note in the above sample output of ifconfig and ip that ip lists an additional network interface as compared to ifconfig. Both commands have been executed on one and the same machine, directly one after the other.
The reason for this may be one of the reasons you may start considering ip as a tool over ipconfig for some tasks, as I did: ip also list interfaces that are not active or configured. With ip -o link, for example, you can get the MAC addresses of all available interfaces (in a single-line format convenient for post-processing), regardless to whether they are already configured or not.
References
- IP subnetting made easy (A nice tutorial on TechRepublic)
- CIDR = Classless Inter-Domain Routing (Wikipedia)
- ip (manpage), ip shows us ... (Linux Advanced Routing & Traffic Control HOWTO)
Total Comments 0