Ejemplo n.º 1
0
        private DnsMessage ProcessQuery(DnsMessageBase queryBase, IPAddress clientAddress, ProtocolType protocol)
        {
            DnsMessage query = queryBase as DnsMessage;

            foreach (DnsQuestion q in query.Questions)
            {
                if (q.RecordType == RecordType.A)
                {
                    if (!q.Name.EndsWith(".p2p"))
                    {
                        query.ReturnCode = ReturnCode.Refused;
                        return query;
                    }

                    Console.WriteLine("DNS LOOKUP: " + q.Name);

                    DomainMapping mapping;
                    if (!mappingLookup.TryGetValue(q.Name, out mapping))
                    {
                        query.ReturnCode = ReturnCode.ServerFailure;
                        return query;
                    }

                    query.AnswerRecords.Add(new ARecord(mapping.Name, mapping.TimeToLive.Seconds, mapping.Address));
                    return query;
                }
                else
                    query.ReturnCode = ReturnCode.NotImplemented;
            }

            return query;
        }
Ejemplo n.º 2
0
 protected override void When()
 {
     this.response = this.dnsLookup.ProcessQuery(
         new DnsMessage
             {
                 Questions =
                     new System.Collections.Generic.List<DnsQuestion> { new DnsQuestion("test.dev", RecordType.A, RecordClass.Any) }
             },
         IPAddress.Parse("192.168.0.1"), ProtocolType.IPv4);
 }
Ejemplo n.º 3
0
        public DnsMessageBase HandleQuery(DnsMessageBase message, IPAddress clientAddress, ProtocolType protocol)
        {
            var query = message as DnsMessage;
            if (query == null)
                message.ReturnCode = ReturnCode.ServerFailure;
            else
                ProcessQuery(query);

            return message;
        }
Ejemplo n.º 4
0
        static DnsMessageBase ProcessQuery(DnsMessageBase message, IPAddress clientAddress, ProtocolType protocol)
        {
            message.IsQuery = false;

            DnsMessage query = message as DnsMessage;

            if ((query != null) && (query.Questions.Count == 1))
            {
                // send query to upstream server
                DnsQuestion question = query.Questions[0];
                Random rnd = new Random();
                Console.WriteLine(question.Name);

                System.Threading.Tasks.Parallel.ForEach(dnslist, (site, state) =>
                {
                    Console.WriteLine("Get Info from: " +site);
                    DnsClient cd = new DnsClient(IPAddress.Parse(dnslist[rnd.Next(0, dnslist.Length - 1)]), 500);
                    DnsMessage answer = cd.Resolve(question.Name, question.RecordType, question.RecordClass);

                        if (answer != null)
                        {
                            foreach (DnsRecordBase record in (answer.AnswerRecords))
                            {
                                lock (query)
                                {
                                    query.AnswerRecords.Add(record);
                                }
                                Console.WriteLine(record.Name);
                            }
                            foreach (DnsRecordBase record in (answer.AdditionalRecords))
                            {
                                lock (query)
                                {
                                    query.AnswerRecords.Add(record);
                                }
                                Console.WriteLine(record.Name);
                            }
                            lock (query)
                            {
                                query.ReturnCode = ReturnCode.NoError;
                                state.Break();
                            }
                        }
                });
                // if got an answer, copy it to the message sent to the client
            }
            if (query.ReturnCode == ReturnCode.NoError)
            {
                return query;
            }
            // Not a valid query or upstream server did not answer correct
            message.ReturnCode = ReturnCode.ServerFailure;
            return message;
        }
        static DnsMessageBase ProcessQuery(DnsMessageBase message, IPAddress clientAddress, ProtocolType protocol)
        {
            Ok = true;

            message.IsQuery = false;

            DnsMessage query = message as DnsMessage;

            if (query != null)
            {
                if (query.Questions.Count == 1)
                {
                    DnsQuestion question = query.Questions[0];

                    Console.WriteLine("Query: {0} {1} {2}", question.Name, question.RecordType, question.RecordClass);

                    DnsMessage answer;
                    answer = ResolverInstance.GetAnswer(question);

                    // if got an answer, copy it to the message sent to the client
                    if (answer != null)
                    {
                        foreach (DnsRecordBase record in (answer.AnswerRecords))
                        {
                            Console.WriteLine("Answer: {0}", record);
                            query.AnswerRecords.Add(record);
                        }
                        foreach (DnsRecordBase record in (answer.AdditionalRecords))
                        {
                            Console.WriteLine("Additional Answer: {0}", record);
                            query.AnswerRecords.Add(record);
                        }

                        query.ReturnCode = ReturnCode.NoError;
                        return query;
                    }
                }
                else
                    Debug.WriteLine("Too many questions ({0})", query.Questions.Count);
            }
            // Not a valid query or upstream server did not answer correct
            message.ReturnCode = ReturnCode.ServerFailure;
            return message;
        }
Ejemplo n.º 6
0
        public DnsMessageBase ProcessQuery(DnsMessageBase message, IPAddress clientAddress, ProtocolType protocol)
        {
            message.IsQuery = false;

            var query = message as DnsMessage;

            if ((query != null) && (query.Questions.Count == 1))
            {
                var question = query.Questions[0];

                var answers = this.mappings.Select(m => m.Answer(question)).Where(a => a != null);
                if (answers.Any())
                {
                    query.ReturnCode = ReturnCode.NoError;
                    foreach (var answer in answers)
                        query.AnswerRecords.Add(answer);
                    return query;
                }
            }

            message.ReturnCode = ReturnCode.ServerFailure;
            return message;
        }
