?
Solved

Ip address and subnet mask as string

Posted on 2003-03-30
20
Medium Priority
?
867 Views
Last Modified: 2013-11-13
I have twos strings, one holds a valid ip address and the other its subnet mask.
I need the network address ( AND of the two). How can I check that the subnet mask is valid ( all 1's followed by all 0's) and get the network number?
E.g.
IPstr="123.4.5.6"
subnetStr="255.255.0.0"
Should give:
"123.4.0.0" as string (network address)

To validate the subnet mask I can arithematically examine each bit in each component and use a flag to check if its all 1's followed by all 0. Is there an easier way? I am a little lost on how perform the bit wise AND operation on these.

0
Comment
Question by:sambha03
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 3
20 Comments
 
LVL 1

Accepted Solution

by:
SilentRage earned 1200 total points
ID: 8233455
Private Declare Function inet_addr Lib "wsock32.dll" (ByVal cp As String) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Sub Form_Load()
    Debug.Print GetNetworkAddr("255.255.0.0", "123.4.5.6")
End Sub
Private Function GetNetworkAddr(ByVal mask As String, ByVal IP As String) As String
Dim Result As Long, Addr(3) As Byte
    Result = inet_addr(mask) And inet_addr(IP)
    CopyMemory Addr(0), Result, 4
    GetNetworkAddr = Addr(0) & "." & Addr(1) & "." & Addr(2) & "." & Addr(3)
End Function

There you go buddy.  Efficient too.
0
 
LVL 1

Expert Comment

by:SilentRage
ID: 8233460
oh, I guess you want a description of what's up eh?

Well, inet_addr converts a string IP into a long number.  So I convert both mask and IP to long numbers so that I can do the bitwise 'And' on the entire address at once for efficiency.  The Result is the long form of the resulting address you want.  I must however convert it to string form.  I considered different methods and decided that one was both efficient, clean, and easy to understand all in one.

So I used CopyMemory to copy the 4 byte long value to a 4 byte array.  This way I can conveniently insert the bytes into their proper dotted IP positions.  btw, I just realized that you can use a join there too.

take this line

GetNetworkAddr = Addr(0) & "." & Addr(1) & "." & Addr(2) & "." & Addr(3)

replace with this line

GetNetworkAddr = Join(Addr, ".")

:)
0
 

Author Comment

by:sambha03
ID: 8233474
This looks great ..really simple too. I'll try it out. Thanks:-)
Any ideas on how to check if subnet mask is valid?
I know it wasnt a part of the original question but do have any ideas on how validate the ip address too? Looking at this makes me think that maybe I am planning things in a very complicated way. I am planing to use string manipulation to check each component of string for 0-255 range and check number of dots in the address. Is there a simpler way?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 1

Expert Comment

by:SilentRage
ID: 8233536
As for a more efficient means of checking IP validity, I gave you half the answer already.  :)  If inet_addr can't convert and IP address to proper form, it's not a valid IP.  :)  The only problem with that approach is that an IP address takes up the full possible range of values that can be stored in a long.  So the return error (-1 or the IP equivilent 255.255.255.255) may fool you into believing that the IP address is valid.  There's one other quirk about inet_addr.  It accepts partial IP addresses as well (127.0.0.0 = 127.0 = 127 etc).

So here's my recommendation on the most efficient way to verify an IP address.

If inet_addr(IP) <> -1 Or IP = "255.255.255.255" Then
    'valid address
    If Len(IP) = Len(replace(IP, ".", "")) + 3 then
        'verified that there are 3 periods
    End If
End If

probably a lot less code and a lot faster than what you're doing.  :)

as for validating if an IP is apart of the local network... I'll research how that is done and give you the code for that as well.
0
 
LVL 1

Expert Comment

by:SilentRage
ID: 8233568
well, I got tired of messing with bad google results so I sat down and figured things out mathematically/logically.  Here's the fruits of my testing:

