Beispiel #1
0
        public void Set(string domain, ref IpRecord val)
        {
            if (domain == null)
            {
                throw new ArgumentNullException(nameof(domain));
            }

            mapLock.EnterWriteLock();
            if (mapHostIp.TryGetValue(domain, out var old))
            {
                if (val.ipLongs != null)
                {
                    old.ipLongs = val.ipLongs;
                    old.expire  = val.expire;
                }
                if (val.ips6 != null)
                {
                    old.ips6    = val.ips6;
                    old.expire6 = val.expire6;
                }
                mapHostIp[domain] = old;
            }
            else
            {
                mapHostIp[domain] = val;
            }
            mapLock.ExitWriteLock();

            SetReverseMap(ref val, domain);
        }
Beispiel #2
0
        public bool QueryByName(string name, out IpRecord val)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            mapLock.EnterReadLock();
            try {
                return(mapHostIp.TryGetValue(name, out val));
            } finally {
                mapLock.ExitReadLock();
            }
        }
Beispiel #3
0
        public bool QueryByName(string domain, out IpRecord val)
        {
            Interlocked.Increment(ref queryByDomains);
            var begin = Logging.getRuntime();

            try {
                var doc = FindDocByDomain(domain).SingleOrDefault();
                if (doc != null)
                {
                    var r = Record.FromDocument(doc);
                    val         = new IpRecord();
                    val.ipLongs = r.Ips;
                    val.ips6    = r.Ips6;
                    val.expire  = r.Expire;
                    val.expire6 = r.Expire6;
                    return(true);
                }
                val = default(IpRecord);
                return(false);
            } finally {
                Interlocked.Add(ref queryByDomainTotalTime, (int)(Logging.getRuntime() - begin));
            }
        }
Beispiel #4
0
        void SetReverseMap(ref IpRecord r, string domain)
        {
            if (domain == null)
            {
                throw new ArgumentNullException(nameof(domain));
            }

            mapLock2.EnterWriteLock();
            if (r.ipLongs != null)
            {
                foreach (var item in r.ipLongs)
                {
                    mapIpHost[item] = domain;
                }
            }
            if (r.ips6 != null)
            {
                foreach (var item in r.ips6)
                {
                    mapIp6Host[item] = domain;
                }
            }
            mapLock2.ExitWriteLock();
        }
Beispiel #5
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);
        }
Beispiel #6
0
        public void Set(string domain, ref IpRecord val)
        {
            lock (syncRoot) {
                var begin = Logging.getRuntime();
                inserts++;
                var    doc = FindDocByDomain(domain).SingleOrDefault();
                Record r   = null;
                if (doc != null)
                {
                    r = Record.FromDocument(doc);
                }
                else
                {
                    r = new Record()
                    {
                        Domain = domain
                    }
                };

                // update IPv4/v6 records separately
                if (val.ipLongs != null)
                {
                    if (r.Ips != null && r.Ips.Length > 0)
                    {
                        if (r.OldIps != null)
                        {
                            r.OldIps = r.OldIps.Union(r.Ips).Except(val.ipLongs).ToArray();
                        }
                        else
                        {
                            r.OldIps = r.Ips.Except(val.ipLongs).ToArray();
                            if (r.OldIps.Length == 0)
                            {
                                r.OldIps = null;
                            }
                        }
                    }
                    r.Ips    = val.ipLongs;
                    r.Date   = DateTime.Now;
                    r.Expire = val.expire;
                }
                if (val.ips6 != null)
                {
                    if (r.Ips6 != null && r.Ips6.Length > 0)
                    {
                        var ec = Ip6.EqualityComparer;
                        if (r.OldIps6 != null)
                        {
                            r.OldIps6 = r.OldIps6.Union(r.Ips6, ec).Except(val.ips6, ec).ToArray();
                        }
                        else
                        {
                            r.OldIps6 = r.Ips6.Except(val.ips6, ec).ToArray();
                            if (r.OldIps6.Length == 0)
                            {
                                r.OldIps6 = null;
                            }
                        }
                    }
                    r.Ips6    = val.ips6;
                    r.Date6   = DateTime.Now;
                    r.Expire6 = val.expire6;
                }

                engine.Upsert(ColRecords, r.ToDocument(), BsonType.Int32);
                insertTotalTime += (int)(Logging.getRuntime() - begin);
            }
        }