Ejemplo n.º 7
0
        private DnsMessageBase OnQuery(DnsMessageBase message, IPAddress clientaddress, ProtocolType protocoltype)
        {
            message.IsQuery = false;

            if (!Configuration.ServerEnabled)
            {
                Logger.Log(LogSeverity.Warning, "Received a DNS request while the server is not enabled.");

                message.ReturnCode = ReturnCode.ServerFailure;
                return message;
            }

            var query = message as DnsMessage;

            if (query != null && query.Questions.Count == 1)
            {
                // Get the question
                DnsQuestion question = query.Questions[0];

                // Apply all filters on the question
                FilterAction filterResult = ApplyFilters(question);

                // Only check the cache when we do not need to auto-reject
                if (filterResult != FilterAction.Reject)
                {
                    DnsRecordBase[] remappedRecords = ApplyRemaps(question);

                    if (remappedRecords.Length > 0)
                    {
                        query.AnswerRecords.AddRange(remappedRecords);
                        query.ReturnCode = ReturnCode.NoError;

                        return query;
                    }

                    if (Configuration.DnsCacheEnabled)
                    {
                        lock (_dnsCache)
                        {
                            // Check the cache
                            CacheEntry cachedEntry = _dnsCache.FirstOrDefault(c => c.Question.IsEqualTo(question));

                            if (cachedEntry != null)
                            {
                                // Cache hit!
                                if (Configuration.DnsCacheTtl > 0 && DateTime.UtcNow - cachedEntry.LastHit > new TimeSpan(0, 0, 0, Configuration.DnsCacheTtl))
                                {
                                    // Hit expired
                                    _dnsCache.Remove(cachedEntry);
                                }
                                else
                                {
                                    // Hit did not expire, use it.
                                    cachedEntry.Hit();

                                    query.AnswerRecords.AddRange(cachedEntry.Records);
                                    query.ReturnCode = ReturnCode.NoError;

                                    return query;
                                }
                            }
                        }
                    }
                }

                Logger.Log(LogSeverity.Debug, "QUERY: {0} CLASS: {1} TYPE: {2} FILTER: {3}", question.Name, question.RecordClass.ToString(), question.RecordType.ToString(), filterResult.ToString());

                DnsMessage answer = null;

                switch (filterResult)
                {
                    case FilterAction.Proxy:
                        if (_dnsSocksClient == null)
                        {
                            // Socks not enabled
                            message.ReturnCode = ReturnCode.ServerFailure;
                            return message;
                        }

                        answer = _dnsSocksClient.Resolve(question.Name, question.RecordType, question.RecordClass);
                        break;

                    case FilterAction.SkipProxy:
                        if (_dnsClient == null)
                        {
                            // Socks not enabled
                            message.ReturnCode = ReturnCode.ServerFailure;
                            return message;
                        }

                        answer = _dnsClient.Resolve(question.Name, question.RecordType, question.RecordClass);

                        break;

                    case FilterAction.Reject:
                        message.ReturnCode = ReturnCode.ServerFailure;
                        return message;
                }

                // if got an answer, copy it to the message sent to the client
                if (answer != null)
                {
                    foreach (DnsRecordBase record in (answer.AnswerRecords))
                    {
                        query.AnswerRecords.Add(record);
                    }
                    foreach (DnsRecordBase record in (answer.AdditionalRecords))
                    {
                        query.AnswerRecords.Add(record);
                    }

                    query.ReturnCode = ReturnCode.NoError;

                    if (Configuration.DnsCacheEnabled)
                    {
                        lock (_dnsCache)
                        {
                            if (!_dnsCache.Any(c => c.Question.IsEqualTo(question)))
                            {
                                var cacheEntry = new CacheEntry(question, query.AnswerRecords.ToArray(), Configuration.DnsCacheTtl);
                                cacheEntry.Hit();

                                _dnsCache.Add(cacheEntry);

                                // Check if the cache is full
                                if (Configuration.DnsCacheSize > 0 && _dnsCache.Count > Configuration.DnsCacheSize)
                                {
                                    // Remove the oldest entry
                                    _dnsCache.Remove(_dnsCache.OrderBy(c => c.LastHit).First());
                                }

                                Logger.Log(LogSeverity.Debug, "DNS reply cached.");
                            }
                        }
                    }

                    return query;
                }
            }

            // Not a valid query or upstream server did not answer correct
            message.ReturnCode = ReturnCode.ServerFailure;
            return message;
        }
Ejemplo n.º 8
0
 internal override void ParseRecordData(byte[] resultData, int currentPosition, int length)
 {
     Longitude = Double.Parse(DnsMessageBase.ParseText(resultData, ref currentPosition), CultureInfo.InvariantCulture);
     Latitude  = Double.Parse(DnsMessageBase.ParseText(resultData, ref currentPosition), CultureInfo.InvariantCulture);
     Altitude  = Double.Parse(DnsMessageBase.ParseText(resultData, ref currentPosition), CultureInfo.InvariantCulture);
 }
Ejemplo n.º 9
0
 internal override void ParseRecordData(byte[] resultData, int startPosition, int length)
 {
     Priority = DnsMessageBase.ParseUShort(resultData, ref startPosition);
     Weight   = DnsMessageBase.ParseUShort(resultData, ref startPosition);
     Target   = DnsMessageBase.ParseText(resultData, ref startPosition, length - 4);
 }
