private static DNSQuestion ReadQuestion(byte[] data, DataReader reader) { DNSQuestion q = new DNSQuestion(); q.QName = ReadString(data, reader); q.QType = (DNSType)reader.ReadUInt16(false); q.QClass = (DNSClass)reader.ReadUInt16(false); return(q); }
/// <summary> /// Create from an array /// </summary> /// <param name="data">The data</param> /// <returns>The parsed DNS packet</returns> public static DNSPacket FromArray(byte[] data) { DataReader reader = new DataReader(new MemoryStream(data)); DNSPacket ret = new DNSPacket(); ret.Id = reader.ReadUInt16(false); ushort flags = reader.ReadUInt16(false); ret.Query = GetBooleanFlag(flags, 0); ret.Opcode = (DNSOpcode)GetFlagValue(flags, 1); ret.AuthoritiveAnswer = GetBooleanFlag(flags, 5); ret.Truncation = GetBooleanFlag(flags, 6); ret.RecursionDesired = GetBooleanFlag(flags, 7); ret.RecursionAvailable = GetBooleanFlag(flags, 8); ret.ResponseCode = (DNSRCode)GetFlagValue(flags, 12); ushort qdcount = reader.ReadUInt16(false); ushort ancount = reader.ReadUInt16(false); ushort nscount = reader.ReadUInt16(false); ushort arcount = reader.ReadUInt16(false); if (qdcount > 0) { DNSQuestion[] questions = new DNSQuestion[qdcount]; for (int i = 0; i < qdcount; i++) { questions[i] = ReadQuestion(data, reader); } ret.Questions = questions; } if (ancount > 0) { ret.Answers = ReadResourceRecords(data, reader, ancount); } if (nscount > 0) { ret.NameServers = ReadResourceRecords(data, reader, nscount); } if (arcount > 0) { ret.Additional = ReadResourceRecords(data, reader, arcount); } return(ret); }
public void TestStubResolverAcceptsSeveralAliasesForAAAARecords() { // Make sure that chains of aliases are supported var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_6ADDRESS, AddressClass.INTERNET); var expected_alias_answer_1 = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new CNAMEResource(new Domain("www.example.com"))); var expected_alias_answer_2 = new DNSRecord( new Domain("www.example.com"), AddressClass.INTERNET, 42, new CNAMEResource(new Domain("web1.www.example.com"))); var expected_addr_answer = new DNSRecord( new Domain("web1.www.example.com"), AddressClass.INTERNET, 42, new AAAAResource(IPv6Address.Parse("2001:cafe:beef::"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_alias_answer_1, expected_alias_answer_2, expected_addr_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_6ADDRESS, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_addr_answer }; expected_result.aliases = new DNSRecord[] { expected_alias_answer_1, expected_alias_answer_2 }; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverAcceptsSOARecords() { // The same as the previous test, but this makes sure that less common // record types are still recognized as answers for the appropriate queries var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.START_OF_AUTHORITY, AddressClass.INTERNET); var expected_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new SOAResource( new Domain("ns.example.com"), new Domain("hostmaster.example.com"), 0, 360, 360, 360, 360)); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.START_OF_AUTHORITY, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_answer }; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverReturnsRedirectionsWithAAAAResourceGlue() { // Make sure that any redirections are returned, even if there aren't any actual // results, along with their glue if provided var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET); var expected_ns_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new NSResource(new Domain("ns.example.com"))); var expected_glue_answer = new DNSRecord( new Domain("ns.example.com"), AddressClass.INTERNET, 42, new AAAAResource(IPv6Address.Parse("2001:cafe:beef::"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[0], new DNSRecord[] { expected_ns_answer }, new DNSRecord[] { expected_glue_answer }); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[0]; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[] { expected_ns_answer }; expected_result.referral_additional = new DNSRecord[] { expected_glue_answer }; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverSequenceOfRelays() { // Make sure that the resolver ignores failing resolvers, as long as at least one succeeds var good_relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var bad_relay = new IPEndPoint(IPAddress.Parse("192.168.0.2"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET); var expected_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new AResource(IPv4Address.Parse("192.168.0.1"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { if (target.Equals(bad_relay)) { throw new SocketException(); } Assert.That(target, Is.EqualTo(good_relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET, new EndPoint[] { bad_relay, good_relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_answer }; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverRejectsIrrelevantGlue() { // Make sure that any redirections are returned, but rejects any bad glue var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET); var expected_ns_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new NSResource(new Domain("ns.example.com"))); var unexpected_glue_answer = new DNSRecord( new Domain("ns2.example.com"), AddressClass.INTERNET, 42, new AResource(IPv4Address.Parse("192.168.0.2"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[0], new DNSRecord[] { expected_ns_answer }, new DNSRecord[] { unexpected_glue_answer }); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[0]; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[] { expected_ns_answer }; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverAcceptsARecords() { // The idea behind this test is to make sure that direct answers to the question are accpted // (no CNAMEs, no referrals, etc.). A records are the most common query, so they are a good // starting point. var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET); var expected_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new AResource(IPv4Address.Parse("192.168.0.1"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.HOST_ADDRESS, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_answer }; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
public void TestStubResolverRecordsCNAMEAnswers() { // This ensures that any request for a CNAME to a paritcular domain ends up in the answers // list (and only the answers list) if we're asking for CNAMEs var relay = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 53); var expected_question = new DNSQuestion( new Domain("example.com"), ResourceRecordType.CANONICAL_NAME, AddressClass.INTERNET); var expected_answer = new DNSRecord( new Domain("example.com"), AddressClass.INTERNET, 42, new CNAMEResource(new Domain("www.example.com"))); var expected_packet = new DNSPacket( 42, false, QueryType.STANDARD_QUERY, false, false, true, true, ResponseType.NO_ERROR, new DNSQuestion[] { expected_question }, new DNSRecord[] { expected_answer }, new DNSRecord[0], new DNSRecord[0]); Func <EndPoint, DNSQuestion, bool, DNSPacket> gives_direct_answers = (target, question, is_recursive) => { Assert.That(target, Is.EqualTo(relay)); Assert.That(question, Is.EqualTo(expected_question)); return(expected_packet); }; var resolver = new StubResolver(new NoopCache(), gives_direct_answers); var result = resolver.Resolve(new Domain("example.com"), ResourceRecordType.CANONICAL_NAME, AddressClass.INTERNET, new EndPoint[] { relay }); var expected_result = new ResolverResult(); expected_result.answers = new DNSRecord[] { expected_answer }; expected_result.aliases = new DNSRecord[0]; expected_result.referrals = new DNSRecord[0]; expected_result.referral_additional = new DNSRecord[0]; Assert.That(result, Is.EqualTo(expected_result)); }
/** * Sends a DNS query to the given server, and waits for a response. * Possibly times out with a SocketException if the response takes * too long. */ public static DNSPacket SendQuery(EndPoint server, DNSQuestion question, bool recursive) { var rng = new Random(); var packet_id = (UInt16)rng.Next(0, (1 << 16) - 1); var to_send = new DNSPacket( packet_id, true, QueryType.STANDARD_QUERY, false, false, recursive, false, ResponseType.NO_ERROR, new DNSQuestion[] { question }, new DNSRecord[0], new DNSRecord[0], new DNSRecord[0]); var send_bytes = to_send.ToBytes(); using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { socket.ReceiveTimeout = 5 * 1000; socket.Bind(new IPEndPoint(IPAddress.Any, 0)); logger.Trace("Sending packet {0} to {1}", packet_id, server); socket.SendTo(send_bytes, server); DNSPacket recv_packet = null; while (recv_packet == null) { logger.Trace("Preparing to receive"); var recv_bytes = new byte[512]; EndPoint remote_endpoint = new IPEndPoint(IPAddress.Any, 0); socket.ReceiveFrom(recv_bytes, ref remote_endpoint); recv_packet = DNSPacket.FromBytes(recv_bytes); if (recv_packet.Id != packet_id) { logger.Trace("Trashing bad packet"); recv_packet = null; } } logger.Trace("Got response {0}", recv_packet); return(recv_packet); } }
/** * Tries to resolve a question against the cache, and possibly several * servers. Throws a ResolverException if both methods fail. */ public DNSPacket QueryServers(Domain domain, ResourceRecordType record_kind, AddressClass addr_class, EndPoint[] servers) { var question = new DNSQuestion(domain, record_kind, addr_class); foreach (var server in servers) { try { var response = send_query(server, question, true); if (response.ResponseType == ResponseType.NO_ERROR) { logger.Trace("Accepting response {0} from {1}", response, server); return(response); } } catch (SocketException error) { logger.Trace("Recoverable error: " + error); } } throw new ResolverException(question.Name, "Cannot resolve query " + question); }
/** * Resolves the given query, returning a QueryResult that contains * everything we found while doing the resolution. */ public QueryResult Execute(Domain domain, ResourceRecordType rtype, AddressClass addr_class, bool recursive) { logger.Trace("Executing query on {0} for type {1} with recursion {2}", domain, rtype, recursive); if (zone.IsAuthorityFor(domain)) { var records = zone.Query(domain, rtype, addr_class).ToList(); // It is possible that there is a CNAME that we should be aware of - in that case, check // it and see if we can find one. if (records.Count == 0) { var cname_records = zone.Query(domain, ResourceRecordType.CANONICAL_NAME, addr_class).ToArray(); if (cname_records.Length != 0) { logger.Trace("Authoritative for CNAMEs, re-executing"); // In this case, try again with the alias var alias = ((CNAMEResource)cname_records[0].Resource).Alias; var alias_results = Execute(alias, rtype, addr_class, recursive); // The RFC directs us to return any intermediate CNAMEs, which we do alias_results.Answers.InsertRange(0, cname_records); return(alias_results); } } var result = new QueryResult(); result.IsAuthority = true; result.FoundAnswer = true; result.Answers = new List <DNSRecord>(); result.Authority = new List <DNSRecord>(); result.Additional = new List <DNSRecord>(); result.Answers.AddRange(records); result.Authority.Add(zone.StartOfAuthority); return(result); } else { var owning_subzone = zone.FindSubZone(domain); if (owning_subzone != null) { logger.Trace("Subzone {0} is authoritative", owning_subzone); // We can punt on the computation to our subzone delgation var subzone_nameservers = zone.Query(owning_subzone, ResourceRecordType.NAME_SERVER, addr_class); var subzone_nameserver_addr_records = subzone_nameservers .SelectMany(ns => zone.Query(ns.Name, ResourceRecordType.HOST_ADDRESS, addr_class)); var subzone_nameserver_addrs = subzone_nameserver_addr_records.Select( record => new IPEndPoint(((AResource)record.Resource).Address, 53) ).ToArray(); IEnumerable <DNSRecord> response = null; try { var info = resolver.Resolve(domain, ResourceRecordType.HOST_ADDRESS, addr_class, subzone_nameserver_addrs); response = info.aliases.Concat(info.answers).ToList(); } catch (ResolverException err) { logger.Trace("Could not resolve from subzone: {0}", err); response = new DNSRecord[] { }; } var result = new QueryResult(); result.IsAuthority = false; result.FoundAnswer = response.Count() > 0; result.Answers = new List <DNSRecord>(response); result.Authority = new List <DNSRecord>(subzone_nameservers); result.Additional = new List <DNSRecord>(subzone_nameserver_addr_records); return(result); } else if (recursive) { // We'll have to go outside our zone and use the general-purpose resolver ResolverResult response; logger.Trace("No authoritative server is local, executing recursive resolver"); try { response = resolver.Resolve(domain, rtype, addr_class, zone.Relays); } catch (ResolverException err) { logger.Trace("Could not resolve: {0}", err); response = new ResolverResult(); response.answers = new List <DNSRecord>(); response.aliases = new List <DNSRecord>(); response.referrals = new List <DNSRecord>(); response.referral_additional = new List <DNSRecord>(); } var result = new QueryResult(); result.IsAuthority = false; result.FoundAnswer = response.answers.Count() > 0; result.Answers = response.aliases.Concat(response.answers).ToList(); result.Authority = response.referrals.ToList(); result.Additional = response.referral_additional.ToList(); return(result); } else { var cached_responses = cache.Query(domain, AddressClass.INTERNET, rtype); if (cached_responses.Count > 0) { logger.Trace("Non-recursive search found {0} cached results", cached_responses.Count); var cached_result = new QueryResult(); cached_result.IsAuthority = false; cached_result.FoundAnswer = true; cached_result.Answers = cached_responses.ToList(); cached_result.Additional = new List <DNSRecord>(); cached_result.Authority = new List <DNSRecord>(); return(cached_result); } // If we can't recurse, and our cache knows nothing, then punt onto the forwarder logger.Trace("Executing limited-case non-recursive resolver"); var question = new DNSQuestion(domain, rtype, AddressClass.INTERNET); foreach (var forwarder in zone.Relays) { try { var forward_result = ResolverUtils.SendQuery(forwarder, question, false); // If the server doesn't like our request, then pass it to something else if (forward_result.ResponseType != ResponseType.NO_ERROR && forward_result.ResponseType != ResponseType.NAME_ERROR) { continue; } var forward_return = new QueryResult(); forward_return.FoundAnswer = forward_result.ResponseType == ResponseType.NO_ERROR; forward_return.IsAuthority = false; forward_return.Answers = forward_result.Answers.ToList(); forward_return.Additional = forward_result.AdditionalRecords.ToList(); forward_return.Authority = forward_result.AuthoritativeAnswers.ToList(); return(forward_return); } catch (SocketException err) { // We can safely punt onto the next forwarder if one bails logger.Trace("Could not request from {0}: {1}", forwarder, err); } } // We can't do anything else here, so there is no such host, as far as we knot var result = new QueryResult(); result.FoundAnswer = false; result.IsAuthority = false; result.Answers = new List <DNSRecord>(); result.Authority = new List <DNSRecord>(); result.Additional = new List <DNSRecord>(); return(result); } } }
public bool AskDNS(string domain, string email) { var transactionID = (Int16)(new Random().Next(maxValue: Int16.MaxValue)); var header = new DNSHeader { transactionID = transactionID, flags = 0x0100, // Just a standard query questionResourceCount = 1, // We have one question answerResourceCount = 0, authorityResourceCount = 0, additionalResourceCount = 0 }; var question = new DNSQuestion(domain, DNSQuestion.Types.MailExchangeRecord); // We want to know about mail server var sizeDNSQuery = header.SizeOf() + question.SizeOf(); var arrDNSQuery = new byte[sizeDNSQuery]; IntPtr ptrHeader = Marshal.AllocHGlobal(header.SizeOf()); Marshal.StructureToPtr(header, ptrHeader, true); Marshal.Copy(ptrHeader, arrDNSQuery, 0, header.SizeOf()); Marshal.FreeHGlobal(ptrHeader); // Copy char data, no need to worry about endianess for char question.name.CopyTo(arrDNSQuery, header.SizeOf()); var arrQuestionType = BitConverter.GetBytes(Endianess.toBigEndian(question.type)); var arrQuestionClassType = BitConverter.GetBytes(Endianess.toBigEndian(question.classType)); arrQuestionType.CopyTo(arrDNSQuery, header.SizeOf() + question.name.Length * sizeof(byte)); arrQuestionClassType.CopyTo(arrDNSQuery, header.SizeOf() + question.name.Length * sizeof(byte) + arrQuestionType.Length); // Send datagram _dNSClient.Send(arrDNSQuery, arrDNSQuery.Length * sizeof(byte)); // Get response do { var result = _dNSClient.ReceiveAsync().Result; // Make sure it is from correct domain if (result.RemoteEndPoint.Address.Equals(_dNSServer)) { // Make sure packet has valid size header if (result.Buffer.Length > header.SizeOf()) { // Convert to DNSHeader ptrHeader = Marshal.AllocHGlobal(header.SizeOf()); Marshal.Copy(result.Buffer, 0, ptrHeader, header.SizeOf()); header = (DNSHeader)Marshal.PtrToStructure(ptrHeader, header.GetType()); Marshal.FreeHGlobal(ptrHeader); // Check that this is the correct transaction packet response if (header.transactionID == transactionID) { // Check that flags has no error and there is atleast one answer if (((header.flags & 0xf) != 0) || header.answerResourceCount == 0) { return(false); } // List of mail servers and their preferences List <Tuple <int, string> > listMailServerAndPrefs = new List <Tuple <int, string> >(); // Determine the start index of Answers structure int indexStartOfAnswer = arrDNSQuery.Length; for (int i = 0; i < header.answerResourceCount; ++i) { if ((result.Buffer[indexStartOfAnswer] & 0xC0) == 0) { throw new NotImplementedException("DNS answer name must be an offset"); } // Convert from byte stream to answer structure IntPtr ptrAnswer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DNSResource))); Marshal.Copy(result.Buffer, indexStartOfAnswer, ptrAnswer, Marshal.SizeOf(typeof(DNSResource))); var answer = (DNSResource)Marshal.PtrToStructure(ptrAnswer, typeof(DNSResource)); Marshal.FreeHGlobal(ptrAnswer); // Increment index ahead indexStartOfAnswer += answer.SizeOf(); if (indexStartOfAnswer > result.Buffer.Length) { break; } // Read preference no, smaller number is more preferred server if (answer.dataLength < 2) { continue; } Int16 preferenceMailExchangeServer = BitConverter.ToInt16(result.Buffer, indexStartOfAnswer); if (Endianess.MachineArchIsLittleEndian) { preferenceMailExchangeServer = Endianess.toLittleEndian(preferenceMailExchangeServer); } indexStartOfAnswer += Marshal.SizeOf(preferenceMailExchangeServer); // Read server name int sizeServerName = answer.dataLength - Marshal.SizeOf(preferenceMailExchangeServer); if (sizeServerName < 2) { continue; } if (indexStartOfAnswer + sizeServerName > result.Buffer.Length) { break; } string serverName = string.Empty; int j = indexStartOfAnswer; while (j < indexStartOfAnswer + sizeServerName - 1) { if ((result.Buffer[j] & 0xC0) != 0) { // It's an offset var offset = BitConverter.ToInt16(result.Buffer, j); if (Endianess.MachineArchIsLittleEndian) { offset = Endianess.toLittleEndian(offset); } offset &= 0x3F; // Remove two most significant bits j += Marshal.SizeOf(offset); // Transverse position from offset until null do { serverName += Encoding.ASCII.GetString(result.Buffer, offset + 1, result.Buffer[offset]) + '.'; offset += (Int16)(result.Buffer[offset] + 1); } while (result.Buffer[offset] != 0); } else { // It's just size serverName += System.Text.Encoding.ASCII.GetString(result.Buffer, j + 1, result.Buffer[j]) + '.'; j += result.Buffer[j] + 1; } } indexStartOfAnswer += answer.dataLength - Marshal.SizeOf(preferenceMailExchangeServer); if (string.IsNullOrEmpty(serverName) && serverName.Length > 2) { continue; } serverName = serverName.Substring(0, serverName.Length - 1); // Remove terminating dot listMailServerAndPrefs.Add(new Tuple <int, string>((int)preferenceMailExchangeServer, serverName)); } // Sort by preference listMailServerAndPrefs = listMailServerAndPrefs.OrderBy(x => x.Item1).ToList(); // Connect with SMTP _sMTPClient = new TcpClient(); _sMTPClient.ConnectAsync(listMailServerAndPrefs.First().Item2, _sMTPPort).Wait(); if (!_sMTPClient.Connected) { throw new WebException("SMTP server refused connection"); } var arrSMTPResponse = new byte[256]; var sizeSMTPResponse = _sMTPClient.Client.Receive(arrSMTPResponse); var connectResponse = Encoding.ASCII.GetString(arrSMTPResponse); if (!connectResponse.StartsWith("220")) { throw new WebException("SMTP server refused to connect"); } _sMTPClient.Client.Send(Encoding.ASCII.GetBytes("HELO " + HelloServer + "\r\n")); sizeSMTPResponse = _sMTPClient.Client.Receive(arrSMTPResponse); var heloResponse = Encoding.ASCII.GetString(arrSMTPResponse); if (!heloResponse.StartsWith("250")) { throw new WebException("SMTP server refused to handshake"); } _sMTPClient.Client.Send(Encoding.ASCII.GetBytes("MAIL FROM:<" + QueryEmail + ">\r\n")); sizeSMTPResponse = _sMTPClient.Client.Receive(arrSMTPResponse); var mailfromResponse = Encoding.ASCII.GetString(arrSMTPResponse); if (!mailfromResponse.StartsWith("250")) { throw new WebException("SMTP server refused to accept mail from"); } _sMTPClient.Client.Send(Encoding.ASCII.GetBytes("RCPT TO:<" + email + ">\r\n")); sizeSMTPResponse = _sMTPClient.Client.Receive(arrSMTPResponse); var rcpttoResponse = Encoding.ASCII.GetString(arrSMTPResponse); _sMTPClient.Client.Send(Encoding.ASCII.GetBytes("QUIT")); // Bye _sMTPClient.Close(); if (!rcpttoResponse.StartsWith("250")) { return(false); } break; } } } } while (true); return(true); }
private static DNSQuestion ReadQuestion(byte[] data, DataReader reader) { DNSQuestion q = new DNSQuestion(); q.QName = ReadString(data, reader); q.QType = (DNSType)reader.ReadUInt16(false); q.QClass = (DNSClass)reader.ReadUInt16(false); return q; }
/// <summary> /// Create from an array /// </summary> /// <param name="data">The data</param> /// <returns>The parsed DNS packet</returns> public static DNSPacket FromArray(byte[] data) { DataReader reader = new DataReader(new MemoryStream(data)); DNSPacket ret = new DNSPacket(); ret.Id = reader.ReadUInt16(false); ushort flags = reader.ReadUInt16(false); ret.Query = GetBooleanFlag(flags, 0); ret.Opcode = (DNSOpcode)GetFlagValue(flags, 1); ret.AuthoritiveAnswer = GetBooleanFlag(flags, 5); ret.Truncation = GetBooleanFlag(flags, 6); ret.RecursionDesired = GetBooleanFlag(flags, 7); ret.RecursionAvailable = GetBooleanFlag(flags, 8); ret.ResponseCode = (DNSRCode)GetFlagValue(flags, 12); ushort qdcount = reader.ReadUInt16(false); ushort ancount = reader.ReadUInt16(false); ushort nscount = reader.ReadUInt16(false); ushort arcount = reader.ReadUInt16(false); if (qdcount > 0) { DNSQuestion[] questions = new DNSQuestion[qdcount]; for (int i = 0; i < qdcount; i++) { questions[i] = ReadQuestion(data, reader); } ret.Questions = questions; } if (ancount > 0) { ret.Answers = ReadResourceRecords(data, reader, ancount); } if (nscount > 0) { ret.NameServers = ReadResourceRecords(data, reader, nscount); } if (arcount > 0) { ret.Additional = ReadResourceRecords(data, reader, arcount); } return ret; }