AdmiralAlkex Posted June 14, 2014 Share Posted June 14, 2014 I needed a way to get SRV records for domains, and the closest I found was >this thread, but no, it was not as easy to 'upgrade' as trancexx said! A summary of my changes: Replaced MX specifics with SRV specifics (obviously...) Adapted the code to work with _ArraySort() instead of her custom SortArray (seemed easier than adding the extra logic I needed) Replaced the non-working RegRead with a DllCall to GetNetworkParams (not sure if that key moved or if it never was there to begin with) Added Googles dns servers to list of public ones and simplified list code Fixed a bug in ExtractSRVServerData() that garbled data if more than 1 record was received Enjoy! expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs Originally was a script to get MX records written by trancexx http://www.autoitscript.com/forum/topic/78465-mx-records-for-a-specific-domain/ Now modified to get SRV records by AdmiralAlkex #ce Opt("MustDeclareVars", 1) #include <StringConstants.au3> #include <Array.au3> Local $domain = "_sip._udp.siplogin.de" ; change it to domain of your interest Local $mx = SRVRecords($domain) If IsArray($mx) Then Local $au For $j = 0 To UBound($mx) - 1 $au &= "Priority:" & $mx[$j][0] & " Weight:" & $mx[$j][1] & " Port:" & $mx[$j][2] & " Target:" & $mx[$j][3] & @CRLF Next MsgBox(0, "SRV records for " & $domain, $au) Else MsgBox(0, "SRV records for " & $domain, "No Records") EndIf Func SRVRecords($domain) Local $binary_data = SRVQueryServer($domain) If $binary_data = -1 Then Return -1 Local $output = ExtractSRVServerData($binary_data) _ArraySort($output, 0, 0, 0, 0) Local $iStart = -1 For $iX = 1 To UBound($output) - 1 If $output[$iX][0] = $output[$iX - 1][0] And $iStart = -1 Then $iStart = $iX - 1 ElseIf $output[$iX][0] <> $output[$iX - 1][0] And $iStart <> -1 Then _ArraySort($output, 1, $iStart, $iX - 1, 1) $iStart = -1 EndIf Next If $iStart <> -1 Then _ArraySort($output, 1, $iStart, $iX - 1, 1) EndIf Return $output EndFunc ;==>SRVRecords Func SRVQueryServer($domain) Local $domain_array $domain_array = StringSplit($domain, ".", 1) Local $binarydom For $el = 1 To $domain_array[0] $binarydom &= Hex(BinaryLen($domain_array[$el]), 2) & StringTrimLeft(StringToBinary($domain_array[$el]), 2) Next $binarydom &= "00" ; for example, 'gmail.com' will be '05676D61696C03636F6D00' and 'autoit.com' will be '066175746F697403636F6D00' Local $identifier = Hex(Random(0, 1000, 1), 2) ; random hex number serving as a handle for the data that will be received Local $server_bin = "0x00" & $identifier & "01000001000000000000" & $binarydom & "00210001" ; this is our query Local $num_time, $data Local $asQueryServers = _GetDnsServerAddress() Local $asPublicServers = StringSplit("8.8.8.8|8.8.4.4|4.2.2.1|67.138.54.100|208.67.222.222|4.2.2.2|4.2.2.3|208.67.220.220|4.2.2.4|4.2.2.5|4.2.2.6", "|", $STR_NOCOUNT) Local $iSize = _ArrayConcatenate($asQueryServers, $asPublicServers) For $num_time = 0 To $iSize - 1 ; this kind of server is not what we want If StringLeft($asQueryServers[$num_time], 3) = "192" Then ContinueLoop If $asQueryServers[$num_time] = "" Then ContinueLoop UDPStartup() Local $sock $sock = UDPOpen($asQueryServers[$num_time], 53) If $sock = -1 Then ; ok, that happens UDPCloseSocket($sock) UDPShutdown() ContinueLoop ; change server and try again EndIf UDPSend($sock, $server_bin) ; sending query Local $tik = 0 Do $data = UDPRecv($sock, 512) $tik += 1 Sleep(100) Until $data <> "" Or $tik = 8 ; waiting reasonable time for the response UDPShutdown() ; stopping service If $data <> "" And StringRight(BinaryMid($data, 2, 1), 2) = $identifier Then Return $data ; if there is data for us, return EndIf Next Return -1 EndFunc ;==>SRVQueryServer Func ExtractSRVServerData($binary_data) Local $num_answ = Dec(StringMid($binary_data, 15, 4)) ; representing number of answers provided by the server Local $arr = StringSplit($binary_data, "C00C00210001", 1) ; splitting input; "C00C000F0001" - translated to human: "this is the answer for your MX query" If $num_answ <> $arr[0] - 1 Or $num_answ = 0 Then Return -1 ; dealing with possible options Local $iPriority[$arr[0]] Local $iWeight[$arr[0]] Local $iPort[$arr[0]] Local $sTarget[$arr[0]] ; server name(s) Local $output[$arr[0] - 1][4] ; this goes out containing both server names and coresponding priority/weight and port numbers Local $offset = 14 ; initial offset For $i = 2 To $arr[0] $arr[$i] = "0x" & $arr[$i] ; well, it is binary data $iPriority[$i - 1] = Dec(StringRight(BinaryMid($arr[$i], 7, 2), 4)) $iWeight[$i - 1] = Dec(StringRight(BinaryMid($arr[$i], 9, 2), 4)) $iPort[$i - 1] = Dec(StringRight(BinaryMid($arr[$i], 11, 2), 4)) $offset += BinaryLen($arr[$i - 1]) + 6 ; adding lenght of every past part plus lenght of that "C00C000F0001" used for splitting Local $array = ReadBinary($binary_data, $offset) ; extraction of server names starts here While $array[1] = 192 ; dealing with special case $array = ReadBinary($binary_data, $array[6] + 2) WEnd $sTarget[$i - 1] &= $array[2] & "." While $array[3] <> 0 ; the end will obviously be at $array[3] = 0 If $array[3] = 192 Then $array = ReadBinary($array[0], $array[4] + 2) If $array[3] = 0 Then $sTarget[$i - 1] &= $array[2] ExitLoop Else $sTarget[$i - 1] &= $array[2] & "." EndIf Else $array = ReadBinary($array[0], $array[5]) If $array[3] = 0 Then $sTarget[$i - 1] &= $array[2] ExitLoop Else $sTarget[$i - 1] &= $array[2] & "." EndIf EndIf WEnd $output[$i - 2][0] = $iPriority[$i - 1] $output[$i - 2][1] = $iWeight[$i - 1] $output[$i - 2][2] = $iPort[$i - 1] $output[$i - 2][3] = $sTarget[$i - 1] Next Return $output ; two-dimensional array EndFunc ;==>ExtractSRVServerData Func ReadBinary($binary_data, $offset) Local $len = Dec(StringRight(BinaryMid($binary_data, $offset - 1, 1), 2)) Local $data_bin = BinaryMid($binary_data, $offset, $len) Local $checker = Dec(StringRight(BinaryMid($data_bin, 1, 1), 2)) Local $data = BinaryToString($data_bin) Local $triger = Dec(StringRight(BinaryMid($binary_data, $offset + $len, 1), 2)) Local $new_offset = Dec(StringRight(BinaryMid($binary_data, $offset + $len + 1, 1), 2)) Local $another_offset = $offset + $len + 1 Local $array[7] = [$binary_data, $len, $data, $triger, $new_offset, $another_offset, $checker] ; bit of this and bit of that Return $array EndFunc ;==>ReadBinary ;Based on Authenticity code from http://www.autoitscript.com/forum/topic/119734-tcpiptoname-extremly-slow-if-no-ptr-record-exists/?p=832148 Func _GetDnsServerAddress() Local $aResult, $tBuf, $tDnsServersList $aResult = DllCall("iphlpapi.dll", "uint", "GetNetworkParams", "int*", 0, "uint*", 4) If $aResult[0] = 111 Then $tBuf = DllStructCreate("byte[" & $aResult[2] & "]") $aResult = DllCall("iphlpapi.dll", "uint", "GetNetworkParams", "struct*", $tBuf, "uint*", $aResult[2]) If $aResult[0] <> 0 Then Return SetError($aResult[0], 0, "") Local $tagIP_ADDR_STRING = "ptr Next;char IpAddress[16];char IpMask[16];uint Context;" $tDnsServersList = DllStructCreate($tagIP_ADDR_STRING, DllStructGetPtr($tBuf) + 268) Local $sOutput = $tDnsServersList.IpAddress While $tDnsServersList.Next $tDnsServersList = DllStructCreate($tagIP_ADDR_STRING, $tDnsServersList.Next) $sOutput &= "|" & $tDnsServersList.IpAddress WEnd Return StringSplit($sOutput, "|", $STR_NOCOUNT) Else Return SetError(-1, 0, "") EndIf EndFunc ;==>_GetDnsServerAddress jvanegmond and trancexx 2 .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface Link to comment Share on other sites More sharing options...
LWC Posted November 9 Share Posted November 9 Thanks! I know it's old, but for anyone looking to pull SRV records, the registry bypass above fails for me too. So I've revised this and other improvements into a central DNS function. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now