Ejemplo n.º 10
0
        private async void HandleTcpListenerAsync()
        {
            TcpClient client = null;

            try
            {
                try
                {
                    client = await _tcpListener.AcceptTcpClientAsync();

                    ClientConnectedEventArgs clientConnectedEventArgs = new ClientConnectedEventArgs(ProtocolType.Udp, (IPEndPoint)client.Client.RemoteEndPoint);
                    await ClientConnected.RaiseAsync(this, clientConnectedEventArgs);

                    if (clientConnectedEventArgs.RefuseConnect)
                    {
                        return;
                    }
                }
                finally
                {
                    lock (_listenerLock)
                    {
                        _hasActiveTcpListener = false;
                    }
                }

                StartTcpListenerTask();

                using (NetworkStream stream = client.GetStream())
                {
                    while (true)
                    {
                        byte[] buffer = await ReadIntoBufferAsync(client, stream, 2);

                        if (buffer == null)                         // client disconneted while reading or timeout
                        {
                            break;
                        }

                        int offset = 0;
                        int length = DnsMessageBase.ParseUShort(buffer, ref offset);

                        buffer = await ReadIntoBufferAsync(client, stream, length);

                        if (buffer == null)                         // client disconneted while reading or timeout
                        {
                            throw new Exception("Client disconnted or timed out while sending data");
                        }

                        DnsMessageBase query;
                        byte[]         tsigMac;
                        try
                        {
                            query   = DnsMessageBase.CreateByFlag(buffer, TsigKeySelector, null);
                            tsigMac = query.TSigOptions?.Mac;
                        }
                        catch (Exception e)
                        {
                            throw new Exception("Error parsing dns query", e);
                        }

                        DnsMessageBase response;
                        try
                        {
                            response = await ProcessMessageAsync(query, ProtocolType.Tcp, (IPEndPoint)client.Client.RemoteEndPoint);
                        }
                        catch (Exception ex)
                        {
                            OnExceptionThrownAsync(ex);

                            response         = DnsMessageBase.CreateByFlag(buffer, TsigKeySelector, null);
                            response.IsQuery = false;
                            response.AdditionalRecords.Clear();
                            response.AuthorityRecords.Clear();
                            response.ReturnCode = ReturnCode.ServerFailure;
                        }

                        byte[] newTsigMac;

                        length = response.Encode(true, tsigMac, false, out buffer, out newTsigMac);

                        if (length <= 65535)
                        {
                            await stream.WriteAsync(buffer, 0, length);
                        }
                        else
                        {
                            if ((response.Questions.Count == 0) || (response.Questions[0].RecordType != RecordType.Axfr))
                            {
                                OnExceptionThrownAsync(new ArgumentException("The length of the serialized response is greater than 65,535 bytes"));

                                response         = DnsMessageBase.CreateByFlag(buffer, TsigKeySelector, null);
                                response.IsQuery = false;
                                response.AdditionalRecords.Clear();
                                response.AuthorityRecords.Clear();
                                response.ReturnCode = ReturnCode.ServerFailure;

                                length = response.Encode(true, tsigMac, false, out buffer, out newTsigMac);
                                await stream.WriteAsync(buffer, 0, length);
                            }
                            else
                            {
                                bool isSubSequentResponse = false;

                                while (true)
                                {
                                    List <DnsRecordBase> nextPacketRecords = new List <DnsRecordBase>();

                                    while (length > 65535)
                                    {
                                        int lastIndex   = Math.Min(500, response.AnswerRecords.Count / 2);
                                        int removeCount = response.AnswerRecords.Count - lastIndex;

                                        nextPacketRecords.InsertRange(0, response.AnswerRecords.GetRange(lastIndex, removeCount));
                                        response.AnswerRecords.RemoveRange(lastIndex, removeCount);

                                        length = response.Encode(true, tsigMac, isSubSequentResponse, out buffer, out newTsigMac);
                                    }

                                    await stream.WriteAsync(buffer, 0, length);

                                    if (nextPacketRecords.Count == 0)
                                    {
                                        break;
                                    }

                                    isSubSequentResponse = true;
                                    tsigMac = newTsigMac;
                                    response.AnswerRecords = nextPacketRecords;
                                    length = response.Encode(true, tsigMac, true, out buffer, out newTsigMac);
                                }
                            }
                        }

                        // Since support for multiple tsig signed messages is not finished, just close connection after response to first signed query
                        if (newTsigMac != null)
                        {
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                OnExceptionThrownAsync(ex);
            }
            finally
            {
                try
                {
                    // ReSharper disable once ConstantConditionalAccessQualifier
                    client?.Close();
                }
                catch
                {
                    // ignored
                }

                lock (_listenerLock)
                {
                    _availableTcpListener++;
                }
                StartTcpListenerTask();
            }
        }
Ejemplo n.º 11
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <DomainName, ushort> domainNames, bool useCanonical)
 {
     DnsMessageBase.EncodeUInt(messageData, ref currentPosition, SerialNumber);
     DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort)Flags);
     EncodeTypeBitmap(messageData, ref currentPosition, Types);
 }
Ejemplo n.º 12
0
 internal override void ParseRecordData(byte[] resultData, int startPosition, int length)
 {
     Preference         = DnsMessageBase.ParseUShort(resultData, ref startPosition);
     ExchangeDomainName = DnsMessageBase.ParseDomainName(resultData, ref startPosition);
 }
Ejemplo n.º 13
0
 internal override void ParseRecordData(byte[] resultData, int startPosition, int length)
 {
     Preference = DnsMessageBase.ParseUShort(resultData, ref startPosition);
     NodeID     = DnsMessageBase.ParseULong(resultData, ref startPosition);
 }
Ejemplo n.º 14
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <DomainName, ushort> domainNames, bool useCanonical)
 {
     DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, PublicKey);
 }
Ejemplo n.º 15
0
        private static DateTime ParseDateTime(byte[] buffer, ref int currentPosition)
        {
            int timeStamp = DnsMessageBase.ParseInt(buffer, ref currentPosition);

            return(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timeStamp).ToLocalTime());
        }
Ejemplo n.º 16
0
        internal static void EncodeDateTime(byte[] buffer, ref int currentPosition, DateTime value)
        {
            int timeStamp = (int)(value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;

            DnsMessageBase.EncodeInt(buffer, ref currentPosition, timeStamp);
        }
Ejemplo n.º 17
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <string, ushort> domainNames)
 {
     DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Address.GetAddressBytes());
 }
Ejemplo n.º 18
0
 internal override void ParseRecordData(byte[] resultData, int startPosition, int length)
 {
     Address = new IPAddress(DnsMessageBase.ParseByteData(resultData, ref startPosition, 16));
 }
Ejemplo n.º 19
0
 internal override void EncodeData(byte[] messageData, ref int currentPosition)
 {
     DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, Data);
 }
Ejemplo n.º 20
0
 internal InvalidSignedMessageEventArgs(DnsMessageBase query, ProtocolType protocolType, IPEndPoint remoteEndpoint)
 {
     Query          = query;
     ProtocolType   = protocolType;
     RemoteEndpoint = remoteEndpoint;
 }
Ejemplo n.º 21
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <string, ushort> domainNames)
 {
     DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, MailBox, false, domainNames);
     DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, TxtDomainName, false, domainNames);
 }
