/*_____________________________________________________________________________ |/ / DNS lookup add-on by David "Saturn" van Moolenbroek | Version 0.16, released 04-08-2006 -- support on #help.script/Quakenet | Use/modify however you want, but please keep my name in it. Thank you! | | Keywords: asynchronous DNS lookup, binary variables, UDP sockets | | This script can perform DNS lookups; somewhat like mIRC's /dns command, but | it communicates with the DNS servers directly, instead of letting mIRC (and | Windows) handle the lookups. | | Unlike mIRC's built-in /dns command, the script works in parallel: you can | start as many queries as you like, and slow queries will not hold back | faster ones. Also, many more lookups than just IPv4 host->IP and IP->host | are supported. This script does *not* cache the results of lookups, though. | | As the script can not directly obtain the nameservers from Windows, you | have two choices: either edit the script (see the "nameservers" identifier | below in the script) to use your nameservers, or get the nslookup DLL that | I wrote specifically for this script; if you put nslookup.dll in your | script directory, the script will use the DLL to obtain the DNS servers | from windows, and use these instead. This DLL can be downloaded from | http://www.xise.nl/mirc/, where the latest version of this script can be | found as well. | | The script defines the following commands/identifiers: | | /nslookup [-ac46t type] [alias [params]] | | This command starts a DNS lookup for the given host or IP address, and | either echo's the result to the status window, or calls a given alias. | | If you specify an IP address, the query defaults to reverse (PTR) lookup, | otherwise to IPv4 (A) lookup; see the "default" identifier in the script. | With the -t switch, or with one of the -a, -4 or -6 shortcuts, you can | specify the lookup type yourself. This script supports the following DNS | lookup/record types: | | A hostname to IPv4 address resolution (shortcut: -4) | AAAA hostname to IPv6 address resolution (shortcut: -6) | PTR IPv4/IPv6 to hostname (reverse) resolution | CNAME canonical name (alias) lookup | NS name server lookup | MX mail exchange server and priority lookup | TXT text record lookup | ALL lookup of all associated records with the name (shortcut: -a) | | Note that by nature, "ALL" queries will not dereference CNAME records. | | If you specify the -c flag, all current queries are cancelled. | | If a callback alias is specified, this alias will be called with the | results, and nothing will be echoed to the screen. When the query is | finished (whether or not successfully), the callback alias is called | like this: | | / [params] [output] | | Where input is the host/IP that the DNS request was issued for, type is | the type of the output (if any) or (otherwise) the original query type, | and output is the first (or, in the case of a MX lookup: best) result | of the DNS lookup. If there is more than one result, the other results | can be obtained by the $ns identifier; see below for details. If the DNS | lookup failed, there is no output parameter. | | The /ns command is a shortcut for /nslookup. | | $ns(N) | | Properties: type | | During an alias callback, this identifier returns the Nth result of the | lookup, or the type of the result (useful for "ALL" queries) if the | "type" property is specified. If N is zero, the number of results is | returned. | | Examples | | /nslookup irc.quakenet.org | /nslookup 2001:888:0:2::6667 | /nslookup -t txt aol.com | /nslookup -a google.com \ _\_____________________________________________________________________________ */ ; a space-separated list of the nameserver IPs to use ; IF YOU DO NOT WANT TO INSTALL NSLOOKUP.DLL, EDIT THE FOLLOWING LINE alias -l nameservers return 205.166.226.38 69.67.108.10 ; this is where the script will look for nslookup.dll, to override the above alias -l nameserverdll return $scriptdir $+ nslookup.dll ; the number of retries and the timeout (doubling with each retry) for queries alias -l retries return 3 alias -l time-out return 4 ; the path MTU to the DNS servers (minimum value is 512) alias -l pmtu return 512 ; the default type to query for alias -l default return A ; do not edit below here alias -l entry return $+($1,-,$hash($2,16),-,$3) alias -l types return a:1 ns:2 cname:5 ptr:12 mx:15 txt:16 aaaa:28 all:255 alias -l qtype return $gettok($wildtok($types,$1 $+ :*,1,32),2,58) alias -l rtype return $gettok($wildtok($types,*: $+ $1,1,32),1,58) alias nslookup { var %type, %clear = $false if (-* iswm $1) { var %opt = $1 tokenize 32 $2- if (t isincs %opt) { if (!$qtype($1)) { echo -aeqtc info * /nslookup: invalid parameters return } %type = $1 tokenize 32 $2- } if (c isincs %opt) { nsclear %clear = $true } if (4 isin %opt) %type = a if (6 isin %opt) %type = aaaa if (a isincs %opt) %type = all } if (!$0) { if (!%clear) || (%type) $& echo -aeqtc info * /nslookup: insufficient parameters return } var %orig = $1, %name = $iif(!$regex($1,/^\.+$/),$gettok($1,1-,46),.), %call = $2- if ((!%type) || ($istok(ptr all,%type,32))) && ($longip($1) isnum) { tokenize 46 $1 %name = $+($4,.,$3,.,$2,.,$1,.in-addr.arpa) if (!%type) %type = ptr } elseif ((!%type) || ($istok(ptr all,%type,32))) && (: isin $1) && $& ($ipv6rev($1)) { %name = $v1 if (!%type) %type = ptr } elseif (%type == ptr) { echo -aeqtc info * /nslookup: invalid parameters return } elseif (!%type) %type = $default nsload var %type = $upper(%type), %qtype = $qtype(%type) var %id = $rand(0,65535), %entry = $entry(%id,%name,%qtype), %n while ($hget(nslookup,%entry) != $null) { if (!%n) var %add = $calc($rand(0,32767) * 2 + 1), %n = 1 elseif (%n == 65535) { echo -aeqtc info * /nslookup: table full return } else inc %n inc %id %add %entry = $entry(%id,%name,%qtype) } if (%call == $null) { echo -eiqstc other * Looking up %orig ( $+ %type $+ ) %call = nsout } hadd -u600 nslookup %entry %name $iif(%orig != %name,$v1,-) %type $cid %call .timerns- $+ %entry -o 1 $time-out $& nsretry %entry %id %qtype $retries $time-out 1 nsquery %id %qtype %name $gettok($hget(nslookup,servers),1,32) } alias -l nsquery { bunset &data badd &data $calc($1 / 256) $calc($1 % 256) 1 0 0 1 0 0 0 0 0 $& $iif($pmtu > 512,1,0) var %l, %n = 1 while ($gettok($3,%n,46) != $null) { %l = $v1 badd &data $len(%l) badd -t &data %l inc %n } badd &data 0 0 $2 0 1 if ($pmtu > 512) $& badd &data 0 0 41 $calc($pmtu / 256) $calc($pmtu % 256) 0 0 0 0 0 0 sockudp -k nslookup $4 53 &data .timerns-sock 1 600 sockclose nslookup } on *:udpread:nslookup:{ sockread &data if ($bvar(&data,0) < 8) return var %id = $bvar(&data,1).nword ; make sure QR=1 OP=0 RD=1 QDCOUNT=1 if ($and($bvar(&data,3),249) != 129) || ($bvar(&data,5).nword != 1) return tokenize 32 $dnexpand(&data,13) if ($0 != 2) || ($calc($1 + 3) > $bvar(&data,0)) return if ($bvar(&data,$calc($1 + 2)).nword != 1) return var %qtype = $bvar(&data,$1).nword var %entry = $entry(%id,$2,%qtype) var %data = $hget(nslookup,%entry) if ($gettok(%data,1,32) != $2) return ; make sure RCODE=0 ANCODE>0 var %ans = $bvar(&data,7).nword if ($and($bvar(&data,4),15) != 0) || (!%ans) { nsres %entry return } if ($hget(nsres)) hfree nsres hmake nsres 10 var %type = $rtype(%qtype), %n = 0 tokenize 32 $calc($1 + 4) %type 1 $2 while (%ans) { tokenize 32 $getrecord($1,$2,$3,$4) if (!$0) break if ($0 > 5) { inc %n hadd nsres n $+ %n $5- } dec %ans } hadd nsres n0 %n var %res = $hget(nsres,n1) if (%type == mx) { var %i = 2 while (%i <= %n) { var %r = $hget(nsres,n $+ %i) if ($gettok(%res,3,32) > $gettok(%r,3,32)) %res = %r inc %i } } .timerns-res 1 0 if ($hget(nsres)) hfree nsres nsres %entry %res } alias -l nsload { if ($hget(nslookup,servers) != $null) { hadd -u600 nslookup servers $v1 return } if (!$hget(nslookup)) hmake nslookup 100 if ($isfile($nameserverdll)) $& hadd -u600 nslookup servers $dll($nameserverdll,GetDnsServers,) else hadd -u600 nslookup servers $nameservers } alias -l nsclear { .timerns-* off sockclose nslookup if ($hget(nslookup)) hfree nslookup if ($hget(nsres)) hfree nsres } alias -l nsretry { if ($4 > 0) { var %next = $calc($6 % $numtok($hget(nslookup,servers),32) + 1) .timerns- $+ $1 -o 1 $5 nsretry $1-3 $calc($4 - 1) $calc($5 * 2) %next nsquery $2-3 $gettok($hget(nslookup,$1),1,32) $& $gettok($hget(nslookup,servers),%next,32) } else nsres $1 } alias -l nsres { var %data = $hget(nslookup,$1), %type = $2, %res = $3- hdel nslookup $1 .timerns- $+ $1 off tokenize 32 $1 %data if (!%type) %type = $4 if ($scid($5)) scid $5 $6- $iif($3 != -,$3,$2) %type %res } alias -l nsout { if ($3 == $null) echo -eistc other * Unable to resolve $1 ( $+ $2 $+ ) else { var %i = 1, %n = $ns(0) linesep -s while (%i <= %n) { var %name = $gettok($ns(%i),1,32), %params = $gettok($ns(%i),2-,32) echo -istc other * Resolved $1 ( $+ $ns(%i).type $+ ) to %name $& $iif($ns(%i).type == mx && %params != $null,( $+ $v1 $+ ),%params) inc %i } linesep -s } } alias ns { if ($isid) { if (!$1) return $iif($hget(nsres,n0),$v1,0) return $gettok($hget(nsres,n $+ $1),$iif($prop == type,1,2-),32) } nslookup $1- } alias -l badd { if (-* !iswm $1) tokenize 32 - $1- bset $1-2 $calc($bvar($2,0) + 1) $3- } alias -l getrecord { dnexpand &data $1 var %off = $gettok($result,1,32), %name = $gettok($result,2,32), %res if (%name != $4) || ($calc(%off + 9) > $bvar(&data,0)) return if ($bvar(&data,$calc(%off + 2)).nword != 1) return var %type = $rtype($bvar(&data,%off).nword) if (%type != $2) && ((!$3) || (%type != cname)) && ($2 != all) return inc %off 10 var %len = $bvar(&data,$calc(%off - 2)).nword, %end = %off + %len if (!%len) || ($calc(%end - 1) > $bvar(&data,0)) return if (%type == cname) { if ($dnexpand(&data,%off) == $null) return %name = $gettok($v1,2,32) if ($istok(cname all,$2,32)) %res = %name } elseif (%type == a) { if (%len != 4) return %res = $longip($bvar(&data,%off).nlong) } elseif (%type == aaaa) { if (%len != 16) return var %i = 0 while (%i < 8) { %res = $iif(%res != $null,%res $+ :) $+ $& $lower($base($bvar(&data,$calc(%off + %i * 2)).nword,10,16)) inc %i } %res = $ipv6comp(%res) } elseif (%type == ns) || (%type == ptr) { if ($dnexpand(&data,%off) == $null) return %res = $gettok($v1,2,32) } elseif (%type == mx) { if (%len < 3) return if ($dnexpand(&data,$calc(%off + 2)) != $null) $& %res = $gettok($v1,2,32) $bvar(&data,%off).nword } elseif (%type == txt) { while ($calc($bvar(&data,%off) + 1) <= %len) { %res = %res $bvar(&data,$calc(%off + 1),$calc($v1 - 1)).text inc %off $v1 dec %len $v1 } } return %end $2 $iif(%type == cname,1,0) %name $upper(%type) %res } alias -l dnexpand { var %off = $2, %new, %end, %res, %c while (%off <= $bvar($1,0)) { %c = $bvar($1,%off) if (!%c) { if (!%end) %end = %off + 1 return %end $iif(%res != $null,%res,.) } elseif (%c >= 192) { if (%off == $bvar($1,0)) return %new = $calc($and(%c,63) + $bvar($1,$calc(%off + 1)) + 1) if (%new >= %off) return if (!%end) %end = %off + 2 %off = %new } else { if (%c > 63) || ($calc(%off + %c - 1) > $bvar($1,0)) || $& ($calc(%c + $iif($len(%s),$calc($v1 + 1), 0)) >= 256) return inc %off %res = $iif($len(%res),%res $+ .) $+ $bvar($1,%off,%c).text inc %off %c } } } alias -l ipv6rev { var %x = $1, %r = ([0-9a-f]{1,4}) if (:: isin %x) { if (::* iswm %x) %x = 0 $+ %x elseif (*:: iswm %x) %x = %x $+ 0 if ($calc(8 - $numtok(%x,58)) > 0) $& .echo -q $regsub(%x,/::/,: $+ $str(0:,$v1),%x) } if (!$regex(%x,$+(/^,$str(%r $+ :,7),%r,$,/i))) return var %i = 8, %g, %s while (%i) { %g = $lower($base($regml(%i),16,16,4)) .echo -q $regsub(n,%g,/(.)(.)(.)(.)/,\4.\3.\2.\1.,%g) %s = %s $+ %g dec %i } return %s $+ ip6.arpa } alias -l ipv6comp { var %x = $1, %n = $regsub(%x,/(?:^|:)(?:0:){6}0(?::|$)/,::,%x), %i = 5 while (!%n) && (%i >= 1) { %n = $regsub(%x,/(.*)(?:^|:)(?:0:){ $+ %i $+ }0(?::|$)/,\1::,%x) dec %i } return %x }