11using Heijden . DNS ;
22using System ;
3+ using System . Collections . Generic ;
4+ using System . Linq ;
35using System . Net ;
6+ using System . Net . NetworkInformation ;
47using System . Threading . Tasks ;
58
69namespace NETworkManager . Models . Network
710{
811 public class DNSLookup
912 {
1013 #region Variables
11- Resolver DNSResolver = new Resolver ( ) ;
14+ Resolver dnsResolver = new Resolver ( ) ;
1215 #endregion
1316
1417 #region Events
@@ -26,103 +29,145 @@ protected virtual void OnLookupError(DNSLookupErrorArgs e)
2629 LookupError ? . Invoke ( this , e ) ;
2730 }
2831
29- public event EventHandler < DNSLookupCompleteArgs > LookupComplete ;
32+ public event EventHandler LookupComplete ;
3033
31- protected virtual void OnLookupComplete ( DNSLookupCompleteArgs e )
34+ protected virtual void OnLookupComplete ( )
3235 {
33- LookupComplete ? . Invoke ( this , e ) ;
36+ LookupComplete ? . Invoke ( this , EventArgs . Empty ) ;
3437 }
3538 #endregion
3639
3740 #region Methods
38- public void LookupAsync ( string hostnameOrIPAddress , DNSLookupOptions DNSLookupOptions )
41+ public void LookupAsync ( List < string > hosts , DNSLookupOptions dnsLookupOptions )
3942 {
4043 Task . Run ( ( ) =>
4144 {
42- // This will convert the query to an Arpa request
43- if ( DNSLookupOptions . Type == QType . PTR )
45+ // DNS server list
46+ List < string > dnsServers = new List < string > ( ) ;
47+
48+ if ( dnsLookupOptions . UseCustomDNSServer )
49+ dnsLookupOptions . CustomDNSServers . ForEach ( x => dnsServers . Add ( x ) ) ;
50+ else // Use windows default dns server, but filter/remove IPv6 site local addresses (fec0:0:0:0:ffff::)
51+ dnsResolver . DnsServers . Where ( x => ! x . Address . ToString ( ) . StartsWith ( @"fec0" ) ) . Select ( y => y . Address . ToString ( ) ) . ToList ( ) . ForEach ( x => dnsServers . Add ( x ) ) ;
52+
53+ // Foreach host
54+ foreach ( string host in hosts )
4455 {
45- if ( IPAddress . TryParse ( hostnameOrIPAddress , out IPAddress ip ) )
46- hostnameOrIPAddress = Resolver . GetArpaFromIp ( ip ) ;
47- }
56+ // Default
57+ string name = host ;
4858
49- if ( DNSLookupOptions . Type == QType . NAPTR )
50- hostnameOrIPAddress = Resolver . GetArpaFromEnum ( hostnameOrIPAddress ) ;
59+ string dnsSuffix = string . Empty ;
5160
52- if ( DNSLookupOptions . UseCustomDNSServer )
53- DNSResolver . DnsServer = DNSLookupOptions . CustomDNSServer ;
61+ if ( name . IndexOf ( "." , StringComparison . OrdinalIgnoreCase ) == - 1 )
62+ {
63+ if ( dnsLookupOptions . AddDNSSuffix )
64+ {
65+ if ( dnsLookupOptions . UseCustomDNSSuffix )
66+ dnsSuffix = dnsLookupOptions . CustomDNSSuffix ;
67+ else
68+ dnsSuffix = IPGlobalProperties . GetIPGlobalProperties ( ) . DomainName ;
69+ }
70+ }
5471
55- DNSResolver . Recursion = DNSLookupOptions . Recursion ;
56- DNSResolver . TransportType = DNSLookupOptions . TransportType ;
57- DNSResolver . Retries = DNSLookupOptions . Attempts ;
58- DNSResolver . TimeOut = DNSLookupOptions . Timeout ;
72+ // Append dns suffix to hostname
73+ if ( ! string . IsNullOrEmpty ( dnsSuffix ) )
74+ name += string . Format ( ".{0}" , dnsSuffix ) ;
5975
60- Response dnsResponse = DNSResolver . Query ( hostnameOrIPAddress , DNSLookupOptions . Type , DNSLookupOptions . Class ) ;
76+ // PTR
77+ if ( dnsLookupOptions . Type == QType . PTR )
78+ {
79+ if ( IPAddress . TryParse ( name , out IPAddress ip ) )
80+ name = Resolver . GetArpaFromIp ( ip ) ;
81+ }
6182
62- // If there was an error... return
63- if ( ! string . IsNullOrEmpty ( dnsResponse . Error ) )
64- {
65- OnLookupError ( new DNSLookupErrorArgs ( dnsResponse . Error , DNSResolver . DnsServer ) ) ;
66- return ;
67- }
83+ // NAPTR
84+ if ( dnsLookupOptions . Type == QType . NAPTR )
85+ name = Resolver . GetArpaFromEnum ( name ) ;
6886
69- // Process the results...
70- ProcessResponse ( dnsResponse ) ;
87+ int port = dnsLookupOptions . UseCustomDNSServer ? dnsLookupOptions . Port : Resolver . DefaultPort ;
7188
72- // If we get a CNAME back (from a result), do a second request and try to get the A, AAAA etc...
73- if ( DNSLookupOptions . ResolveCNAME && DNSLookupOptions . Type != QType . CNAME )
74- {
75- foreach ( RecordCNAME r in dnsResponse . RecordsCNAME )
89+ Parallel . ForEach ( dnsServers , dnsServer =>
7690 {
77- Response DNSResponse2 = DNSResolver . Query ( r . CNAME , DNSLookupOptions . Type , DNSLookupOptions . Class ) ;
91+ // Create a new for each request
92+ Resolver resolver = new Resolver ( dnsServer , port )
93+ {
94+ Recursion = dnsLookupOptions . Recursion ,
95+ TransportType = dnsLookupOptions . TransportType ,
96+ Retries = dnsLookupOptions . Attempts ,
97+ TimeOut = dnsLookupOptions . Timeout
98+ } ;
7899
79- if ( ! string . IsNullOrEmpty ( DNSResponse2 . Error ) )
100+ Response dnsResponse = resolver . Query ( name , dnsLookupOptions . Type , dnsLookupOptions . Class ) ;
101+
102+ // If there was an error... return
103+ if ( ! string . IsNullOrEmpty ( dnsResponse . Error ) )
80104 {
81- OnLookupError ( new DNSLookupErrorArgs ( DNSResponse2 . Error , DNSResolver . DnsServer ) ) ;
82- continue ;
105+ OnLookupError ( new DNSLookupErrorArgs ( dnsResponse . Error , resolver . DnsServer ) ) ;
106+ return ;
83107 }
84108
85- ProcessResponse ( DNSResponse2 ) ;
86- }
109+ // Process the results...
110+ ProcessResponse ( dnsResponse ) ;
111+
112+ // If we get a CNAME back (from an ANY result), do a second request and try to get the A, AAAA etc...
113+ if ( dnsLookupOptions . ResolveCNAME && dnsLookupOptions . Type == QType . ANY )
114+ {
115+ foreach ( RecordCNAME r in dnsResponse . RecordsCNAME )
116+ {
117+ Response dnsResponse2 = resolver . Query ( r . CNAME , dnsLookupOptions . Type , dnsLookupOptions . Class ) ;
118+
119+ if ( ! string . IsNullOrEmpty ( dnsResponse2 . Error ) )
120+ {
121+ OnLookupError ( new DNSLookupErrorArgs ( dnsResponse2 . Error , resolver . DnsServer ) ) ;
122+ continue ;
123+ }
124+
125+ ProcessResponse ( dnsResponse2 ) ;
126+ }
127+ }
128+ } ) ;
87129 }
88-
89- OnLookupComplete ( new DNSLookupCompleteArgs ( dnsResponse . Server . ToString ( ) , dnsResponse . Questions . Count , dnsResponse . Answers . Count , dnsResponse . Authorities . Count , dnsResponse . Additionals . Count , dnsResponse . MessageSize ) ) ;
130+
131+ OnLookupComplete ( ) ;
90132 } ) ;
91133 }
92134
93135 private void ProcessResponse ( Response dnsResponse )
94136 {
137+ string dnsServer = dnsResponse . Server . Address . ToString ( ) ;
138+ int port = dnsResponse . Server . Port ;
139+
95140 // A
96141 foreach ( RecordA r in dnsResponse . RecordsA )
97- OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r ) ) ;
142+ OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r , dnsServer , port ) ) ;
98143
99144 // AAAA
100145 foreach ( RecordAAAA r in dnsResponse . RecordsAAAA )
101- OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r ) ) ;
146+ OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r , dnsServer , port ) ) ;
102147
103148 // CNAME
104149 foreach ( RecordCNAME r in dnsResponse . RecordsCNAME )
105- OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r ) ) ;
150+ OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r , dnsServer , port ) ) ;
106151
107152 // MX
108153 foreach ( RecordMX r in dnsResponse . RecordsMX )
109- OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r ) ) ;
154+ OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r , dnsServer , port ) ) ;
110155
111156 // NS
112157 foreach ( RecordNS r in dnsResponse . RecordsNS )
113- OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r ) ) ;
158+ OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r , dnsServer , port ) ) ;
114159
115160 // PTR
116161 foreach ( RecordPTR r in dnsResponse . RecordsPTR )
117- OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r ) ) ;
162+ OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r , dnsServer , port ) ) ;
118163
119164 // SOA
120165 foreach ( RecordSOA r in dnsResponse . RecordsSOA )
121- OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r ) ) ;
166+ OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r , dnsServer , port ) ) ;
122167
123168 // TXT
124169 foreach ( RecordTXT r in dnsResponse . RecordsTXT )
125- OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r ) ) ;
170+ OnRecordReceived ( new DNSLookupRecordArgs ( r . RR , r , dnsServer , port ) ) ;
126171 }
127172 #endregion
128173 }
0 commit comments