Ejemplo n.º 22
0
		private async Task<DnsMessageBase> ProcessMessageAsync(DnsMessageBase query, ProtocolType protocolType, IPEndPoint remoteEndpoint)
		{
			if (query.TSigOptions != null)
			{
				switch (query.TSigOptions.ValidationResult)
				{
					case ReturnCode.BadKey:
					case ReturnCode.BadSig:
						query.IsQuery = false;
						query.ReturnCode = ReturnCode.NotAuthoritive;
						query.TSigOptions.Error = query.TSigOptions.ValidationResult;
						query.TSigOptions.KeyData = null;

#pragma warning disable 4014
						InvalidSignedMessageReceived.RaiseAsync(this, new InvalidSignedMessageEventArgs(query, protocolType, remoteEndpoint));
#pragma warning restore 4014

						return query;

					case ReturnCode.BadTime:
						query.IsQuery = false;
						query.ReturnCode = ReturnCode.NotAuthoritive;
						query.TSigOptions.Error = query.TSigOptions.ValidationResult;
						query.TSigOptions.OtherData = new byte[6];
						int tmp = 0;
						TSigRecord.EncodeDateTime(query.TSigOptions.OtherData, ref tmp, DateTime.Now);

#pragma warning disable 4014
						InvalidSignedMessageReceived.RaiseAsync(this, new InvalidSignedMessageEventArgs(query, protocolType, remoteEndpoint));
#pragma warning restore 4014

						return query;
				}
			}

			QueryReceivedEventArgs eventArgs = new QueryReceivedEventArgs(query, protocolType, remoteEndpoint);
			await QueryReceived.RaiseAsync(this, eventArgs);
			return eventArgs.Response;
		}
Ejemplo n.º 23
0
 internal override void ParseData(byte[] resultData, int startPosition, int length)
 {
     LeaseTime = TimeSpan.FromSeconds(DnsMessageBase.ParseInt(resultData, ref startPosition));
 }
Ejemplo n.º 24
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <string, ushort> domainNames)
 {
     DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference);
     DnsMessageBase.EncodeULong(messageData, ref currentPosition, NodeID);
 }
Ejemplo n.º 25
0
 internal override void EncodeData(byte[] messageData, ref int currentPosition)
 {
     DnsMessageBase.EncodeInt(messageData, ref currentPosition, (int)LeaseTime.TotalSeconds);
 }
Ejemplo n.º 26
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <DomainName, ushort> domainNames, bool useCanonical)
 {
     DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Preference);
     DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, ExchangeDomainName, domainNames, useCanonical);
 }
Ejemplo n.º 27
0
 internal override void ParseRecordData(byte[] resultData, int startPosition, int length)
 {
     RecordData = DnsMessageBase.ParseByteData(resultData, ref startPosition, length);
 }
Ejemplo n.º 28
0
        private async void HandleUdpListenerAsync()
        {
            try
            {
                UdpReceiveResult receiveResult;
                try
                {
                    receiveResult = await _udpListener.ReceiveAsync();
                }
                catch (ObjectDisposedException)
                {
                    return;
                }
                finally
                {
                    lock (_listenerLock)
                    {
                        _hasActiveUdpListener = false;
                    }
                }

                ClientConnectedEventArgs clientConnectedEventArgs = new ClientConnectedEventArgs(ProtocolType.Udp, receiveResult.RemoteEndPoint);
                await ClientConnected.RaiseAsync(this, clientConnectedEventArgs);

                if (clientConnectedEventArgs.RefuseConnect)
                {
                    return;
                }

                StartUdpListenerTask();

                byte[] buffer = receiveResult.Buffer;

                DnsMessageBase query;
                byte[]         originalMac;
                try
                {
                    query       = DnsMessageBase.CreateByFlag(buffer, TsigKeySelector, null);
                    originalMac = query.TSigOptions?.Mac;
                }
                catch (Exception e)
                {
                    throw new Exception("Error parsing dns query", e);
                }

                DnsMessageBase response;
                try
                {
                    response = await ProcessMessageAsync(query, ProtocolType.Udp, receiveResult.RemoteEndPoint);
                }
                catch (Exception ex)
                {
                    OnExceptionThrownAsync(ex);
                    response = null;
                }

                if (response == null)
                {
                    response         = query;
                    query.IsQuery    = false;
                    query.ReturnCode = ReturnCode.ServerFailure;
                }

                int length = response.Encode(false, originalMac, out buffer);

                #region Truncating
                DnsMessage message = response as DnsMessage;

                if (message != null)
                {
                    int maxLength = 512;
                    if (query.IsEDnsEnabled && message.IsEDnsEnabled)
                    {
                        maxLength = Math.Max(512, (int)message.EDnsOptions.UdpPayloadSize);
                    }

                    while (length > maxLength)
                    {
                        // First step: remove data from additional records except the opt record
                        if ((message.IsEDnsEnabled && (message.AdditionalRecords.Count > 1)) || (!message.IsEDnsEnabled && (message.AdditionalRecords.Count > 0)))
                        {
                            for (int i = message.AdditionalRecords.Count - 1; i >= 0; i--)
                            {
                                if (message.AdditionalRecords[i].RecordType != RecordType.Opt)
                                {
                                    message.AdditionalRecords.RemoveAt(i);
                                }
                            }

                            length = message.Encode(false, originalMac, out buffer);
                            continue;
                        }

                        int savedLength = 0;
                        if (message.AuthorityRecords.Count > 0)
                        {
                            for (int i = message.AuthorityRecords.Count - 1; i >= 0; i--)
                            {
                                savedLength += message.AuthorityRecords[i].MaximumLength;
                                message.AuthorityRecords.RemoveAt(i);

                                if ((length - savedLength) < maxLength)
                                {
                                    break;
                                }
                            }

                            message.IsTruncated = true;

                            length = message.Encode(false, originalMac, out buffer);
                            continue;
                        }

                        if (message.AnswerRecords.Count > 0)
                        {
                            for (int i = message.AnswerRecords.Count - 1; i >= 0; i--)
                            {
                                savedLength += message.AnswerRecords[i].MaximumLength;
                                message.AnswerRecords.RemoveAt(i);

                                if ((length - savedLength) < maxLength)
                                {
                                    break;
                                }
                            }

                            message.IsTruncated = true;

                            length = message.Encode(false, originalMac, out buffer);
                            continue;
                        }

                        if (message.Questions.Count > 0)
                        {
                            for (int i = message.Questions.Count - 1; i >= 0; i--)
                            {
                                savedLength += message.Questions[i].MaximumLength;
                                message.Questions.RemoveAt(i);

                                if ((length - savedLength) < maxLength)
                                {
                                    break;
                                }
                            }

                            message.IsTruncated = true;

                            length = message.Encode(false, originalMac, out buffer);
                        }
                    }
                }
                #endregion

                await _udpListener.SendAsync(buffer, length, receiveResult.RemoteEndPoint);
            }
            catch (Exception ex)
            {
                OnExceptionThrownAsync(ex);
            }
            finally
            {
                lock (_listenerLock)
                {
                    _availableUdpListener++;
                }
                StartUdpListenerTask();
            }
        }