Private Declare Function inet_addr Lib "wsock32.dll" (ByVal cp As String) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Sub Form_Load()
Dim NetAddr As Long, TestIP1 As Long, TestIP2 As Long
    'returns: 192.168.1.192 in long form
    NetAddr = GetNetworkAddr("255.255.255.192", "192.168.1.195")

    TestIP1 = inet_addr("192.168.1.205")    'valid IP
    TestIP2 = inet_addr("192.168.1.123")    'invalid IP
    TestIP3 = inet_addr("127.0.0.1")        'another invalid IP

    Debug.Print LongToIP(NetAddr Or TestIP1) '192.168.1.205
    Debug.Print LongToIP(NetAddr Or TestIP2) '192.168.1.251
    Debug.Print LongToIP(NetAddr Or TestIP3) '255.168.1.193
End Sub
Private Function GetNetworkAddr(ByVal Mask As String, ByVal IP As String) As String
    GetNetworkAddr = inet_addr(Mask) And inet_addr(IP)
End Function
Private Function LongToIP(ByVal Address As Long) As String
Dim Addr(3) As Byte
    CopyMemory Addr(0), Address, 4
    LongToIP = Addr(0) & "." & Addr(1) & "." & Addr(2) & "." & Addr(3)
End Function

I figured that the NetAddr is what best represents both the mask and network, so I figured it was the key value to be used in validating other IP's.  Then I tested it against other IP's using AND - but I didn't see any useable patterns.  Then I tried OR and bingo!  If you bitwise or an IP against a network address, and the result is the SAME as the test IP, then it belongs on the network.  Otherwise, it does not.

You can try other IP values to make sure my rule fits all scenarios.  My hunch is that it does.
0
 
LVL 1

Expert Comment

by:SilentRage
ID: 8233573
btw, notice that I used an uncommon (but valid!) subnet mask to be sure the trick worked - and not figure out some logic scheme that only worked with 0 ended masks.
0
 

Author Comment

by:sambha03
ID: 8233598
This is really great :-) You already solved 95% of my problem. I wasnt refering to checking if Ip is in the network address but just checking that the subnet mask is valid ( all 1's followed by all 0's). E.g 255.0.255.255 is invalid mask (1's followed by 0's and again 1's). Other samples are:
255.128.0.0 : valid mask
255.128.0.1 : invalid mask
I appreciate your effort a lot. Thanks for the help. I have increased the points.
0
 
LVL 1

Expert Comment

by:SilentRage
ID: 8233717
oooooooooooooooh, so that's what you were talking about with the 1's and 0's.  heh.  I have a bad habit of ignoring what I don't understand.

but anyway... validating whether a subnet mask is valid.  Well, I spent a long time trying to think of an efficient way, but I'm tired of thinking.  So here's a way:

Private Function ValidMask(ByVal NetMask As String) As Boolean
Dim Mask As Long, BitIndex As Long, Addr(3) As Byte, X As Long, Y As Long
    'This failed before, gotta make it specific
    If NetMask = "255.255.255.255" Then
        ValidMask = True
        Exit Function
    End If

    'It would have to be a valid IP to be a valid mask right?  :)
    If ValidIP(NetMask) Then
        Mask = inet_addr(NetMask)
        'do that array of bytes thing again
        CopyMemory Addr(0), Mask, 4

        'Do the greater than test, an IP segment will never be greater than a previous
        If Addr(0) >= Addr(1) And Addr(1) >= Addr(2) And Addr(2) >= Addr(3) Then
            For X = 0 To 3
                If ValidMask = True And Addr(X) > 0 Then
                    ValidMask = False
                    Exit Function
                ElseIf Addr(X) < 255 Then
                    'make sure the bits are sorted right
                    For Y = 8 To 2 Step -1
                        'If this bit is lower than the next bit - INVALID!!!
                        If (Addr(X) And (Y ^ 2)) < (Addr(X) And ((Y - 1) ^ 2)) Then
                            Exit Function
                        End If
                    Next
                    ValidMask = True
                End If
            Next
        End If
    End If
End Function
0
 
LVL 1

Expert Comment

by:SilentRage
ID: 8233719
oh, forgot to include my ValidIP function.

Private Function ValidIP(ByVal IP As String) As Boolean
    If inet_addr(IP) <> -1 Or IP = "255.255.255.255" Then
       ValidIP = Len(IP) = Len(Replace(IP, ".", "")) + 3
    End If
End Function
0
 

Author Comment

by:sambha03
ID: 8239590
Thanks I got it working.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question