Getting the ISP from the IP

Published 2006-05-22. Read 4,341 times. 0 Comments. Tagged: ip isp programming vb.net webdev

Following on from my last article on getting the correct IP address from your user, its time to take it a little further with some whois lookups.

Click here for a demo of IPLookup

A whois lookup *can* tell you lots of information about the users IP address. It can tell you the owner of the IP, the country, a short description about the owner or organisation using it. If its owned by a company, it can even give you the address.

So what? Well unless you’re doing some stats, it really hasn’t got more use then just being cool. You’ll be able to tell where people are, sometimes to their doorstep.

My code below is a complete VB.net class. You should be able to drag and drop it into your projects. A sample on how to trigger it:

Dim ipl As New IPLookup("81.15.12.4")
Response.Write("Your ISP is " & ipl.ISP)

Of course this is a very simplified example. I will expand the code at a later date to include a bit of caching to stop the server doing lookup after lookup. Note this is released under a Non-Commercial Share-Alike Creative Commons License. If you need it under a different license, just contact me.

Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Text.RegularExpressions

Public Class IPLookup

#Region " Public Property-Vars and properties "
    Private _IP As String
    Public Property IP() As String
        Get
            Return _IP
        End Get
        Set(ByVal value As String)
            _IP = value
            ParseAndLookup()
        End Set
    End Property

    Private _ISP As String
    Public ReadOnly Property ISP() As String
        Get
            Return _ISP
        End Get
    End Property

    Private _ISPDescription As String
    Public ReadOnly Property ISPDescription() As String
        Get
            Return _ISPDescription
        End Get
    End Property

    Private _Country As String
    Public ReadOnly Property Country() As String
        Get
            Return _Country
        End Get
    End Property

    Private _Service As String
    Public ReadOnly Property Service() As String
        Get
            Return _Service
        End Get
    End Property

    Private _ServiceText As String
    Public ReadOnly Property ServiceText() As String
        Get
            Return _ServiceText
        End Get
    End Property
#End Region

#Region " Private Class Variables "
    ' IP segments
    Private _IPSeg(4) As Integer

    ' Sites to do the lookup
    Private sites() As String = {"whois.apnic.net", _
                                 "whois.ripe.net", _
                                 "whois.arin.net"}
#End Region

    Public Sub New(ByVal thisIP As String)
        _IP = thisIP
        ParseAndLookup()
    End Sub

    Private Sub ParseAndLookup()
        ' Precondition: If IP is invalid, set error and exit
        If Not ParseIP() Then
            SetError()
            _ISP = "Broke at parse"
            Exit Sub
        End If

        ' Defined here to keep in scope later on
        Dim tempStore As String = String.Empty
        Dim strDomain As String = _IP & vbCrLf
        Dim arrDomain As Byte() = Encoding.ASCII.GetBytes(strDomain)

        Dim i As Integer ' dim here for scope
        For i = 0 To _IPSeg.Length
            ' Make a TCPClient and connect
            Dim tcpC As New TcpClient(sites(i), 43)
            Dim tcpStream As Stream = tcpC.GetStream

            ' Write the IP into the stream
            tcpStream.Write(arrDomain, 0, strDomain.Length)

            ' Read the return stream into a string
            Dim objSR As New StreamReader(tcpStream, Encoding.ASCII)
            tempStore = objSR.ReadToEnd

            ' Close the stream
            tcpC.Close()

            ' See if we have a winner yet
            Select Case i
                Case 0 ' Apnic
                    If Not (tempStore.Contains("RIPE") Or _
                            tempStore.Contains("arin")) Then
                        Exit For
                    End If
                Case 1 ' Ripe
                    If Not (tempStore.Contains("iana") Or _
                            tempStore.Contains("arin")) Then
                        Exit For
                    End If
                Case 2 ' Arin
                    If Not (tempStore.Contains("RIPE") Or _
                            tempStore.Contains("apnic")) Then
                        Exit For
                    End If
            End Select
        Next

        ' Store the service used into private var
        _Service = sites(i)

        ' Store the raw text
        _ServiceText = tempStore

        ' Get the data from the result
        Dim pat As String = "(?:netname:\s+(?<nname>.*)\s+" & _
                            "(?:descr:\s+(?<ndesc>.*)\s+)+" & _
                            "country:\s+(?<ncoun>.*)\s+)|" & _
                            "(?:OrgName:\s+(?<nname>.*)\s+" & _
                            "OrgID:\s+(?<ndesc>.*)\s+.*" & _
                            "country:\s+(?<ncoun>.*)\s+)"

        Dim match As Match = Regex.Match(tempStore, pat)

        ' Midcondition: explode if no match
        If Not match.Success Then
            SetError()
            _ISP = "Broke at regex"
            Exit Sub
        End If

        With match
            _ISP = .Groups("nname").Value
            _ISPDescription = .Groups("ndesc").Value
            _Country = .Groups("ncoun").Value
        End With

        ' Fin.

    End Sub


    ' Sub for churning the String-IP into Integer segments
    Private Function ParseIP() As Boolean

        ' Get a list of matches based on the given IP
        Dim _matches As MatchCollection = Regex.Matches(_IP, "(\d{1,3})")

        ' Midcondition: Check there are at least 4 maches
        If _matches.Count < 4 Then Return False

        ' Iterate the matches and assign
        Dim count As Integer = 0
        For Each _match As Match In _matches
            If count > 3 Then Exit For

            _IPSeg(count) = Integer.Parse(_match.Value)

            count += 1
        Next

        ' Postcondition: Check the segments to make sure they're under 256
        For Each seg As Integer In _IPSeg
            If seg > 255 Then Return False
        Next

        ' Reassign ip from segments
        _IP = String.Format("{0}.{1}.{2}.{3}", _ 
            _IPSeg(0), _IPSeg(1), _IPSeg(2), _IPSeg(3))

        Return True
    End Function


    Private Sub SetError()
        _ISP = "Error"
        _ISPDescription = "Invalid IP"
        _Country = "Unknown"
    End Sub

End Class

About Oli: I’m a Django and Python programmer, occasional designer, Ubuntu member, Ask Ubuntu moderator and technical blogger. I occasionally like to rant about subjects I should probably learn more about but I usually mean well.

Stay updated: Subscribe by RSS or Subscribe by Email.