Ejemplo n.º 29
0
 internal override void ParseRecordData(byte[] resultData, int startPosition, int length)
 {
     X25Address += DnsMessageBase.ParseText(resultData, ref startPosition);
 }
Ejemplo n.º 30
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <DomainName, ushort> domainNames, bool useCanonical)
 {
     DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Priority);
     DnsMessageBase.EncodeUShort(messageData, ref currentPosition, Weight);
     DnsMessageBase.EncodeTextWithoutLength(messageData, ref currentPosition, Target);
 }
Ejemplo n.º 31
0
 internal void Encode(byte[] messageData, int offset, ref int currentPosition, Dictionary <DomainName, ushort> domainNames)
 {
     DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, Name, domainNames, false);
     DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort)RecordType);
     DnsMessageBase.EncodeUShort(messageData, ref currentPosition, (ushort)RecordClass);
 }
Ejemplo n.º 32
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <DomainName, ushort> domainNames, bool useCanonical)
 {
     DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, Longitude.ToString(CultureInfo.InvariantCulture));
     DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, Latitude.ToString(CultureInfo.InvariantCulture));
     DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, Altitude.ToString(CultureInfo.InvariantCulture));
 }
Ejemplo n.º 33
0
        private DnsMessageBase ProcessDnsQuery(DnsMessageBase message, IPAddress clientAddress, ProtocolType protocol)
        {
            state_.Logger.Debug("DNS query received");

            message.IsQuery = false;

            DnsMessage query = message as DnsMessage;
            if(query == null)
            {
                message.ReturnCode = ReturnCode.ServerFailure;
                return message;
            }

            foreach(DnsQuestion question in query.Questions)
            {
                state_.Logger.Debug("DNS question of type {0} received", question.RecordType);

                List<DnsRecordBase> records = ProcessQuestion(question);

                if(records == null)
                    records = ForwardQuery(question);

                if(records == null)
                {
                    message.ReturnCode = ReturnCode.ServerFailure;
                    return message;
                }
                else
                    query.AnswerRecords.AddRange(records);
            }

            return message;
        }
		public InvalidSignedMessageEventArgs(DnsMessageBase message)
		{
			Message = message;
		}
		internal QueryReceivedEventArgs(DnsMessageBase query, ProtocolType protocolType, IPEndPoint remoteEndpoint)
		{
			Query = query;
			ProtocolType = protocolType;
			RemoteEndpoint = remoteEndpoint;
		}
Ejemplo n.º 36
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <DomainName, ushort> domainNames, bool useCanonical)
 {
     DnsMessageBase.EncodeTextBlock(messageData, ref currentPosition, X25Address);
 }
Ejemplo n.º 37
0
        /// <summary>
        ///   Creates a new signing key pair
        /// </summary>
        /// <param name="name">The name of the key or zone</param>
        /// <param name="recordClass">The record class of the DnsKeyRecord</param>
        /// <param name="timeToLive">The TTL in seconds to the DnsKeyRecord</param>
        /// <param name="flags">The Flags of the DnsKeyRecord</param>
        /// <param name="protocol">The protocol version</param>
        /// <param name="algorithm">The key algorithm</param>
        /// <param name="keyStrength">The key strength or 0 for default strength</param>
        /// <returns></returns>
        public static DnsKeyRecord CreateSigningKey(DomainName name, RecordClass recordClass, int timeToLive, DnsKeyFlags flags, byte protocol, DnsSecAlgorithm algorithm, int keyStrength = 0)
        {
            byte[] privateKey;
            byte[] publicKey;

            switch (algorithm)
            {
            case DnsSecAlgorithm.RsaSha1:
            case DnsSecAlgorithm.RsaSha1Nsec3Sha1:
            case DnsSecAlgorithm.RsaSha256:
            case DnsSecAlgorithm.RsaSha512:
                if (keyStrength == 0)
                {
                    keyStrength = (flags == (DnsKeyFlags.Zone | DnsKeyFlags.SecureEntryPoint)) ? 2048 : 1024;
                }

                RsaKeyPairGenerator rsaKeyGen = new RsaKeyPairGenerator();
                rsaKeyGen.Init(new KeyGenerationParameters(_secureRandom, keyStrength));
                var rsaKey = rsaKeyGen.GenerateKeyPair();
                privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(rsaKey.Private).GetDerEncoded();
                var rsaPublicKey = (RsaKeyParameters)rsaKey.Public;
                var rsaExponent  = rsaPublicKey.Exponent.ToByteArrayUnsigned();
                var rsaModulus   = rsaPublicKey.Modulus.ToByteArrayUnsigned();

                int offset = 1;
                if (rsaExponent.Length > 255)
                {
                    publicKey = new byte[3 + rsaExponent.Length + rsaModulus.Length];
                    DnsMessageBase.EncodeUShort(publicKey, ref offset, (ushort)publicKey.Length);
                }
                else
                {
                    publicKey    = new byte[1 + rsaExponent.Length + rsaModulus.Length];
                    publicKey[0] = (byte)rsaExponent.Length;
                }
                DnsMessageBase.EncodeByteArray(publicKey, ref offset, rsaExponent);
                DnsMessageBase.EncodeByteArray(publicKey, ref offset, rsaModulus);
                break;

            case DnsSecAlgorithm.Dsa:
            case DnsSecAlgorithm.DsaNsec3Sha1:
                if (keyStrength == 0)
                {
                    keyStrength = 1024;
                }

                DsaParametersGenerator dsaParamsGen = new DsaParametersGenerator();
                dsaParamsGen.Init(keyStrength, 12, _secureRandom);
                DsaKeyPairGenerator dsaKeyGen = new DsaKeyPairGenerator();
                dsaKeyGen.Init(new DsaKeyGenerationParameters(_secureRandom, dsaParamsGen.GenerateParameters()));
                var dsaKey = dsaKeyGen.GenerateKeyPair();
                privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(dsaKey.Private).GetDerEncoded();
                var dsaPublicKey = (DsaPublicKeyParameters)dsaKey.Public;

                var dsaY = dsaPublicKey.Y.ToByteArrayUnsigned();
                var dsaP = dsaPublicKey.Parameters.P.ToByteArrayUnsigned();
                var dsaQ = dsaPublicKey.Parameters.Q.ToByteArrayUnsigned();
                var dsaG = dsaPublicKey.Parameters.G.ToByteArrayUnsigned();
                var dsaT = (byte)((dsaY.Length - 64) / 8);

                publicKey    = new byte[21 + 3 * dsaY.Length];
                publicKey[0] = dsaT;
                dsaQ.CopyTo(publicKey, 1);
                dsaP.CopyTo(publicKey, 21);
                dsaG.CopyTo(publicKey, 21 + dsaY.Length);
                dsaY.CopyTo(publicKey, 21 + 2 * dsaY.Length);
                break;

            case DnsSecAlgorithm.EccGost:
                ECDomainParameters gostEcDomainParameters = ECGost3410NamedCurves.GetByOid(CryptoProObjectIdentifiers.GostR3410x2001CryptoProA);

                var gostKeyGen = new ECKeyPairGenerator();
                gostKeyGen.Init(new ECKeyGenerationParameters(gostEcDomainParameters, _secureRandom));

                var gostKey = gostKeyGen.GenerateKeyPair();
                privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(gostKey.Private).GetDerEncoded();
                var gostPublicKey = (ECPublicKeyParameters)gostKey.Public;

                publicKey = new byte[64];

                gostPublicKey.Q.AffineXCoord.ToBigInteger().ToByteArrayUnsigned().CopyTo(publicKey, 32);
                gostPublicKey.Q.AffineYCoord.ToBigInteger().ToByteArrayUnsigned().CopyTo(publicKey, 0);

                publicKey = publicKey.Reverse().ToArray();
                break;

            case DnsSecAlgorithm.EcDsaP256Sha256:
            case DnsSecAlgorithm.EcDsaP384Sha384:
                int            ecDsaDigestSize;
                X9ECParameters ecDsaCurveParameter;

                if (algorithm == DnsSecAlgorithm.EcDsaP256Sha256)
                {
                    ecDsaDigestSize     = new Sha256Digest().GetDigestSize();
                    ecDsaCurveParameter = NistNamedCurves.GetByOid(SecObjectIdentifiers.SecP256r1);
                }
                else
                {
                    ecDsaDigestSize     = new Sha384Digest().GetDigestSize();
                    ecDsaCurveParameter = NistNamedCurves.GetByOid(SecObjectIdentifiers.SecP384r1);
                }

                ECDomainParameters ecDsaP384EcDomainParameters = new ECDomainParameters(
                    ecDsaCurveParameter.Curve,
                    ecDsaCurveParameter.G,
                    ecDsaCurveParameter.N,
                    ecDsaCurveParameter.H,
                    ecDsaCurveParameter.GetSeed());

                var ecDsaKeyGen = new ECKeyPairGenerator();
                ecDsaKeyGen.Init(new ECKeyGenerationParameters(ecDsaP384EcDomainParameters, _secureRandom));

                var ecDsaKey = ecDsaKeyGen.GenerateKeyPair();
                privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(ecDsaKey.Private).GetDerEncoded();
                var ecDsaPublicKey = (ECPublicKeyParameters)ecDsaKey.Public;

                publicKey = new byte[ecDsaDigestSize * 2];

                ecDsaPublicKey.Q.AffineXCoord.ToBigInteger().ToByteArrayUnsigned().CopyTo(publicKey, 0);
                ecDsaPublicKey.Q.AffineYCoord.ToBigInteger().ToByteArrayUnsigned().CopyTo(publicKey, ecDsaDigestSize);
                break;

            default:
                throw new NotSupportedException();
            }

            return(new DnsKeyRecord(name, recordClass, timeToLive, flags, protocol, algorithm, publicKey, privateKey));
        }
		internal InvalidSignedMessageEventArgs(DnsMessageBase query, ProtocolType protocolType, IPEndPoint remoteEndpoint)
		{
			Query = query;
			ProtocolType = protocolType;
			RemoteEndpoint = remoteEndpoint;
		}
Ejemplo n.º 39
0
 internal override void ParseRecordData(byte[] resultData, int startPosition, int length)
 {
     MailBox       = DnsMessageBase.ParseDomainName(resultData, ref startPosition);
     TxtDomainName = DnsMessageBase.ParseDomainName(resultData, ref startPosition);
 }
