Scanner-library1-in-windows8.gif

Scanner-library-in-windows8.gif

Now that we have an address and subnet, we know exactly what we can do as far as pinging. The next step is to actually start the ping.

We can define a ping as follows:

Dim png As New Net.NetworkInformation.Ping

The Ping.Send method has several overloaded methods but the one that we will use here is Ping.Send(IPAddress). All send methods return a PingReply structure which contains the address and round trip time. So we can send a ping and get a reply which can then be analyzed.

PingReply = png.Send(PingAddress) ' ping the IP and capture the responce

From the address we can then determine the node name like so:

Dim IpToDomainName As IPHostEntry = Dns.GetHostEntry(IP)
'return information about a particular address
Return (IpToDomainName.HostName) ' the name of that node is in that info


Putting all that together we get the following code snippet.

Static row As Long
Dim pr As PingReply ' pinging an address returns a structure called ping reply
Dim ComputerName As String = ""
Timer1.Enabled = False ' since we are doing this periodically on a timer, just disable the timer while we are in here to prevent re-entry
' turn the timer back on when we leave. This ensures the fastest turn around
If DataGridView1.ColumnCount < 3 Then ' initialize the colums of the grid view
DataGridView1.Columns.Add("Column1", "IP")
DataGridView1.Columns.Add("Column1", "Time")
DataGridView1.Columns.Add("Column1", "Name")
End If

