Exploding IPv4 ranges using Swift. 💥
How to generate an Array of all IP addresses contained within a range using Swift
Recently while working on a pet project using SwiftNIO, I found that I had the need to expand an IPv4 set defined as a range into an Array of IP addresses.
I took to the googles, but alas, I couldn’t find any pre-existing modules or code examples for doing this in Swift. I also took a brief read of Apple’s new Network.framework which introduces a new IPAddress Type and some other neat stuff… but it didn’t include support for the functionality I was looking for. 😔
I’ve use python libraries such as ipaddress, numerous times in the past for projects like this. Like a good library should, they always abstract how things work under the hood and just leave you with a simple method or two that can be used to accomplish most tasks.
How hard could it be to do a simplified version myself? As it turns out, not too hard once you try doing things the wrong way a few times.
After a couple ill-fated attempts to use fancy iteration and nesting of the different octet levels, it dawned on me …
”IP addresses are really just big numbers expressed in an easier-to-communicate wrapper” 🧐
It’s true. IPv4 addresses are just integers between 1 and 4,294,967,296 (IPv4 address space), expressed as 4 8-bit numbers (Octets) separated by periods.
Knowing this, the problem becomes far simpler. To explode an IP range into a list its constituent addresses you just need to follow a few simple steps.
- Convert your upper and lower bounds to integers.
- Build an array containing all integers between the upper and lower bounds.
- Iterate over the array converting integers back into IPv4 format.
I wrote several functions that accomplish these steps using a couple different methods.
IP to Integer
Going from IPv4 to an integer isn’t too complicated. I looked at a couple ways to do this.
The first way is a bit more detailed, but may be easier to understand for some. It works by iterating over the octets in an IP address and multiplying each by the next power of 256. This works because IP addresses are base 256.
Alternatively you can also use bit shifting operators in Swift to accomplish this. As you can see our general function looks pretty similar, however, instead of doing arithmetic we’re just shifting bits around.
Integer to IP
This was the trickier part in my opinion. Again we can do this either by reversing the powers of 256 operation from earlier or using bitshifting. However, unlike going from IP to Int, in this case bitwise operations are clearly less complex.
The basic idea for using powers of 256 here is to use a loop to extract one octet of the original IP during each iteration, from most significant to least significant. It gets a little messy because the first octet and the final octet necessarily need to be dealt with differently than the middle two octets.
Luckily the bitwise function to do this is MUCH easier. Here we’re just doing a shift operation and a bitwise AND to determine each octet value.
Putting it all together
This is really the easy part and should work regardless of the combination of methods used above.
And there you have it, simple IPv4 range expansion using Swift. If you know of any more elegant or efficient ways to do this please share in the comments.