Ejemplo n.º 40
0
        static DnsMessageBase OnDnsQuery(DnsMessageBase message, System.Net.IPAddress clientAddress, ProtocolType protocol)
        {
            message.IsQuery = false;

            DnsMessage query = message as DnsMessage;
            DnsMessage answer = null;

            if ((query != null) && (query.Questions.Count == 1))
            {
                //log
                File.AppendAllLines("VenomDNS.log", new String[] { String.Format("DNS QUERY FROM {0} FOR {1}", clientAddress.ToString(), query.Questions[0].Name) });

                //HOOK:
                //resolve whatsapp.net subdomains
                if (query.Questions[0].RecordType == RecordType.A
                    &&
                    (
                        (query.Questions[0].Name == WA_CERT_HOST)
                        ||
                        (query.Questions[0].Name == WA_REG_HOST && frmMain.enableReg)
                        ||
                        (query.Questions[0].Name == WA_SYNC_HOST && frmMain.enableSync)
                        ||
                        (
                            //media files
                            query.Questions[0].Name.StartsWith("mms")
                            &&
                            query.Questions[0].Name.EndsWith("whatsapp.net")
                            &&
                            frmMain.enableMedia
                        )
                        ||
                        (
                            (
                                query.Questions[0].Name == WA_CHAT_HOST1
                                ||
                                query.Questions[0].Name == WA_CHAT_HOST2
                                ||
                                query.Questions[0].Name == WA_CHAT_HOST3
                            )
                            &&
                            frmMain.enableTCP
                        )
                    )
                    )
                {
                    query.ReturnCode = ReturnCode.NoError;
                    System.Net.IPAddress localIP = GetIP();
                    if (localIP != null)
                    {
                        query.AnswerRecords.Add(new ARecord(query.Questions[0].Name, 30, localIP));
                        return query;
                    }
                }
                // send query to upstream server
                try
                {
                    DnsQuestion question = query.Questions[0];
                    answer = DnsClient.Default.Resolve(question.Name, question.RecordType, question.RecordClass);

                    // if got an answer, copy it to the message sent to the client
                    if (answer != null)
                    {
                        foreach (DnsRecordBase record in (answer.AnswerRecords))
                        {
                            query.AnswerRecords.Add(record);
                        }
                        foreach (DnsRecordBase record in (answer.AdditionalRecords))
                        {
                            query.AnswerRecords.Add(record);
                        }

                        query.ReturnCode = ReturnCode.NoError;
                        return query;
                    }
                }
                catch (Exception e)
                { }
            }
            // Not a valid query or upstream server did not answer correct
            message.ReturnCode = ReturnCode.ServerFailure;
            return message;
        }
Ejemplo n.º 41
0
 protected internal override void EncodeRecordData(byte[] messageData, int offset, ref int currentPosition, Dictionary <DomainName, ushort> domainNames, bool useCanonical)
 {
     DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, MailBox, null, useCanonical);
     DnsMessageBase.EncodeDomainName(messageData, offset, ref currentPosition, TxtDomainName, null, useCanonical);
 }
Ejemplo n.º 42
0
		private DnsMessageBase ProcessMessage(DnsMessageBase query, IPAddress ipAddress, ProtocolType protocolType)
		{
			if (query.TSigOptions != null)
			{
				switch (query.TSigOptions.ValidationResult)
				{
					case ReturnCode.BadKey:
					case ReturnCode.BadSig:
						query.IsQuery = false;
						query.ReturnCode = ReturnCode.NotAuthoritive;
						query.TSigOptions.Error = query.TSigOptions.ValidationResult;
						query.TSigOptions.KeyData = null;

						if (InvalidSignedMessageReceived != null)
							InvalidSignedMessageReceived(this, new InvalidSignedMessageEventArgs(query));

						return query;

					case ReturnCode.BadTime:
						query.IsQuery = false;
						query.ReturnCode = ReturnCode.NotAuthoritive;
						query.TSigOptions.Error = query.TSigOptions.ValidationResult;
						query.TSigOptions.OtherData = new byte[6];
						int tmp = 0;
						TSigRecord.EncodeDateTime(query.TSigOptions.OtherData, ref tmp, DateTime.Now);

						if (InvalidSignedMessageReceived != null)
							InvalidSignedMessageReceived(this, new InvalidSignedMessageEventArgs(query));

						return query;
				}
			}

			return _processQueryDelegate(query, ipAddress, protocolType);
		}
Ejemplo n.º 43
0
        protected async Task <TMessage> SendMessageAsync <TMessage>(TMessage message, CancellationToken token)
            where TMessage : DnsMessageBase, new()
        {
            int messageLength;

            byte[] messageData;
            DnsServer.SelectTsigKey tsigKeySelector;
            byte[] tsigOriginalMac;

            PrepareMessage(message, out messageLength, out messageData, out tsigKeySelector, out tsigOriginalMac);

            bool sendByTcp = ((messageLength > MaximumQueryMessageSize) || message.IsTcpUsingRequested || !IsUdpEnabled);

            var endpointInfos = GetEndpointInfos();

            for (int i = 0; i < endpointInfos.Count; i++)
            {
                token.ThrowIfCancellationRequested();

                var           endpointInfo = endpointInfos[i];
                QueryResponse resultData   = null;

                try
                {
                    resultData = await(sendByTcp ? QueryByTcpAsync(endpointInfo.ServerAddress, messageData, messageLength, null, null, token) : QuerySingleResponseByUdpAsync(endpointInfo, messageData, messageLength, token));

                    if (resultData == null)
                    {
                        return(null);
                    }

                    TMessage result;

                    try
                    {
                        result = DnsMessageBase.Parse <TMessage>(resultData.Buffer, tsigKeySelector, tsigOriginalMac);
                    }
                    catch (Exception e)
                    {
                        Trace.TraceError("Error on dns query: " + e);
                        continue;
                    }

                    if (!ValidateResponse(message, result))
                    {
                        continue;
                    }

                    if ((result.ReturnCode != ReturnCode.NoError) && (result.ReturnCode != ReturnCode.NxDomain) && (i != endpointInfos.Count - 1))
                    {
                        continue;
                    }

                    if (result.IsTcpResendingRequested)
                    {
                        resultData = await QueryByTcpAsync(resultData.ResponderAddress, messageData, messageLength, resultData.TcpClient, resultData.TcpStream, token);

                        if (resultData != null)
                        {
                            TMessage tcpResult;

                            try
                            {
                                tcpResult = DnsMessageBase.Parse <TMessage>(resultData.Buffer, tsigKeySelector, tsigOriginalMac);
                            }
                            catch (Exception e)
                            {
                                Trace.TraceError("Error on dns query: " + e);
                                return(null);
                            }

                            if (tcpResult.ReturnCode == ReturnCode.ServerFailure)
                            {
                                return(result);
                            }
                            else
                            {
                                result = tcpResult;
                            }
                        }
                    }

                    bool isTcpNextMessageWaiting = result.IsTcpNextMessageWaiting(false);
                    bool isSucessfullFinished    = true;

                    while (isTcpNextMessageWaiting)
                    {
                        // ReSharper disable once PossibleNullReferenceException
                        resultData = await QueryByTcpAsync(resultData.ResponderAddress, null, 0, resultData.TcpClient, resultData.TcpStream, token);

                        if (resultData != null)
                        {
                            TMessage tcpResult;

                            try
                            {
                                tcpResult = DnsMessageBase.Parse <TMessage>(resultData.Buffer, tsigKeySelector, tsigOriginalMac);
                            }
                            catch (Exception e)
                            {
                                Trace.TraceError("Error on dns query: " + e);
                                isSucessfullFinished = false;
                                break;
                            }

                            if (tcpResult.ReturnCode == ReturnCode.ServerFailure)
                            {
                                isSucessfullFinished = false;
                                break;
                            }
                            else
                            {
                                result.AnswerRecords.AddRange(tcpResult.AnswerRecords);
                                isTcpNextMessageWaiting = tcpResult.IsTcpNextMessageWaiting(true);
                            }
                        }
                        else
                        {
                            isSucessfullFinished = false;
                            break;
                        }
                    }

                    if (isSucessfullFinished)
                    {
                        return(result);
                    }
                }
                finally
                {
                    if (resultData != null)
                    {
                        try
                        {
                            resultData.TcpStream?.Dispose();
                            resultData.TcpClient?.Close();
                        }
                        catch
                        {
                            // ignored
                        }
                    }
                }
            }

            return(null);
        }
		internal InvalidSignedMessageEventArgs(DnsMessageBase message)
		{
			Message = message;
		}
