简体   繁体   中英

Convert CIDR notation into IP range

We are using the GeoLite2 database in order to implement an IP -> country lookup. For performance reasons, we want to import the CSV and convert it to our own format.

The CSV is represented like this:

5.39.40.96/27,3017382,3017382,,0,0
5.39.40.128/28,3017382,3017382,,0,0
5.39.40.144/28,2635167,3017382,,0,0
5.39.40.160/27,3017382,3017382,,0,0
5.39.40.192/26,3017382,3017382,,0,0
5.39.41.0/25,3017382,3017382,,0,0
5.39.41.128/26,3017382,3017382,,0,0
5.39.41.192/26,2635167,3017382,,0,0
5.39.42.0/24,3017382,3017382,,0,0
5.39.43.0/25,3017382,3017382,,0,0

So we need to convert the CIDR notation ( example: 5.39.40.96/27 ) into an IP address range. (From IP - To IP)

How can this be done in C#?

Note: This is not a duplicate of this question , since I'm asking about a C# implementation and not Java.

Here is one way to handle it, without using any library functions to make it clear what's happening and to help if someone needs to implement it in other languages later on.

The code first converts the CIDR into a 32bit number, then creates the mask to determine the start address, uses the inverse of the mask to determine the end address and then converts back to CIDR format.

Note that there is no error detection so the input must be in the abcd/m format.

The conversion of the IP address is just a simple concatenation of the four octets in big endian form (AABBCCDD) using bit shifts.

The mask tells how many bits from the most significant bit are fixed, meaning 32 is a single IP range and 0 would be the whole IP range. Thus we can take a mask with all bits set and shift it left with 32-maskbits to determine the actual mask.

If we set the maskbits bits to zero, we get the beginning of the range, so we AND the IP with maskbits. If we set the bits to one, we get the end of the range, so we will OR with the negated bits of mask.

Printing the IP address in CIDR format is again simple: just split the 32bit value into octets and write them separated with dots.

using System;

namespace CSTests
{
    class Program
    {
        static string toip(uint ip)
        {
            return String.Format("{0}.{1}.{2}.{3}", ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
        }

        static void Main(string[] args)
        {
            string IP = "5.39.40.96/27";
            string[] parts = IP.Split('.', '/');

            uint ipnum = (Convert.ToUInt32(parts[0]) << 24) |
                (Convert.ToUInt32(parts[1]) << 16) |
                (Convert.ToUInt32(parts[2]) << 8) |
                Convert.ToUInt32(parts[3]);

            int maskbits = Convert.ToInt32(parts[4]);
            uint mask = 0xffffffff;
            mask <<= (32 - maskbits);

            uint ipstart = ipnum & mask;
            uint ipend = ipnum | (mask ^ 0xffffffff);

            Console.WriteLine(toip(ipstart) + " - " + toip(ipend));
        }
    }
}

Output:

5.39.40.96 - 5.39.40.127

Sami Kuhmonen, this is very nice code and seriously simplified. I noticed that it returns the network ID and the broadcast. However, for those that wish for it to return the usable address space. Simply add one to the starting IP and subtract one from the ending IP.

toip(ipstart + 1) + " - " + toip(ipend -1);

Here your answer is not correct Network ID should be: 5.39.40.64 and Broadcast ID shoudl be: 5.39.40.95 and Usable IP : 5.39.40.65 to 5.39.40.94

I calculated also in Advance Subnet Calculator, you can see result in picture enter image description here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM