Sign in to follow this  
Followers 0
maqleod

TCPNameToIP() - get more than one IP?

9 posts in this topic

TCPNameToIP() does only a portion of what I'm looking to do. I am looking to write in autoit a basic version of the Host command in Unix. I've started the process and gotten a skeleton written, but I really need to expand and am not sure how to do so at this point.

#include <iNet.au3>
#include <File.au3>

main()

Func main()
    Local $newstring, $hostname, $ipaddress
    TCPStartup()
    validate()
    If _StringIsIP($CmdLine[1]) Then
        $ipaddress = _TCPIpToName($CmdLine[1],1)
        If not @error Then
            For $i = 1 to $ipaddress[0]
                ConsoleWrite($CmdLine[1] & " has domain name pointer " & $ipaddress[$i])
            Next
        Else
            ConsoleWrite("No reverse lookup available")
        EndIf
    Else
        If _StringIsHost($CmdLine[1]) Then
        If StringLeft($CmdLine[1],4) = "www." Then
            $newstring = StringTrimLeft($CmdLine[1],4)
        Else
            $newstring = $CmdLine[1]
        EndIf
        $hostname = TCPNameToIP($newstring)
        ConsoleWrite($CmdLine[1] & " has IP of " & $hostname)
        Else
            ConsoleWrite("Input was not a valid IP or Hostname")
        EndIf
    EndIf
    Exit
    TCPShutdown()
EndFunc  ;==>main

Func validate()
    If $CmdLine[0] = 0 Or $CmdLine[1] = "-help" Then
        ConsoleWrite("Usage: host(.exe) hostname or IP")
        ConsoleWrite(@CRLF & "returns ")
        Exit
    ElseIf $CmdLine[0] > 1 Then
        ConsoleWrite("Error, too many arguments.")
        Exit
    ElseIf $CmdLine[0] < 1 Then
        ConsoleWrite("Error, too few arguments.")
        Exit
    EndIf
EndFunc  ;==>validate

Func _StringIsIp($s_String) ;note that this will only validate IPv4 addresses
    Local $s_Part, $f_Ip = False
    $s_Part = StringSplit ($s_String, ".")
    If Not @error Then
        If $s_Part[0] = 4 Then
            For $i = 1 to $s_Part[0]
                If StringisInt($s_Part[$i]) and $s_Part[$i] <= 255 Then
                    $f_Ip = True
                Else
                    $f_Ip = False
                    ExitLoop
                EndIf
            Next
        EndIf
    EndIf
    Return $f_Ip
EndFunc  ;==>_StringIsIP

Func _StringIsHost($s_String)
    Local $s_Part, $f_Host = False, $s_Tlds
    _FileReadToArray("tlds",$s_Tlds)
    $s_Part = StringSplit($s_String, ".")
    For $i = 1 to $s_Tlds[0]
        If $s_Part[$s_Part[0]] = $s_Tlds[$i] Then
            $f_Host = True
        EndIf
    Next
    Return $f_Host
EndFunc ;==>_StringIsHost

When I run this, the results can differ:

C:\Projects\AutoIt\Host>host google.com
google.com has IP of 74.125.19.99

C:\Projects\AutoIt\Host>host google.com
google.com has IP of 74.125.19.103

When I run host in my unix shell, I get this:

maqleod@andLinux:~$ host google.com
google.com has address 74.125.19.103
google.com has address 74.125.19.104
google.com has address 74.125.19.147
google.com has address 74.125.19.99
google.com mail is handled by 300 google.com.s9b1.psmtp.com.
google.com mail is handled by 400 google.com.s9b2.psmtp.com.
google.com mail is handled by 100 google.com.s9a1.psmtp.com.
google.com mail is handled by 200 google.com.s9a2.psmtp.com.

So what I am looking to find out is how can I iterate through the IP addresses for a single host name (I would prefer to do this with a system dll or wmi call, no external apps), and does anyone know how to query for the mx and cname records as well?

I suppose what would be most handy is just a method of querying dns for the a, cname and mx records, I just don't know where to start. I've tried searching the forum and google for methods of dns querying and have come up empty handed.

Any help would be appreciated.


[u]You can download my projects at:[/u] Pulsar Software

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

If you need only the IPs, just use nslookup ;)

###>nslookup google.com
Server:  ... (used DNS server)
Address:  ...

Nicht autorisierte Antwort:
Name:    google.com
Addresses:  209.85.135.147, 209.85.135.104, 209.85.135.103, 209.85.135.105
          209.85.135.106, 209.85.135.99
Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

You could call DnsQuery yourself and get all the records.

Share this post


Link to post
Share on other sites

You could call DnsQuery yourself and get all the records.

Thanks, this does look like what I need, but I'm not completely sure how to use it. Would this be a dll call from autoit? and if so, what dll?


[u]You can download my projects at:[/u] Pulsar Software

Share this post


Link to post
Share on other sites

Yes it's a dll call. The page says the library is dnsapi.dll.

Share this post


Link to post
Share on other sites

Yes it's a dll call. The page says the library is dnsapi.dll.

I completely missed that when I read over the page. Looks like I'll be doing some research on that dll and how to do dll calls in autoit.

[u]You can download my projects at:[/u] Pulsar Software

Share this post


Link to post
Share on other sites

This DLLcall is one of the more complicated ones ;)

I implemented a part of the function, but not all record types. Just add those you need.

;#########################################################################################################################################
#Region DNS UDFs
#include-once
Global Const $tagDNS_RECORD = "ptr pNext; ptr pName; WORD wType; WORD wDataLength; DWORD Flags; DWORD dwTtl; DWORD dwReserved; ptr Data"
Global Const $DNS_TYPE_A    = 0x0001
Global Const $DNS_TYPE_NS    = 0x0002
Global Const $DNS_TYPE_MD    = 0x0003
Global Const $DNS_TYPE_MF    = 0x0004
Global Const $DNS_TYPE_CNAME    = 0x0005
Global Const $DNS_TYPE_SOA    = 0x0006
Global Const $DNS_TYPE_MB    = 0x0007
Global Const $DNS_TYPE_MG    = 0x0008
Global Const $DNS_TYPE_MR    = 0x0009
Global Const $DNS_TYPE_NULL    = 0x000a
Global Const $DNS_TYPE_WKS    = 0x000b
Global Const $DNS_TYPE_PTR    = 0x000c
Global Const $DNS_TYPE_HINFO    = 0x000d
Global Const $DNS_TYPE_MINFO    = 0x000e
Global Const $DNS_TYPE_MX    = 0x000f
Global Const $DNS_TYPE_TEXT    = 0x0010
Global Const $DNS_TYPE_RP    = 0x0011
Global Const $DNS_TYPE_AFSDB    = 0x0012
Global Const $DNS_TYPE_X25    = 0x0013
Global Const $DNS_TYPE_ISDN    = 0x0014
Global Const $DNS_TYPE_RT    = 0x0015
Global Const $DNS_TYPE_NSAP    = 0x0016
Global Const $DNS_TYPE_NSAPPTR    = 0x0017
Global Const $DNS_TYPE_SIG    = 0x0018
Global Const $DNS_TYPE_KEY    = 0x0019
Global Const $DNS_TYPE_PX    = 0x001a
Global Const $DNS_TYPE_GPOS    = 0x001b
Global Const $DNS_TYPE_AAAA    = 0x001c
Global Const $DNS_TYPE_LOC    = 0x001d
Global Const $DNS_TYPE_NXT    = 0x001e
Global Const $DNS_TYPE_EID    = 0x001f
Global Const $DNS_TYPE_NIMLOC    = 0x0020
Global Const $DNS_TYPE_SRV    = 0x0021
Global Const $DNS_TYPE_ATMA    = 0x0022
Global Const $DNS_TYPE_NAPTR    = 0x0023
Global Const $DNS_TYPE_KX    = 0x0024
Global Const $DNS_TYPE_CERT    = 0x0025
Global Const $DNS_TYPE_A6    = 0x0026
Global Const $DNS_TYPE_DNAME    = 0x0027
Global Const $DNS_TYPE_SINK    = 0x0028
Global Const $DNS_TYPE_OPT    = 0x0029
Global Const $DNS_TYPE_DS    = 0x002B
Global Const $DNS_TYPE_RRSIG    = 0x002E
Global Const $DNS_TYPE_NSEC    = 0x002F
Global Const $DNS_TYPE_DNSKEY    = 0x0030
Global Const $DNS_TYPE_DHCID    = 0x0031
Global Const $DNS_TYPE_UINFO    = 0x0064
Global Const $DNS_TYPE_UID    = 0x0065
Global Const $DNS_TYPE_GID    = 0x0066
Global Const $DNS_TYPE_UNSPEC    = 0x0067
Global Const $DNS_TYPE_ADDRS    = 0x00f8
Global Const $DNS_TYPE_TKEY    = 0x00f9
Global Const $DNS_TYPE_TSIG    = 0x00fa
Global Const $DNS_TYPE_IXFR    = 0x00fb
Global Const $DNS_TYPE_AXFR    = 0x00fc
Global Const $DNS_TYPE_MAILB    = 0x00fd
Global Const $DNS_TYPE_MAILA    = 0x00fe
Global Const $DNS_TYPE_ALL    = 0x00ff
Global Const $DNS_TYPE_ANY    = 0x00ff
Global Const $DNS_TYPE_WINS    = 0xff01
Global Const $DNS_TYPE_WINSR    = 0xff02
Global Const $DNS_TYPE_NBSTAT    = $DNS_TYPE_WINSR

Global Const $tagDNS_MX_DATA = "ptr pNameExchange; WORD  wPreference; WORD  Pad;"
Global Const $tagDNS_A_DATA = "dword IpAddress"
;... more DNS_..._DATA structures come here

Global Const $DNS_QUERY_BYPASS_CACHE = 0x00000008
; ... more DNS_QUERY_... options come here



