|
-
Apr 15th, 2015, 11:01 PM
#1
[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
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|