Пример #1
0
        static void Main(string[] args)
        {
            // Start P2P thread
            Thread p2pListener = new Thread(new ThreadStart(P2P.Run));

            p2pListener.Start();

            // Open UDP socket
            UdpClient  listener = new UdpClient(listenPort);
            IPEndPoint groupEP;

            // Receive a packet
            try
            {
                byte[] recv_buf;
                while (true)
                {
                    // Set listen address
                    groupEP = new IPEndPoint(IPAddress.Any, listenPort);

                    // Receive data, client will be placed in groupEP
                    recv_buf = listener.Receive(ref groupEP);

                    // Parse DNS data
                    MemoryStream ms = new MemoryStream(recv_buf);
                    BinaryReader br = new BinaryReader(ms);

                    DNS_header header = new DNS_header();
                    header.Read(br);

                    if (header.QDcount != 1)
                    {
                        Console.WriteLine("Cannot parse DNS request where QDcount != 1");
                        continue;
                    }

                    DNS_question question = new DNS_question();
                    question.Read(br);

                    // Get the answer to the query
                    byte[] ans_ip = new byte[4];
                    DNScache.resolve(question.name, ref ans_ip);

                    // Send a response
                    MemoryStream ms_out = new MemoryStream();
                    BinaryWriter bw     = new BinaryWriter(ms_out);

                    // Modify DNS header
                    header.qr      = true;
                    header.rcode   = 0;
                    header.ANcount = 1;

                    // Write DNS header
                    header.Write(bw);

                    // Write question
                    question.Write(bw);

                    // Generate answer
                    DNS_answer answer = new DNS_answer();
                    answer.name   = question.name;
                    answer.atype  = 1;
                    answer.aclass = 1;
                    answer.ttl    = 60;
                    answer.rdlen  = 4;
                    answer.rdata  = ans_ip;

                    // Write answer
                    answer.Write(bw);

                    // Send the packet
                    byte[] buf_out = ms_out.ToArray();
                    listener.Send(buf_out, buf_out.Length, groupEP);
                }
            } catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                Console.ReadLine();
            }

            p2pListener.Interrupt();
        }
Пример #2
0
        public static bool resolve(string name, ref byte[] result)
        {
            // If the cache contains the result, return it
            lock (_lock_cache)
            {
                if (_cache.ContainsKey(name))
                {
                    cache_entry ce = _cache[name];
                    if (ce.expiry < DateTime.Now)
                    {
                        _cache.Remove(name);
                    }
                    else
                    {
                        if (ce.success)
                        {
                            Array.Copy(ce.address, result, 4);
                        }
#if DEBUG
                        Console.WriteLine("Resolved through local cache!");
#endif
                        log.Info("cache");
                        return(ce.success);
                    }
                }
            }

            // Query P2P before delegating to real DNS server
            if (P2P.resolve(name, ref result))
            {
#if DEBUG
                Console.WriteLine("Resolved through P2P!");
#endif
                log.Info("p2p");
                return(true);
            }

            // Otherwise, we must query a real DNS server
            // TODO: Change from hardcoded DNS server to configurable server
            DNS_header req = new DNS_header();
            req.ID      = 1337;
            req.qr      = false;
            req.opcode  = 0;
            req.tc      = false;
            req.rd      = true;
            req.QDcount = 1;
            req.ANcount = 0;
            req.NScount = 0;
            req.ARcount = 0;

            DNS_question req_q = new DNS_question();
            req_q.name   = name;
            req_q.qclass = 1;
            req_q.qtype  = 1;

            // Set up the packet
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            req.Write(bw);
            req_q.Write(bw);

            // Send the packet
            byte[]    req_buf = ms.ToArray();
            UdpClient client  = new UdpClient();
            client.Connect(IPAddress.Parse("8.8.8.8"), 53);
            client.Send(req_buf, req_buf.Length);

            // Receive a packet
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("8.8.8.8"), 53);
            client.Client.ReceiveTimeout = 1000;
            byte[] res_buf;
            try
            {
                res_buf = client.Receive(ref ipep);
            } catch (SocketException ex)
            {
                return(false);
            }
            MemoryStream res_ms = new MemoryStream(res_buf);
            BinaryReader res_br = new BinaryReader(res_ms);
            DNS_header   res_h  = new DNS_header();
            res_h.Read(res_br);

            if (!res_h.qr)
            {
                Console.WriteLine("Received packet was a query!");
                return(false);
            }

            if (res_h.rcode != 0)
            {
                lock (_lock_cache)
                {
                    cache_entry ce = new cache_entry();
                    ce.success = false;
                    ce.expiry  = DateTime.Now.AddMinutes(15);
                    _cache.Add(name, ce);
                }
                return(false);
            }

            DNS_question[] res_qs = new DNS_question[res_h.QDcount];
            DNS_answer[]   res_as = new DNS_answer[res_h.ANcount];

#if DEBUG
            Console.WriteLine("Questions: {0}\nAnswers: {1}", res_h.QDcount, res_h.ANcount);
#endif

            for (int i = 0; i < res_h.QDcount; i++)
            {
                res_qs[i] = new DNS_question();
                res_qs[i].Read(res_br);

#if DEBUG
                Console.WriteLine("Question {0}: {1}\n", i, res_qs[i].name);
#endif
            }

            byte[] address = new byte[4];
            uint   ttl     = 0;
            bool   answer  = false;
            for (int i = 0; i < res_h.ANcount; i++)
            {
                res_as[i] = new DNS_answer();
                res_as[i].Read(res_br);

#if DEBUG
                Console.WriteLine("Answer {0}: {1}\n", i, res_as[i].name);
#endif
                if (res_as[i].atype == 1)
                {
#if DEBUG
                    Console.WriteLine("{0}.{1}.{2}.{3} TTL: {4}", res_as[i].rdata[0], res_as[i].rdata[1], res_as[i].rdata[2], res_as[i].rdata[3], res_as[i].ttl);
#endif
                    for (int j = 0; j < 4; j++)
                    {
                        address[j] = res_as[i].rdata[j];
                        ttl        = res_as[i].ttl;
                        answer     = true;
                    }
                }
            }

            if (answer)
            {
                lock (_lock_cache)
                {
                    cache_entry ce = new cache_entry();
                    ce.success = true;
                    ce.address = address;
                    ce.expiry  = DateTime.Now.AddSeconds(ttl);
                    _cache.Add(name, ce);
                }

                for (int i = 0; i < 4; i++)
                {
                    result[i] = address[i];
                }

#if DEBUG
                Console.WriteLine("Resolved through DNS!");
#endif
                log.Info("dns");
                return(true);
            }

            return(false);
        }