Results 1 to 3 of 3

Thread: [RESOLVED] Convert CIDR To Subnet Range (IPv4)

  1. #1

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Resolved [RESOLVED] Convert CIDR To Subnet Range (IPv4)

    A friend at work asked if I knew how to extract the subnet range from a CIDR format. For those that don't know, CIDR is simply an IP address followed by a mask bit count (192.10.25.33/28).

    After looking about, I found some truly complicated methods that convert IPs and masks to binary representations as strings, performing XOR, AND operations on the string characters, and other crazy stuff.

    I think I've discovered a really short simple solution and would like input before I pass it off to that friend. Specifically, I have two questions:

    1) Do you see anything wrong with the logic?
    2) Stupid question maybe, but here I'll show my ignorance. Would network byte order affect the logic on how the mask is created, i.e., little/big endian?

    Site I used to test my results: http://www.subnet-calculator.com/

    Add this to a module and from your immediate window (Ctrl+G), simply pass it some CIDR formats, i.e.,
    TestIt "126.192.22.254/30"
    Code:
    Public Sub TestIt(CIDR As String)
    
        ' CIDR format: xxx.xxx.xxx.xxx/mask bit count
        ' IP octets do not need leading zeros
        ' mask bit count must be between 8 and 32 inclusively
        
        Dim lMask As Long, lMskWildCard As Long
        Dim lIP As Long, sTokens() As String
        Dim x As Long, lMin As Long, lMax As Long
        
        x = InStr(CIDR, "/")
        If x = 0 Then
            MsgBox "Invalid CIDR format passed"
            Exit Sub
        End If
        
        lMask = Val(Mid$(CIDR, x + 1))
        If lMask < 8 Or lMask > 32 Then
            MsgBox "Invalid CIDR mask passed"
            Exit Sub
        End If
        
        sTokens() = Split(Left$(CIDR, x - 1), ".")
        If UBound(sTokens) <> 3 Then 
            MsgBox "Invalid CIDR format passed"
            Exit Sub
        End If
        
        lMskWildCard = 2& ^ (32& - lMask) - 1&
        lMask = &HFFFFFFFF And Not lMskWildCard
        
        On Error GoTo ErrHandler
        lMax = &H10000
        For x = 1 To 3
            lMin = CLng(sTokens(x))
            If lMin < 0 Or lMin > 255 Then Err.Raise 5
            lIP = lIP Or lMin * lMax
            lMax = lMax \ &H100&
        Next
        
        lMax = (lIP And lMask) Or lMskWildCard Or CLng("&H" & Hex(sTokens(0)) & "000000")
        lMin = (lIP And lMask) Or ((lIP And (lMskWildCard Xor -1&)) And lMskWildCard) Or CLng("&H" & Hex(sTokens(0)) & "000000")
        
        Debug.Print "Min/Max Range: "; _
            sTokens(0); "."; _
            CStr((lMin And &HFF0000) \ &H10000); "."; CStr((lMin And &HFF00&) \ &H100); "."; CStr(lMin And &HFF); " thru "; _
            sTokens(0); "."; _
            CStr((lMax And &HFF0000) \ &H10000); "."; CStr((lMax And &HFF00&) \ &H100); "."; CStr(lMax And &HFF)
            
    ErrHandler:
        If Err Then
            Err.Clear
            MsgBox "Invalid CIDR IP address passed"
        End If
    End Sub
    I haven't decided how I want to return the min/max range (string/Long) & will do that once you network gurus give this a thumbs up. Thank you

    Some notes.
    1. This isn't a subnet calculator, so no verification of mask to network class is being performed. The data being sent to this routine would be real-world CIDR. Because of this, a 31-bit mask is not trapped as a 'bad format'. That being said, all the sanity checks in the code are primarily for testing only. The format of the CIDR will eventually be validated (in case of garbled data) before the function is ever called.
    2. Number of usable hosts would equate to lMax - lMin -1 except that a 32-bit mask would result in just 1 host
    3. The first useable host would be lMin+1 and last would be lMax-1. lMin would be the subnet ID and lMax would be the broadcast address
    Last edited by LaVolpe; Apr 16th, 2015 at 12:55 PM. Reason: fixed typos
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  2. #2

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Convert CIDR To Subnet Range (IPv4)

    I'll mark this resolved, but if anyone sees an issue, please post it here. The code appears to be working, I just don't want to leave my buddy hanging if there is a logic flaw
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3
    New Member
    Join Date
    Feb 2011
    Posts
    3

    Re: [RESOLVED] Convert CIDR To Subnet Range (IPv4)

    this post is a few years old but i just found it a few days ago and the posted code works great. The vb guru king lavolpe has come to the rescue once again. I was using a free service to find city country from IP with a call from VB6 inet but the service was missing in action last attempt so I thought I would try to knock out a quick solution in VB as i had previously done a country from IP a while back. Well, the country/city is not so easy as it requires the CIDR formula which, as lavolpe mentioned is complex. I have no idea HOW it works but I plugged in the lavolpe code and was good to go. Now i can see a list of where my users are from country/city without rely on third party service which can vanish at any time.

    And thank you for the vb png which I also used in my bg game greedygammon (written in VB-5/6). As soon as i saw "lavolpe" in the CIDR search results from google i was like YESSS!! and was not disappointed

    It took a while to get everything to work as the csv file from maxmind was 220 megs and VB6 tapped out under that load so I had to break up the file into 5 parts and ran a separate exe for each one. Only took about 2 minutes to process on my slow i3 machine but good enough for what i use it for
    cheers,

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width