/// <summary> /// Sends a DNS Request /// </summary> /// <param name="OpCode">OpCode</param> /// <param name="Recursive">If recursive evaluation is desired. /// (Recursive evaluation is optional on behalf of the DNS server.</param> /// <param name="Questions">Questions</param> /// <param name="Destination">Destination. If null, default destination is assumed.</param> /// <param name="Callback">Method to call when response is returned.</param> /// <param name="State">State object to pass on to callback method.</param> public void SendRequest(OpCode OpCode, bool Recursive, Question[] Questions, IPEndPoint Destination, DnsMessageEventHandler Callback, object State) { using (MemoryStream Request = new MemoryStream()) { ushort ID = DnsResolver.NextID; DnsClient.WriteUInt16(ID, Request); byte b = (byte)((int)OpCode << 3); if (Recursive) { b |= 1; } Request.WriteByte(b); Request.WriteByte((byte)RCode.NoError); int c = Questions.Length; if (c == 0) { throw new ArgumentException("No questions included in request.", nameof(Questions)); } if (c > ushort.MaxValue) { throw new ArgumentException("Too many questions in request.", nameof(Questions)); } DnsClient.WriteUInt16((ushort)c, Request); // Query Count DnsClient.WriteUInt16(0, Request); // Answer Count DnsClient.WriteUInt16(0, Request); // Authoritative Count DnsClient.WriteUInt16(0, Request); // Additional Count Dictionary <string, ushort> NamePositions = new Dictionary <string, ushort>(); foreach (Question Q in Questions) { DnsClient.WriteName(Q.QNAME, Request, NamePositions); DnsClient.WriteUInt16((ushort)Q.QTYPE, Request); DnsClient.WriteUInt16((ushort)Q.QCLASS, Request); } byte[] Packet = Request.ToArray(); this.BeginTransmit(ID, Packet, Destination, Callback, State); } }
/// <summary> /// Sends a message to a DNS server. /// </summary> /// <param name="ID">Message ID</param> /// <param name="Message">Encoded message</param> /// <param name="Destination">Destination. If null, default destination is assumed.</param> /// <param name="Callback">method to call when a response is returned.</param> /// <param name="State">State object to pass on to callback method.</param> protected async void BeginTransmit(ushort ID, byte[] Message, IPEndPoint Destination, DnsMessageEventHandler Callback, object State) { if (this.disposed) { return; } if (!(Callback is null)) { Rec Rec = new Rec() { ID = ID, Output = Message, Destination = Destination, Callback = Callback, State = State }; lock (this.outgoingMessages) { this.outgoingMessages[ID] = Rec; } this.scheduler.Add(DateTime.Now.AddSeconds(2), this.CheckRetry, Rec); } lock (this.outputQueue) { if (this.isWriting) { this.outputQueue.AddLast(new KeyValuePair <byte[], IPEndPoint>(Message, Destination)); return; } else { this.isWriting = true; } } try { while (Message != null) { this.TransmitBinary(Message); await this.SendAsync(Message, Destination); if (this.disposed) { return; } lock (this.outputQueue) { if (this.outputQueue.First is null) { this.isWriting = false; Message = null; } else { Message = this.outputQueue.First.Value.Key; Destination = this.outputQueue.First.Value.Value; this.outputQueue.RemoveFirst(); } } } } catch (Exception ex) { this.Error(ex.Message); } }
/// <summary> /// Execute a DNS query. /// </summary> /// <param name="Questions">Questions</param> /// <param name="Destination">Destination. If null, default destination is assumed.</param> /// <param name="Callback">Method to call when response is returned.</param> /// <param name="State">State object to pass on to callback method.</param> public void Query(Question[] Questions, IPEndPoint Destination, DnsMessageEventHandler Callback, object State) { this.SendRequest(OpCode.Query, false, Questions, Destination, Callback, State); }
/// <summary> /// Execute a DNS query. /// </summary> /// <param name="QNAME">Query Name</param> /// <param name="QTYPEs">Query Types</param> /// <param name="QCLASS">Query Class</param> /// <param name="Destination">Destination. If null, default destination is assumed.</param> /// <param name="Callback">Method to call when response is returned.</param> /// <param name="State">State object to pass on to callback method.</param> public void Query(string QNAME, QTYPE[] QTYPEs, QCLASS QCLASS, IPEndPoint Destination, DnsMessageEventHandler Callback, object State) { this.Query(ToQuestions(QNAME, QTYPEs, QCLASS), Destination, Callback, State); }
/// <summary> /// Execute a DNS query. /// </summary> /// <param name="QNAME">Query Name</param> /// <param name="QTYPE">Query Type</param> /// <param name="QCLASS">Query Class</param> /// <param name="Destination">Destination. If null, default destination is assumed.</param> /// <param name="Callback">Method to call when response is returned.</param> /// <param name="State">State object to pass on to callback method.</param> public void Query(string QNAME, QTYPE QTYPE, QCLASS QCLASS, IPEndPoint Destination, DnsMessageEventHandler Callback, object State) { this.Query(new Question[] { new Question(QNAME, QTYPE, QCLASS) }, Destination, Callback, State); }