Func _Dns_Query($sOwner, $wType, $nOptions=0)
    ; Author: ProgAndy
    Local Static $hDNSAPI_DLL = DllOpen("Dnsapi.dll")
    Local $aRes = DllCall($hDNSAPI_DLL, "dword", "DnsQuery_W", "wstr", $sOwner, "WORD", $wType, "DWORD", $nOptions, 'ptr', 0,   "ptr*", 0, "ptr", 0)
    If @error Then Return SetError (1,0,0)
    Local $aResult[21][3] = [[0]], $iSize = 20, $i, $pNext = $aRes[5], $tDNS, $tData
    If $aRes[0] <> 0 Then Return SetError(2,$aRes[0],0)
    While $pNext
        $i = $aResult[0][0]+1
        $aResult[0][0]=$i
        If $i > $iSize Then
            $iSize += 20
            ReDim $aResult[$i][3]
        EndIf
        $tDNS = DllStructCreate($tagDNS_RECORD, $pNext)
        $aResult[$i][0] = __Dns_PtrStringRead(DllStructGetData($tDNS, 'pName'))
        $aResult[$i][1] = DllStructGetData($tDNS, 'wType')
        Switch $aResult[$i][1]
            Case $DNS_TYPE_A
                $aResult[$i][2] = __Dns_Inet_ntoa(DllStructGetData(DllStructCreate($tagDNS_A_DATA, DllStructGetPtr($tDNS, "Data")), 'IpAddress'))
            Case $DNS_TYPE_MX
                $tData = DllStructCreate($tagDNS_MX_DATA, DllStructGetPtr($tDNS, "Data"))
                Local $aSubRes[2] = [__Dns_PtrStringRead(DllStructGetData($tData, 'pNameExchange')), DllStructGetData($tData, 'wPreference')]
                $aResult[$i][2] = $aSubRes
            ; cases for other types would be here
            Case Else
                $aResult[$i][2] = "[[NOT IMPL]]"
        EndSwitch


        $pNext = DllStructGetData($tDNS, 'pNext')
    WEnd
    DllCall($hDNSAPI_DLL, "none", "DnsRecordListFree", "ptr", $aRes[5], "dword", 1)
    ReDim $aResult[$aResult[0][0]+1][3]
    Return $aResult
EndFunc

Func __Dns_Inet_ntoa($nIP)
    ; Author: ProgAndy
    Local $aRes = DllCall("ws2_32.dll", "str", "inet_ntoa", "dword", $nIP)
    If @error Then Return SetError(1,0,'')
    Return $aRes[0]
EndFunc

Func __Dns_PtrStringLen($pStr)
    ; Author: ProgAndy
    Local $aResult = DllCall("kernel32.dll", 'int', 'lstrlenW', 'ptr', $pStr)
    If @error Then Return SetError(1, 0, 0)
    Return $aResult[0]
EndFunc   ;==>__Au3Obj_PtrStringLen

Func __Dns_PtrStringRead($pStr, $iLen = -1)
    ; Author: ProgAndy
    If $iLen < 1 Then $iLen = __Dns_PtrStringLen($pStr)
    If $iLen < 1 Then Return SetError(1, 0, '')
    Return DllStructGetData(DllStructCreate("wchar[" & $iLen & "]", $pStr), 1)
EndFunc   ;==>__Au3Obj_PtrStringRead

#EndRegion DNS UDFs
;#########################################################################################################################################

Examples:

#include "DNS.au3"

; some examples for the UDF
#include<Array.au3>
$x = _Dns_Query("google.com", $DNS_TYPE_A) ; use local cache if available
;~ $x = _Dns_Query("google.com", $DNS_TYPE_A, $DNS_QUERY_BYPASS_CACHE) ; this call does not use local cache and refreshes from DNS server
_ArrayDisplay($x)

$x = _Dns_Query("google.com", $DNS_TYPE_MX)
If Not @error Then
    $text = ''
    For $i = 1 To $x[0][0]
        If $x[$i][1] = $DNS_TYPE_MX Then
            $mx = $x[$i][2]
            $text &= '--- MX ---' & @CRLF & "Owner: " & $x[$i][0] & @CRLF & "Address: " & $mx[0] & @CRLF & "Priority: " & $mx[1] & @CRLF & @CRLF
        ElseIf $x[$i][1] = $DNS_TYPE_A Then
            $text &= '--- A  ---' & @CRLF & "Owner: " & $x[$i][0] & @CRLF & "Address: " & $x[$i][2] & @CRLF & @CRLF
        EndIf
    Next
EndIf
MsgBox(0, 'Query MX records', $text)

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Thanks, this looks great, I will be adding it when I get off work, I'll post updated/working code when I incorporate it in.

I could have probably worked until the end of the month and not gotten a solution that worked. I will be spending some time looking over the MSDN documentation and your UDF to see how it all goes together.

Edited by maqleod

[u]You can download my projects at:[/u] Pulsar Software

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

@progandy, I am having trouble with the MX records. When I test it on any domain, the only value that I get returned is "15". This isn't the priority or the mail server, so I don't know why I get that response. I looked at the structure of the record in your UDF, but I'm not sure what the format for this particular record is.

Edit: Found the structure on the MSDN site, and it looks like everything should work right, I just don't know why I am not getting the right priority or the mail server name.

Edited by maqleod

[u]You can download my projects at:[/u] Pulsar Software

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0