Esempio n. 1
0
 private Task <DnsResponse> StartResolve(DnsRequestType type, string strName, out bool newTask)
 {
     if (dnsProvider == null)
     {
         throw new Exception("no dns resolver");
     }
     lock (resolvingNames) {
         newTask = false;
         if (resolvingNames.TryGetValue(strName, out var rt))
         {
             // try to return a running task
             if (type == DnsRequestType.A && rt.A != null)
             {
                 return(rt.A);
             }
             if (type == DnsRequestType.AAAA || rt.AAAA != null)
             {
                 return(rt.AAAA);
             }
             if (type == DnsRequestType.AnAAAA)
             {
                 if (rt.A == rt.AAAA)
                 {
                     return(rt.A);
                 }
                 if (rt.A != null && rt.AAAA != null)
                 {
                     return(UnionWarpper(rt));
                 }
             }
         }
         else
         {
             rt = new ResolveTask();
             resolvingNames[strName] = rt;
         }
         var task = Controller.ResolveName(this, AdapterRef.FromAdapter(dnsProvider), new DnsRequest(strName, type));
         if ((type & DnsRequestType.A) != 0 && rt.A == null)
         {
             rt.A = task;
         }
         if ((type & DnsRequestType.AAAA) != 0 && rt.AAAA == null)
         {
             rt.AAAA = task;
         }
         newTask = true;
         return(task);
     }
 }
Esempio n. 2
0
        private async Task <IResponse> HandleDnsRequest(IRequest request)
        {
            var q = request;
            var r = Response.FromRequest(request);

            r.ResponseCode = ResponseCode.ServerFailure;
            try {
                var questions = q.Questions;
                if (questions.Count == 0)
                {
                    Logger.warning($"id {q.Id} does not contain any questions." +
                                   $"\nAdditionalRecords: {string.Join(", ", q.AdditionalRecords)}");
                }

                //
                var queryNames = new Dictionary <Domain, DnsRequestType>();
                foreach (var item in questions)
                {
                    if (item.Type == RecordType.A || item.Type == RecordType.AAAA)
                    {
                        DnsRequestType type = item.Type == RecordType.A ? DnsRequestType.A : DnsRequestType.AAAA;
                        if (verbose)
                        {
                            Logger.debugForce($"id {q.Id} query: {item}");
                        }
                        if (!queryNames.ContainsKey(item.Name))
                        {
                            queryNames.Add(item.Name, type);
                        }
                        else
                        {
                            queryNames[item.Name] |= type;
                        }
                    }
                    else if (item.Type == RecordType.PTR)
                    {
                    }
                    else
                    {
                        Logger.warning("Unsupported DNS record: " + item);
                    }
                }

                foreach (var kv in queryNames)
                {
                    DnsRequestType          reqType = kv.Value;
                    bool                    reqv4   = (reqType & DnsRequestType.A) != 0;
                    bool                    reqv6   = (reqType & DnsRequestType.AAAA) != 0;
                    var                     strName = kv.Key.ToString();
                    IEnumerable <IPAddress> ips     = emptyIps;
                    IpRecord                val     = new IpRecord();
                    bool                    exist   = cacheDns?.QueryByName(strName, out val) ?? false;
                    var                     now     = DateTime.Now;
                    if (val.expire < now)
                    {
                        val.ipLongs = null;
                    }
                    if (val.expire6 < now)
                    {
                        val.ips6 = null;
                    }
                    var ipLongs = val.ipLongs;
                    var ips6    = val.ips6;
                    if (!exist || (reqv4 && ipLongs == null) || (reqv6 && ips6 == null))
                    {
                        var startTime = Logging.getRuntime();
                        var task      = StartResolve(reqType, strName, out var newTask);
                        try {
                            try {
                                var resp = await task;
                                if (resp != null)
                                {
                                    var iparr = resp.Addresses;
                                    ips = iparr;
                                    ipFilter(iparr, ref ipLongs, ref ips6);
                                }
                            } catch (Exception e) {
                                if (newTask)
                                {
                                    Logger.warning("resolving: " + strName + " (" + reqType + "): " + e.Message + " (" + (Logging.getRuntime() - startTime) + " ms)");
                                }
                                continue;
                            }

                            if (newTask)
                            {
                                Logger.info("" + strName + " (" + reqType + ") -> " + string.Join("|", ips)
                                            + " (" + (Logging.getRuntime() - startTime) + " ms)");
                                var newExpire = DateTime.Now.AddSeconds(cache_ttl);
                                // If we requested only A records (not AnAAAA) and an empty result returned, then there's
                                // really no A records, so we can cache the empty result:
                                if (reqType == DnsRequestType.A && ipLongs == null)
                                {
                                    ipLongs = new uint[0];
                                }
                                if (ipLongs != null)
                                {
                                    val.ipLongs = ipLongs;
                                    val.expire  = newExpire;
                                }
                                // The same reason:
                                if (reqType == DnsRequestType.AAAA && ips6 == null)
                                {
                                    ips6 = new Ip6[0];
                                }
                                if (ips6 != null)
                                {
                                    val.ips6    = ips6;
                                    val.expire6 = newExpire;
                                }
                                cacheDns?.Set(strName, ref val);
                            }
                        } finally {
                            if (newTask)
                            {
                                EndResolve(strName, task);
                            }
                        }
                    }

                    if (reqv4 && ipLongs != null)
                    {
                        foreach (var item in ipLongs)
                        {
                            r.AnswerRecords.Add(new ResourceRecord(kv.Key, BitConverter.GetBytes(item), RecordType.A, ttl: TimeSpan.FromSeconds(ttl)));
                        }
                    }
                    if (reqv6 && ips6 != null)
                    {
                        foreach (var item in ips6)
                        {
                            r.AnswerRecords.Add(new ResourceRecord(kv.Key, item.ToBytes(), RecordType.AAAA, ttl: TimeSpan.FromSeconds(ttl)));
                        }
                    }
                    r.ResponseCode = ResponseCode.NoError;
                }
            } catch (Exception e) {
                Logger.exception(e, Logging.Level.Error, "server");
            }
            return(r);
        }
Esempio n. 3
0
 public DnsRequest(string name, DnsRequestType type)
 {
     Name = name;
     Type = type;
 }