Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
DnsResolver.cs
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Net;
5using System.Net.NetworkInformation;
6using System.Net.Sockets;
7using System.Text;
8using System.Text.RegularExpressions;
9using System.Threading.Tasks;
10using Waher.Events;
17
19{
31 public static class DnsResolver
32 {
36 public const int DefaultDnsPort = 53;
37
38 private static readonly Regex arpanetHostName = new Regex(@"^[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?([.][a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", RegexOptions.Compiled | RegexOptions.Singleline);
39 private static readonly object synchObject = new object();
40 private static readonly Random rnd = new Random();
41 private static ushort nextId = 0;
42 private static DnsHttpsClient httpsClient = null;
43 private static DnsUdpClient udpClient = null;
44 private static bool networkChanged = false;
45 private static int nestingDepth = 0;
46
47 static DnsResolver()
48 {
49 try
50 {
51 NetworkChange.NetworkAddressChanged += (Sender, e) => networkChanged = true;
52 }
53 catch (Exception ex)
54 {
55 Log.Exception(ex);
56 }
57 }
58
62 public static Uri DnsOverHttpsUri
63 {
64 get => httpsClient?.Uri;
65 set
66 {
67 if (value is null)
68 {
69 httpsClient?.Dispose();
70 httpsClient = null;
71 }
72 else if (httpsClient is null)
73 httpsClient = new DnsHttpsClient(value);
74 else
75 httpsClient.Uri = value;
76 }
77 }
78
82 public static IPAddress[] DnsServerAddresses
83 {
84 get
85 {
86 List<IPAddress> Addresses = new List<IPAddress>();
87
88 NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
89 foreach (NetworkInterface Interface in Interfaces)
90 {
91 if (Interface.OperationalStatus == OperationalStatus.Up)
92 {
93 foreach (IPAddress Address in Interface.GetIPProperties().DnsAddresses)
94 {
95 if (!Addresses.Contains(Address))
96 Addresses.Add(Address);
97 }
98 }
99 }
100
101 return Addresses.ToArray();
102 }
103 }
104
110 public static bool IsValidArpanetHostName(string HostName)
111 {
112 if (HostName.Length > 255)
113 return false;
114
115 Match M;
116
117 lock (arpanetHostName)
118 {
119 M = arpanetHostName.Match(HostName);
120 }
121
122 return (M.Success && M.Index == 0 && M.Length == HostName.Length);
123 }
124
128 internal static ushort NextID
129 {
130 get
131 {
132 lock (synchObject)
133 {
134 return nextId++;
135 }
136 }
137 }
138
147 public static Task<ResourceRecord[]> Resolve(string Name, QTYPE TYPE, QCLASS CLASS)
148 {
149 return Resolve(Name, TYPE, null, CLASS, null);
150 }
151
161 public static Task<ResourceRecord[]> Resolve(string Name, QTYPE TYPE, QCLASS CLASS, ProfilerThread Thread)
162 {
163 return Resolve(Name, TYPE, null, CLASS, Thread);
164 }
165
175 public static Task<ResourceRecord[]> Resolve(string Name, QTYPE TYPE, TYPE? ExceptionType, QCLASS CLASS)
176 {
177 return Resolve(Name, TYPE, ExceptionType, CLASS, null);
178 }
179
190 public static async Task<ResourceRecord[]> Resolve(string Name, QTYPE TYPE, TYPE? ExceptionType, QCLASS CLASS, ProfilerThread Thread)
191 {
192 LinkedList<KeyValuePair<string, IPEndPoint>> Backup = null;
193 TYPE? ExpectedType;
194 IPEndPoint Destination = null;
195 int Timeout = 5000; // Local timeout
196
197 if (Enum.TryParse(TYPE.ToString(), out TYPE T))
198 ExpectedType = T;
199 else
200 ExpectedType = null;
201
202 Thread?.NewState("Client");
203
204 lock (synchObject)
205 {
206 if (nestingDepth == 0 && networkChanged)
207 {
208 networkChanged = false;
209 udpClient?.Dispose();
210 udpClient = null;
211 }
212
213 if (udpClient is null)
214 udpClient = new DnsUdpClient();
215
216 nestingDepth++;
217 }
218
219 try
220 {
221 while (true)
222 {
223 Thread?.NewState("Query");
224
225 DnsResponse Response = await Query(Name, TYPE, CLASS, Timeout, Destination, false, Thread);
226 string CName = null;
227
228 if (Response is null)
229 {
230 Destination = await NextDestination(Backup);
231 if (Destination is null)
232 throw new IOException("Unable to resolve DNS query: " + Name + ", " + TYPE.ToString() + ", " + CLASS.ToString());
233
234 continue; // Check an alternative
235 }
236
237 if (!(Response.Answer is null))
238 {
239 if (!ExpectedType.HasValue)
240 return Response.Answer;
241
242 foreach (ResourceRecord RR in Response.Answer)
243 {
244 if (RR.Type == ExpectedType.Value)
245 return Response.Answer;
246
247 if (CName is null && RR.Type == Enumerations.TYPE.CNAME && RR is CNAME CNAME)
248 CName = CNAME.Name2;
249 }
250
251 if (ExceptionType.HasValue)
252 {
253 foreach (ResourceRecord RR in Response.Answer)
254 {
255 if (RR.Type == ExceptionType.Value)
256 return Response.Answer;
257 }
258 }
259
260 if (!(CName is null))
261 {
262 Name = CName;
263 Backup = null;
264 continue;
265 }
266 }
267
268 if (!(Response.Authority is null))
269 {
270 foreach (ResourceRecord RR in Response.Authority)
271 {
272 if (RR is NS NS)
273 {
274 string Authority = NS.Name2;
275 IPAddress AuthorityAddress = null;
276
277 if (!(Response.Additional is null))
278 {
279 foreach (ResourceRecord RR2 in Response.Additional)
280 {
281 if (RR2 is A A)
282 {
283 AuthorityAddress = A.Address;
284 break;
285 }
286 else if (RR2 is AAAA AAAA)
287 {
288 AuthorityAddress = AAAA.Address;
289 break;
290 }
291 }
292 }
293
294 if (Backup is null)
295 Backup = new LinkedList<KeyValuePair<string, IPEndPoint>>();
296
297 if (AuthorityAddress is null)
298 Backup.AddLast(new KeyValuePair<string, IPEndPoint>(Authority, null));
299 else
300 Backup.AddLast(new KeyValuePair<string, IPEndPoint>(null, new IPEndPoint(AuthorityAddress, DefaultDnsPort)));
301 }
302 }
303 }
304
305 Destination = await NextDestination(Backup);
306 if (Destination is null)
307 throw new IOException("Unable to resolve DNS query: " + Name + ", " + TYPE.ToString() + ", " + CLASS.ToString());
308
309 Timeout = 5000;
310 }
311 }
312 finally
313 {
314 lock (synchObject)
315 {
316 nestingDepth--;
317 }
318 }
319 }
320
329 public static Task<DnsResponse> Query(string Name, QTYPE TYPE, QCLASS CLASS)
330 {
331 return Query(Name, TYPE, CLASS, null);
332 }
333
343 public static Task<DnsResponse> Query(string Name, QTYPE TYPE, QCLASS CLASS, ProfilerThread Thread)
344 {
345 lock (synchObject)
346 {
347 if (nestingDepth == 0 && networkChanged)
348 {
349 networkChanged = false;
350 udpClient?.Dispose();
351 udpClient = null;
352 }
353
354 if (udpClient is null)
355 udpClient = new DnsUdpClient();
356
357 nestingDepth++;
358 }
359
360 try
361 {
362 return Query(Name, TYPE, CLASS, 2000, null, true, Thread);
363 }
364 finally
365 {
366 lock (synchObject)
367 {
368 nestingDepth--;
369 }
370 }
371 }
372
373 private static async Task<DnsResponse> Query(string Name, QTYPE TYPE, QCLASS CLASS, int Timeout, IPEndPoint Destination,
374 bool ReturnRaw, ProfilerThread Thread)
375 {
376 DnsResponse Response;
377 DnsMessage Message;
378
380 {
381 try
382 {
383 Thread?.NewState("Search");
384
385 IEnumerable<DnsResponse> Records = await Database.Find<DnsResponse>();
386
387 Response = await Database.FindFirstDeleteRest<DnsResponse>(new FilterAnd(
388 new FilterFieldEqualTo("Name", Name),
389 new FilterFieldEqualTo("Type", TYPE),
390 new FilterFieldEqualTo("Class", CLASS)));
391
392 if (!(Response is null) && (Response.Expires <= DateTime.Now || Response.Raw is null))
393 {
394 await Database.DeleteLazy(Response);
395 Response = null;
396 }
397 }
398 catch (Exception ex)
399 {
400 Thread?.Exception(ex);
401
402 // Some inconsistency in database. Clear collection to get fresh set of DNS entries.
403 await Database.Clear("DnsCache");
404 Response = null;
405 }
406 }
407 else
408 Response = null;
409
410 if (Response is null)
411 {
412 bool Save = true;
413 DnsClient Client;
414
415 if (Destination is null)
416 {
417 Client = httpsClient;
418 if (Client is null)
419 {
420 Client = udpClient;
421 Thread?.NewState("UDP");
422 }
423 else
424 Thread?.NewState("HTTPS");
425 }
426 else
427 {
428 Client = udpClient;
429 Thread?.NewState("UDP");
430 }
431
432 Client.Thread = Thread;
433
434 try
435 {
436 Message = await Client.SendRequestAsync(OpCode.Query, true, new Question[]
437 {
438 new Question(Name, TYPE, CLASS)
439 }, Destination, Timeout);
440
441 switch (Message.RCode)
442 {
443 case RCode.NXDomain:
444 if (ReturnRaw)
445 Save = false;
446 else
447 throw new GenericException("Domain name not found: " + Name, Object: Name);
448 break;
449 }
450 }
451 catch (TimeoutException ex)
452 {
453 Thread?.Exception(ex);
454 Message = null;
455 }
456 finally
457 {
458 Client.Thread = null;
459 }
460
461 if (Message is null || Message.RCode != RCode.NoError)
462 {
463 if (ReturnRaw)
464 Save = false;
465 else
466 return null;
467 }
468
469 uint Ttl = 60 * 60 * 24 * 30; // Maximum TTL = 30 days
470
471 Response = new DnsResponse()
472 {
473 Name = Name,
474 Type = TYPE,
475 Class = CLASS,
476 Answer = CheckTtl(ref Ttl, Message?.Answer),
477 Authority = CheckTtl(ref Ttl, Message?.Authority),
478 Additional = CheckTtl(ref Ttl, Message?.Additional),
479 Raw = Message?.Binary,
480 Expires = DateTime.Now.AddSeconds(Ttl)
481 };
482
483 if (Save && Database.HasProvider)
484 {
485 Thread?.NewState("Store");
486 try
487 {
488 await Database.InsertLazy(Response);
489 }
490 catch (Exception ex)
491 {
492 Log.Exception(ex);
493 }
494 }
495 }
496
497 return Response;
498 }
499
500 private static async Task<IPEndPoint> NextDestination(LinkedList<KeyValuePair<string, IPEndPoint>> Backup)
501 {
502 IPEndPoint Destination = null;
503
504 while (Destination is null && !(Backup?.First is null))
505 {
506 KeyValuePair<string, IPEndPoint> P = Backup.First.Value;
507 Backup.RemoveFirst();
508
509 Destination = P.Value;
510
511 if (Destination is null)
512 {
513 IPAddress[] Addresses;
514
515 try
516 {
517 Addresses = await LookupIP4Addresses(P.Key);
518 }
519 catch (Exception)
520 {
521 Addresses = null;
522 }
523
524 if (Addresses is null || Addresses.Length == 0)
525 {
526 try
527 {
528 Addresses = await LookupIP6Addresses(P.Key);
529 }
530 catch (Exception)
531 {
532 Addresses = null;
533 }
534 }
535
536 if (!(Addresses is null))
537 {
538 foreach (IPAddress Address in Addresses)
539 {
540 IPEndPoint EP = new IPEndPoint(Address, DefaultDnsPort);
541
542 if (Destination is null)
543 Destination = EP;
544 else
545 {
546 if (Backup is null)
547 Backup = new LinkedList<KeyValuePair<string, IPEndPoint>>();
548
549 Backup.AddLast(new KeyValuePair<string, IPEndPoint>(null, EP));
550 }
551 }
552 }
553 }
554 }
555
556 return Destination;
557 }
558
559 private static ResourceRecord[] CheckTtl(ref uint Ttl, ResourceRecord[] Records)
560 {
561 if (!(Records is null))
562 {
563 foreach (ResourceRecord RR in Records)
564 {
565 if (RR.Ttl < Ttl)
566 Ttl = RR.Ttl;
567 }
568 }
569
570 return Records;
571 }
572
580 public static async Task<IPAddress[]> LookupIP4Addresses(string DomainName)
581 {
582 List<IPAddress> Result = new List<IPAddress>();
583
584 foreach (ResourceRecord RR in await Resolve(DomainName, QTYPE.A, QCLASS.IN))
585 {
586 if (RR is A A)
587 Result.Add(A.Address);
588 }
589
590 return Result.ToArray();
591 }
592
600 public static async Task<IPAddress[]> LookupIP6Addresses(string DomainName)
601 {
602 List<IPAddress> Result = new List<IPAddress>();
603
604 foreach (ResourceRecord RR in await Resolve(DomainName, QTYPE.AAAA, QCLASS.IN))
605 {
606 if (RR is AAAA AAAA)
607 Result.Add(AAAA.Address);
608 }
609
610 return Result.ToArray();
611 }
612
620 public static async Task<string[]> LookupMailExchange(string DomainName)
621 {
622 List<MX> Records = new List<MX>();
623 ResourceRecord[] RRs = await Resolve(DomainName, QTYPE.MX, TYPE.A, QCLASS.IN);
624
625 foreach (ResourceRecord RR in RRs)
626 {
627 if (RR is MX MX)
628 Records.Add(MX);
629 }
630
631 if (Records.Count == 0)
632 {
633 foreach (ResourceRecord RR in RRs)
634 {
635 if (RR is A A)
636 Records.Add(new MX() { Exchange = A.Address.ToString() });
637 }
638 }
639 else
640 Records.Sort((r1, r2) => r2.Preference - r1.Preference); // Descending
641
642 int i, c = Records.Count;
643 string[] Result = new string[c];
644
645 for (i = 0; i < c; i++)
646 Result[i] = Records[i].Exchange;
647
648 return Result;
649 }
650
659 public static string AddressToName(IPAddress Address, string IP4DomainName, string IP6DomainName)
660 {
661 byte[] Bin = Address.GetAddressBytes();
662
663 switch (Bin.Length)
664 {
665 case 4:
666 if (string.IsNullOrEmpty(IP4DomainName))
667 throw new ArgumentOutOfRangeException("IPv4 addresses not supported.");
668
669 StringBuilder sb = new StringBuilder();
670 int i;
671
672 for (i = 3; i >= 0; i--)
673 {
674 sb.Append(Bin[i].ToString());
675 sb.Append('.');
676 }
677
678 sb.Append(IP4DomainName);
679
680 return sb.ToString();
681
682 case 16:
683 if (string.IsNullOrEmpty(IP6DomainName))
684 throw new ArgumentOutOfRangeException("IPv6 addresses not supported.");
685
686 byte b, b2;
687
688 sb = new StringBuilder();
689
690 for (i = 15; i >= 0; i--)
691 {
692 b = Bin[i];
693 b2 = (byte)(b & 15);
694 if (b2 < 10)
695 sb.Append((char)('0' + b2));
696 else
697 sb.Append((char)('A' + b2 - 10));
698
699 sb.Append('.');
700
701 b2 = (byte)(b >> 4);
702 if (b2 < 10)
703 sb.Append((char)('0' + b2));
704 else
705 sb.Append((char)('A' + b2 - 10));
706
707 sb.Append('.');
708 }
709
710 sb.Append(IP6DomainName);
711
712 return sb.ToString();
713
714 default:
715 throw new ArgumentOutOfRangeException("Unrecognized IP address.", nameof(Address));
716 }
717 }
718
726 public static async Task<string[]> LookupDomainName(IPAddress Address)
727 {
728 string Name = AddressToName(Address, "IN-ADDR.ARPA", "IP6.ARPA");
729 List<string> Result = new List<string>();
730
731 foreach (ResourceRecord RR in await Resolve(Name, QTYPE.PTR, QCLASS.IN))
732 {
733 if (RR is PTR PTR)
734 Result.Add(PTR.Name2);
735 }
736
737 return Result.ToArray();
738 }
739
745 public static async Task<string[]> LookupText(string Name)
746 {
747 List<string> Result = new List<string>();
748
749 foreach (ResourceRecord RR in await Resolve(Name, QTYPE.TXT, QCLASS.IN))
750 {
751 if (RR is TXT TXT)
752 Result.AddRange(TXT.Text);
753 }
754
755 return Result.ToArray();
756 }
757
765 public static async Task<string[]> LookupBlackList(IPAddress Address, string BlackListDomainName)
766 {
767 string Name = AddressToName(Address, BlackListDomainName, null);
768 ResourceRecord[] As;
769
770 try
771 {
772 As = await Resolve(Name, QTYPE.A, QCLASS.IN);
773 }
774 catch (ArgumentException)
775 {
776 return null;
777 }
778
779 List<string> Result = null;
780
781 try
782 {
783 foreach (ResourceRecord RR in await Resolve(Name, QTYPE.TXT, QCLASS.IN))
784 {
785 if (RR is TXT TXT)
786 {
787 if (Result is null)
788 Result = new List<string>();
789
790 Result.AddRange(TXT.Text);
791 }
792 }
793
794 if (!(Result is null))
795 return Result.ToArray();
796 }
797 catch (Exception)
798 {
799 // Ignore
800 }
801
802 foreach (ResourceRecord RR in As)
803 {
804 if (RR is A A)
805 {
806 if (Result is null)
807 Result = new List<string>();
808
809 Result.Add(A.Address.ToString());
810 }
811 }
812
813 return Result?.ToArray();
814 }
815
825 public static Task<SRV> LookupServiceEndpoint(string DomainName, string ServiceName, string Protocol)
826 {
827 return LookupServiceEndpoint(DomainName, ServiceName, Protocol, null);
828 }
829
840 public static async Task<SRV> LookupServiceEndpoint(string DomainName, string ServiceName, string Protocol, ProfilerThread Thread)
841 {
842 Thread?.NewState("Resolve");
843
844 string Name = "_" + ServiceName + "._" + Protocol.ToLower() + "." + DomainName;
845 SortedDictionary<ushort, List<SRV>> ServicesByPriority = new SortedDictionary<ushort, List<SRV>>();
846 List<SRV> SamePriority;
847
848 foreach (ResourceRecord RR in await Resolve(Name, QTYPE.SRV, QCLASS.IN, Thread))
849 {
850 if (RR is SRV SRV)
851 {
852 if (!ServicesByPriority.TryGetValue(SRV.Priority, out SamePriority))
853 {
854 SamePriority = new List<SRV>();
855 ServicesByPriority[SRV.Priority] = SamePriority;
856 }
857
858 SamePriority.Add(SRV);
859 }
860 }
861
862 Thread?.NewState("Select");
863
864 while (true)
865 {
866 ushort? FirstKey = null;
867
868 SamePriority = null;
869 foreach (KeyValuePair<ushort, List<SRV>> P in ServicesByPriority)
870 {
871 FirstKey = P.Key;
872 SamePriority = P.Value;
873 break;
874 }
875
876 if (!FirstKey.HasValue)
877 throw new IOException("Service Endpoint not found.");
878
879 int TotWeight = 0;
880 int i;
881
882 foreach (SRV SRV in SamePriority)
883 TotWeight += SRV.Weight;
884
885 SRV Selected = null;
886
887 if (TotWeight > 0)
888 {
889 lock (rnd)
890 {
891 i = rnd.Next(TotWeight);
892 }
893
894 foreach (SRV SRV in SamePriority)
895 {
896 if (i < SRV.Weight)
897 {
898 Selected = SRV;
899 SamePriority.Remove(SRV);
900 if (SamePriority.Count == 0)
901 ServicesByPriority.Remove(FirstKey.Value);
902 break;
903 }
904 else
905 i -= SRV.Weight;
906 }
907 }
908 else
909 {
910 foreach (SRV SRV in SamePriority)
911 {
912 Selected = SRV;
913 SamePriority.Remove(SRV);
914 if (SamePriority.Count == 0)
915 ServicesByPriority.Remove(FirstKey.Value);
916 break;
917 }
918 }
919
920 // TODO: Check host availability on the given port... If not available, continue with next.
921
922 if (Selected is null)
923 ServicesByPriority.Remove(FirstKey.Value);
924 else if (Selected.TargetHost != ".")
925 return Selected;
926 }
927 }
928
937 public static async Task<SRV[]> LookupServiceEndpoints(string DomainName, string ServiceName, string Protocol)
938 {
939 string Name = "_" + ServiceName + "._" + Protocol.ToLower() + "." + DomainName;
940 List<SRV> Result = new List<SRV>();
941
942 foreach (ResourceRecord RR in await Resolve(Name, QTYPE.SRV, QCLASS.IN))
943 {
944 if (RR is SRV SRV)
945 Result.Add(SRV);
946 }
947
948 return Result.ToArray();
949 }
950
960 public static int Next(int MaxValue)
961 {
962 lock (rnd)
963 {
964 return rnd.Next(MaxValue);
965 }
966 }
967
973 public static async Task<string[]> ReverseDns(IPAddress Address)
974 {
975 StringBuilder sb = new StringBuilder();
976 byte[] Bytes = Address.GetAddressBytes();
977 int i = Bytes.Length;
978
979 if (Address.AddressFamily == AddressFamily.InterNetwork)
980 {
981 while (i-- > 0)
982 {
983 sb.Append(Bytes[i].ToString());
984 sb.Append('.');
985 }
986
987 sb.Append("in-addr.arpa");
988 }
989 else if (Address.AddressFamily == AddressFamily.InterNetworkV6)
990 {
991 Address.GetAddressBytes();
992
993 while (i-- > 0)
994 {
995 byte b = Bytes[i];
996
997 sb.Append((b & 15).ToString("x1"));
998 sb.Append('.');
999
1000 sb.Append((b >> 4).ToString("x1"));
1001 sb.Append('.');
1002 }
1003
1004 sb.Append("ip6.arpa");
1005 }
1006 else
1007 throw new ArgumentException("Unsupported address family.", nameof(Address));
1008
1009 ResourceRecord[] Records = await Resolve(sb.ToString(), QTYPE.PTR, QCLASS.IN);
1010 List<string> Names = new List<string>();
1011
1012 foreach (ResourceRecord Rec in Records)
1013 {
1014 if (Rec is PTR PtrRecord)
1015 Names.Add(PtrRecord.Name2);
1016 }
1017
1018 return Names.ToArray();
1019 }
1020
1021 }
1022}
Generic exception, with meta-data for logging.
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1647
Abstract base class for DNS clients.
Definition: DnsClient.cs:21
async Task< DnsMessage > SendRequestAsync(OpCode OpCode, bool Recursive, Question[] Questions, IPEndPoint Destination, int Timeout)
Sends a DNS Request
Definition: DnsClient.cs:305
virtual void Dispose()
IDisposable.Dispose
Definition: DnsClient.cs:235
Implements a DNS over HTTPS (DoH)-based client.
ResourceRecord[] Authority
Authority resource records
Definition: DnsResponse.cs:96
ResourceRecord[] Answer
Answer resource records
Definition: DnsResponse.cs:86
ResourceRecord[] Additional
Additional resource records
Definition: DnsResponse.cs:106
Implements a DNS UDP-based client.
Definition: DnsUdpClient.cs:14
override void Dispose()
IDisposable.Dispose
Contains information about a DNS Question
Definition: Question.cs:12
DNS resolver, as defined in:
Definition: DnsResolver.cs:32
static bool IsValidArpanetHostName(string HostName)
Checks if a host name is a valid ARPHANET host name.
Definition: DnsResolver.cs:110
static async Task< string[]> LookupText(string Name)
Looks up text (TXT) records for a name.
Definition: DnsResolver.cs:745
static async Task< string[]> LookupDomainName(IPAddress Address)
Looks up the domain name pointing to a specific IP address.
Definition: DnsResolver.cs:726
static Task< ResourceRecord[]> Resolve(string Name, QTYPE TYPE, QCLASS CLASS)
Resolves a DNS name.
Definition: DnsResolver.cs:147
static Task< DnsResponse > Query(string Name, QTYPE TYPE, QCLASS CLASS, ProfilerThread Thread)
Resolves a DNS name.
Definition: DnsResolver.cs:343
static async Task< string[]> LookupMailExchange(string DomainName)
Looks up the Mail Exchanges related to a given domain name.
Definition: DnsResolver.cs:620
static async Task< string[]> ReverseDns(IPAddress Address)
Performs a reverse DNS lookup of an IP address.
Definition: DnsResolver.cs:973
static string AddressToName(IPAddress Address, string IP4DomainName, string IP6DomainName)
Converts an IP Address to a domain name for reverse IP lookup, or DNSBL lookup.
Definition: DnsResolver.cs:659
static Task< DnsResponse > Query(string Name, QTYPE TYPE, QCLASS CLASS)
Resolves a DNS name.
Definition: DnsResolver.cs:329
static Task< ResourceRecord[]> Resolve(string Name, QTYPE TYPE, QCLASS CLASS, ProfilerThread Thread)
Resolves a DNS name.
Definition: DnsResolver.cs:161
static IPAddress[] DnsServerAddresses
Available DNS Server Addresses.
Definition: DnsResolver.cs:83
static Task< ResourceRecord[]> Resolve(string Name, QTYPE TYPE, TYPE? ExceptionType, QCLASS CLASS)
Resolves a DNS name.
Definition: DnsResolver.cs:175
static async Task< IPAddress[]> LookupIP6Addresses(string DomainName)
Looks up the IPv6 addresses related to a given domain name.
Definition: DnsResolver.cs:600
static async Task< IPAddress[]> LookupIP4Addresses(string DomainName)
Looks up the IPv4 addresses related to a given domain name.
Definition: DnsResolver.cs:580
static Task< SRV > LookupServiceEndpoint(string DomainName, string ServiceName, string Protocol)
Looks up a service endpoint for a domain. If multiple are available, an appropriate one is selected a...
Definition: DnsResolver.cs:825
static Uri DnsOverHttpsUri
URI used in DNS over HTTPS (DoH) requests. Setting the property to null disables DNS over HTTPS (DoH)...
Definition: DnsResolver.cs:63
static async Task< SRV > LookupServiceEndpoint(string DomainName, string ServiceName, string Protocol, ProfilerThread Thread)
Looks up a service endpoint for a domain. If multiple are available, an appropriate one is selected a...
Definition: DnsResolver.cs:840
static async Task< ResourceRecord[]> Resolve(string Name, QTYPE TYPE, TYPE? ExceptionType, QCLASS CLASS, ProfilerThread Thread)
Resolves a DNS name.
Definition: DnsResolver.cs:190
static async Task< string[]> LookupBlackList(IPAddress Address, string BlackListDomainName)
Looks up an IP Address in a DNS Block List.
Definition: DnsResolver.cs:765
static async Task< SRV[]> LookupServiceEndpoints(string DomainName, string ServiceName, string Protocol)
Looks up a available service endpoints for a domain.
Definition: DnsResolver.cs:937
static int Next(int MaxValue)
Returns a non-negative random integer that is less than the specified maximum.
Definition: DnsResolver.cs:960
Abstract base class for a resource record.
string[] Text
Descriptive text.
Definition: TXT.cs:52
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:19
static async Task DeleteLazy(object Object)
Deletes an object in the database, if unlocked. If locked, object will be deleted at next opportunity...
Definition: Database.cs:756
static bool HasProvider
If a database provider is registered.
Definition: Database.cs:79
static async Task InsertLazy(object Object)
Inserts an object into the database, if unlocked. If locked, object will be inserted at next opportun...
Definition: Database.cs:156
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
Definition: Database.cs:247
static async Task Clear(string CollectionName)
Clears a collection of all objects.
Definition: Database.cs:1206
This filter selects objects that conform to all child-filters provided.
Definition: FilterAnd.cs:10
This filter selects objects that have a named field equal to a given value.
Class that keeps track of events and timing for one thread.
void Exception(System.Exception Exception)
Exception occurred
void NewState(string State)
Thread changes state.
OpCode
DNS Operation Codes
Definition: OpCode.cs:11
RCode
DNS Response Code
Definition: RCode.cs:11
CLASS
TYPE fields are used in resource records.
Definition: CLASS.cs:11
QTYPE
QTYPE fields appear in the question part of a query.
Definition: QTYPE.cs:11
QCLASS
QCLASS fields appear in the question section of a query.
Definition: QCLASS.cs:11
TYPE
TYPE fields are used in resource records.
Definition: TYPE.cs:11