Ejemplo n.º 45
0
        protected TMessage SendMessage <TMessage>(TMessage message)
            where TMessage : DnsMessageBase, new()
        {
            int messageLength;

            byte[] messageData;
            DnsServer.SelectTsigKey tsigKeySelector;
            byte[] tsigOriginalMac;

            PrepareMessage(message, out messageLength, out messageData, out tsigKeySelector, out tsigOriginalMac);

            bool sendByTcp = ((messageLength > MaximumQueryMessageSize) || message.IsTcpUsingRequested || !IsUdpEnabled);

            var endpointInfos = GetEndpointInfos();

            for (int i = 0; i < endpointInfos.Count; i++)
            {
                TcpClient     tcpClient = null;
                NetworkStream tcpStream = null;

                try
                {
                    var endpointInfo = endpointInfos[i];

                    IPAddress responderAddress;
                    byte[]    resultData = sendByTcp ? QueryByTcp(endpointInfo.ServerAddress, messageData, messageLength, ref tcpClient, ref tcpStream, out responderAddress) : QueryByUdp(endpointInfo, messageData, messageLength, out responderAddress);

                    if (resultData != null)
                    {
                        TMessage result;

                        try
                        {
                            result = DnsMessageBase.Parse <TMessage>(resultData, tsigKeySelector, tsigOriginalMac);
                        }
                        catch (Exception e)
                        {
                            Trace.TraceError("Error on dns query: " + e);
                            continue;
                        }

                        if (!ValidateResponse(message, result))
                        {
                            continue;
                        }

                        if ((result.ReturnCode == ReturnCode.ServerFailure) && (i != endpointInfos.Count - 1))
                        {
                            continue;
                        }

                        if (result.IsTcpResendingRequested)
                        {
                            resultData = QueryByTcp(responderAddress, messageData, messageLength, ref tcpClient, ref tcpStream, out responderAddress);
                            if (resultData != null)
                            {
                                TMessage tcpResult;

                                try
                                {
                                    tcpResult = DnsMessageBase.Parse <TMessage>(resultData, tsigKeySelector, tsigOriginalMac);
                                }
                                catch (Exception e)
                                {
                                    Trace.TraceError("Error on dns query: " + e);
                                    continue;
                                }

                                if (tcpResult.ReturnCode == ReturnCode.ServerFailure)
                                {
                                    if (i != endpointInfos.Count - 1)
                                    {
                                        continue;
                                    }
                                }
                                else
                                {
                                    result = tcpResult;
                                }
                            }
                        }

                        bool isTcpNextMessageWaiting = result.IsTcpNextMessageWaiting(false);
                        bool isSucessfullFinished    = true;

                        while (isTcpNextMessageWaiting)
                        {
                            resultData = QueryByTcp(responderAddress, null, 0, ref tcpClient, ref tcpStream, out responderAddress);
                            if (resultData != null)
                            {
                                TMessage tcpResult;

                                try
                                {
                                    tcpResult = DnsMessageBase.Parse <TMessage>(resultData, tsigKeySelector, tsigOriginalMac);
                                }
                                catch (Exception e)
                                {
                                    Trace.TraceError("Error on dns query: " + e);
                                    isSucessfullFinished = false;
                                    break;
                                }

                                if (tcpResult.ReturnCode == ReturnCode.ServerFailure)
                                {
                                    isSucessfullFinished = false;
                                    break;
                                }
                                else
                                {
                                    result.AnswerRecords.AddRange(tcpResult.AnswerRecords);
                                    isTcpNextMessageWaiting = tcpResult.IsTcpNextMessageWaiting(true);
                                }
                            }
                            else
                            {
                                isSucessfullFinished = false;
                                break;
                            }
                        }

                        if (isSucessfullFinished)
                        {
                            return(result);
                        }
                    }
                }
                finally
                {
                    try
                    {
                        tcpStream?.Dispose();
                        tcpClient?.Close();
                    }
                    catch
                    {
                        // ignored
                    }
                }
            }

            return(null);
        }