Beispiel #1
0
        private static Func <UdpReceiveResult, Task <byte[]> > CreateAsyncCallback(DnsServer server)
        {
            return(async result =>
            {
                var answer = await server.HandleQuery(result.Buffer);

                return DnsPacketParser.CreatePacket(answer);
            });
        }
Beispiel #2
0
        public async Task <DnsPacket> HandleQuery(byte[] buffer)
        {
            await AnswersCache.CleanExpiredAnswers();

            var parsedPacket = DnsPacketParser.ParsePacket(buffer);
            var queries      = parsedPacket.Queries;
            var answers      = await Task.WhenAll(queries.AsParallel()
                                                  .Select(async query =>
            {
                Logger.Info("Handling query {0} {1} {2}", query.Name, query.AnswerType, query.Class);
                DnsPacket resultAnswer;
                var answerInCache = AnswersCache.TryGetAnswer(query.Name, query.AnswerType, out var dnsAnswers);
                if (!answerInCache)
                {
                    try
                    {
                        resultAnswer = await ResolveQuery(buffer);
                    }
                    catch (TimeoutException e)
                    {
                        Logger.Error(e, "Query time out: {0} {1}", query.Name, query.AnswerType);
                        return(DnsPacketParser.CreateSimpleErrorPacket(query, parsedPacket.QueryId, 2));
                    }
                    Logger.Info("Query {0} {1}, TTL:{2}", query.Name, query.AnswerType,
                                resultAnswer.Answers.Any() ? resultAnswer.Answers.Min(a => a.TTL) : 0);
                    if (resultAnswer.Flags.ReplyCode != 0)
                    {
                        return(DnsPacketParser.CreateSimpleErrorPacket(query, parsedPacket.QueryId, 5));
                    }

                    PutAsnwersInCache(resultAnswer);
                }
                else
                {
                    Logger.Info("Query <{0} {1} {2}> found in cache!", query.Name, query.Class, query.AnswerType);
                    parsedPacket.Answers.AddRange(dnsAnswers);
                    resultAnswer = parsedPacket;
                    resultAnswer.Flags.Response           = true;
                    resultAnswer.Flags.RecursionAvailable = true;
                }
                return(resultAnswer);
            }));

            return(answers[0]);
        }
Beispiel #3
0
        private async Task <DnsPacket> ResolveQuery(byte[] packet)
        {
            Logger.Info("Handling query");
            using (var udpClient = new UdpClient())
            {
                var sendTask = udpClient.SendAsync(packet, packet.Length, remoteEndPoint);
                var sendRes  = await Task.WhenAny(sendTask, Task.Delay(1500));

                if (sendRes == sendTask)
                {
                    await sendTask;
                }
                Logger.Info("sent to server");
                var receiveTask = udpClient.ReceiveAsync();
                var res         = await Task.WhenAny(receiveTask, Task.Delay(1500));

                UdpReceiveResult result;
                if (res == receiveTask)
                {
                    result = await receiveTask;
                }
                else
                {
                    throw new TimeoutException("Query timed out");
                }
                Logger.Info("received from server");
                if (!Equals(result.RemoteEndPoint, remoteEndPoint))
                {
                    throw new ArgumentException();
                }
                var parsedAnswer = DnsPacketParser.ParsePacket(result.Buffer);
                Logger.Info("Received answer for <{0} {1} {2}>", parsedAnswer.Queries[0].Name,
                            parsedAnswer.Queries[0].AnswerType, parsedAnswer.Queries[0].Class);
                return(parsedAnswer);
            }
        }