If txtIP.Text <> "" Then ' if there is an IP selected
If PingAddress = "" Then ' if the ping address is empty
PingAddress = txtIP.Text ' fill it from the text box otherwise just ping the address in the box (for inrementing the address
If Not FindAddressBytes() Then ' convert the IP address into a four byte array
Exit Sub 'if that didn't work . . . give up
End If
End If
Else
PingAddress = ""
End If
Try
ToolStripStatusLabel2.Text = "initializing" ' inform the user
RebuildPingAddress() ' this reconverts the address from four byte array back to a string (after we have automatically incremented it
txtIP.Text = PingAddress ' show the user where we are
' we are now ready to send a ping to see if anyone is home
'Dim png As New Net.NetworkInformation.Ping
pr = png.Send(PingAddress) ' ping the IP and capture the responce
ToolStripStatusLabel2.Text = "pinging " & PingAddress
If pr.Status = IPStatus.Success Then ' if the responce was good
DataGridView1.Rows.Add() ' we should add a new row to the grid view
DataGridView1.Rows(row).Cells(0).Value = pr.Address ' and fill that row in with address
DataGridView1.Rows(row).Cells(1).Value = pr.RoundtripTime.ToString & " ms" ' round trip time
' we should now show the name of the device / computer at that address
ComputerName = DoGetHostEntry(pr.Address.ToString)
DataGridView1.Rows(row).Cells(2).Value = ComputerName ' display that nodes name
'b = pr.Buffer ' the buffer contains the returned data from the ping (most often just a series of bytes
If Not active Then ' allow the user to cancel
ToolStripStatusLabel2.Text = "User Canceled"
Exit Sub

End If

So we have 'pinged' our own address and found that we are there. It didn't take all that code to figure that out. What we would like to know is whether or not there are others on the same network. That's the same only a different address. If we knew all the addresses that were on the network, we would just make a list and ping them but we don't. Therefore we must ping all addresses that are within the range of our subnet by incrementing the address after each ping. If the ping is successful then we add that info to the list and keep going.

Of course 'if it is worth doing, it is worth overdoing . . . we might like to see what ports are open and thus vulnerable. This can be done in the straightforward / slow manner by trying to open every port from 0 to 65535. If it connects then that port is open. If an error occurs that port is not open. Opening a port that is available is quite quick. If all ports were open this would be fast and furious but any time the port is not open, it takes atleast a second to throw an error, So we are looking at more that 65000 seconds to check a normal node and there are usually more than one nodes.

I think I just fell asleep thinking about all that waiting . . . excuse me while I make some coffee.

If you are only checking a few of the more commonm nodes there is no need to get fancy so lets look at the easy way first.
To check to see if a port is open you can use the TCPClient.Connect method:

'instanciate a new instance of the TCPClient Class
' try to use the connect method to connect to the particular port on the particular address
' if the connection worked
' close the connection since we really don't need to do anything more
' mark the status as connected
' if an exception occured then the port os not open
' clear the error for general principals
' mark it as not open
Dim TCP As TcpClient = New TcpClient()

Try

TCP.Connect(IPAddress, p.Portid)

If TCP.Connected Then

TCP.Close()

ClassStatus = ClassStatusEnum.DoneConnected

End If

Catch ex As Exception
Err.Clear()
ClassStatus = ClassStatusEnum.DoneNotConnected
End Try

Of course we now need to write code that checks each port one at a time to see if the call (to the previous code) suceeded in connecting. Pretty straight forward, so I won't go deeply into the details except that you need to pass it two lists of PortStruct (Int32 PortNumber, and String PortUsage ). The first list is a list of ports to check passed by value. The second is a list to be filled in of ports that are open and is therefore passed by referance (pointer). Check each port in sequence and if it connected add it to the list of open ports and voila (as they say somewhere).

Private Function SlowCheckThem(ByVal PortsToTest As List(Of PortStruct), ByVal openPorts As List(Of PortStruct)) As Boolean
Dim rv As Boolean = False
Dim c() As clsCheckPort = Nothing ' create an array of clsCheckPort
Dim prt As PortStruct
Dim j As Integer = 0
Dim ThreadArray() As Thread ' Create an array of Threads

Try

For Each p As PortStruct In PortsToTest ' check each port
ReDim Preserve c(j) ' instanciate a clsCheckPort for each port to check
ReDim Preserve ThreadArray(j) ' instanciate a threasd for each port to check
c(j) = New clsCheckPort(PingAddress, p.PortId)
c(j).CheckPort() ' start the thread . . . passing the port structure to the thread
j += 1
Application.DoEvents()
Next
For i As Integer = 0 To j - 1 ' check each instance of the class
If c(i).CheckStatus = clsCheckPort.ClassStatusEnum.DoneConnected Then 'if the status nis done and connected
prt.PortId = c(i).Port ' create and fill in a structure
prt.PortUse = c(i).PortUse
openPorts.Add(prt) ' to add it to the openPorts list
End If
Application.DoEvents()
Next
rv = True
Catch ex As Exception

End Try
Return rv
End Function

If you want to check a lot of ports (for instance . . . all of them), you won't use the previous method. You will want to create a bunch (an array) of threads that will each check one port. Give it a small amount of time to finish checking and then check the results.

Private Function CheckThem(ByVal PortsToTest As List(Of PortStruct), ByVal openPorts As List(Of PortStruct)) As Boolean
Dim rv As Boolean = False
Dim c() As clsCheckPort = Nothing ' create an array of clsCheckPort
Dim prt As PortStruct
Dim j As Integer = 0
Dim ThreadArray() As Thread ' Create an array of Threads

Try

For Each p As PortStruct In PortsToTest ' check each port
ReDim Preserve c(j)
ReDim Preserve ThreadArray(j)
c(j) = New clsCheckPort(PingAddress, p.PortId) ' instanciate a clsCheckPort for each port to check
ThreadArray(j) = New Thread(AddressOf c(j).CheckPort) ' instanciate a threasd for each port to check
ThreadArray(j).Start() ' start the thread
j += 1
Application.DoEvents()
Next
Wait(1000) ' give the last thread a moment ot complete
For i As Integer = 0 To j - 1 ' check each instance of the class
If c(i).CheckStatus = clsCheckPort.ClassStatusEnum.DoneConnected Then 'if the status nis done and connected
prt.PortId = c(i).Port ' create and fill in a structure
prt.PortUse = c(i).PortUse
openPorts.Add(prt) ' to add it to the openPorts list
End If
Application.DoEvents()
Next
rv = True
Catch ex As Exception

End Try
Return rv
End Function

To check many ports efficiently and quickly we pass a different function the same lists as before. In the function we first create an array of the class that does the work and then we create an array of threads to do the work. Loop through and start all the threads. While you are busy starting one thread, the previous thread will have been working its magic. If it connects, it will probably be done before you call the next thread. if not . . . who cares?

When you finish calling the last thread, just wait for a moment (a few milliseconds) to let the last few threads connect if they can. Then start checking the class array to see who has connected. Fill the open list in and voila (as they say somewhere else). The rest is just normal code.