Пример #1
0
    def handleQuery(self, msg, addr, port):
        """Deal with incoming query packets.  Provides a response if
        possible."""
        out = None

        # Support unicast client responses
        #
        if port != dns._MDNS_PORT:
            out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA, 0)
            for question in msg.questions:
                out.addQuestion(question)
        log.debug( 'Questions...')
        for question in msg.questions:
            log.debug( 'Question: %s', question )
            if question.type == dns._TYPE_PTR:
                for service in list(self.services.values()):
                    if question.name == service.type:
                        log.info( 'Service query found %s', service.name )
                        if out is None:
                            out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)
                        out.addAnswer(msg, dns.DNSPointer(service.type, dns._TYPE_PTR, dns._CLASS_IN, dns._DNS_TTL, service.name))
                        # devices such as AAstra phones will not re-query to
                        # resolve the pointer, they expect the final IP to show up
                        # in the response
                        out.addAdditionalAnswer(dns.DNSText(service.name, dns._TYPE_TXT, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.text))
                        out.addAdditionalAnswer(dns.DNSService(service.name, dns._TYPE_SRV, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.priority, service.weight, service.port, service.server))
                        out.addAdditionalAnswer(dns.DNSAddress(service.server, dns._TYPE_A, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.address))
            else:
                try:
                    if out is None:
                        out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)

                    # Answer A record queries for any service addresses we know
                    if question.type == dns._TYPE_A or question.type == dns._TYPE_ANY:
                        for service in list(self.services.values()):
                            if service.server == question.name.lower():
                                out.addAnswer(msg, DNSAddress(question.name, dns._TYPE_A, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.address))


                    service = self.services.get(question.name.lower(), None)
                    if not service: continue

                    if question.type == dns._TYPE_SRV or question.type == dns._TYPE_ANY:
                        out.addAnswer(msg, dns.DNSService(question.name, dns._TYPE_SRV, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.priority, service.weight, service.port, service.server))
                    if question.type == dns._TYPE_TXT or question.type == dns._TYPE_ANY:
                        out.addAnswer(msg, dns.DNSText(question.name, dns._TYPE_TXT, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.text))
                    if question.type == dns._TYPE_SRV:
                        out.addAdditionalAnswer(dns.DNSAddress(service.server, dns._TYPE_A, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.address))
                except Exception as err:
                    log.error(
                        'Error handling query: %s',traceback.format_exc()
                    )

        if out is not None and out.answers:
            out.id = msg.id
            self.send(out, addr, port)
        else:
            log.debug( 'No answer for %s', [q for q in msg.questions] )
Пример #2
0
 def testResponseHeaderBits(self):
     generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
     bytes = generated.packet()
     print("bytes", bytes.encode())
     flags = ord(bytes[2].encode()) << 8 | ord(bytes[3].encode())
     print("flags ", flags)
     self.assertEqual(flags, 0x8000)
Пример #3
0
 def unregisterService(self, info):
     """Unregister a service."""
     try:
         del (self.services[info.name.lower()])
     except:
         pass
     now = dns.currentTimeMillis()
     nextTime = now
     i = 0
     while i < 3:
         if now < nextTime:
             self.wait(nextTime - now)
             now = dns.currentTimeMillis()
             continue
         out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)
         out.addAnswerAtTime(
             dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN, 0,
                            info.name), 0)
         out.addAnswerAtTime(
             dns.DNSService(info.name, dns._TYPE_SRV, dns._CLASS_IN, 0,
                            info.priority, info.weight, info.port,
                            info.name), 0)
         out.addAnswerAtTime(
             dns.DNSText(info.name, dns._TYPE_TXT, dns._CLASS_IN, 0,
                         info.text), 0)
         if info.address:
             out.addAnswerAtTime(
                 dns.DNSAddress(info.server, dns._TYPE_A, dns._CLASS_IN, 0,
                                info.address), 0)
         self.send(out)
         i += 1
         nextTime += _UNREGISTER_TIME
Пример #4
0
 def test_response_header_bits(self):
     generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
     b = generated.packet()
     print("bytes", b)
     #flags = ord(b[2]) << 8 | ord(b[3])
     flags = b[2] << 8 | b[3]
     self.assertEqual(flags, 0x8000)
Пример #5
0
    def registerService(self, info, ttl=dns._DNS_TTL):
        """Registers service information to the network with a default TTL
        of 60 seconds.  Zeroconf will then respond to requests for
        information for that service.  The name of the service may be
        changed if needed to make it unique on the network."""
        #print "REGISTERING SERVICE!"
        #log.debug(">>",self.services[info.name.lower()])
    
        #import pdb
        #pdb.set_trace()
        
        self.checkService(info)
        self.services[info.name.lower()] = info
        log.debug(">>",self.services[info.name.lower()])
        
        now = dns.currentTimeMillis()
        nextTime = now
        i = 0
        while i < 3:
            if now < nextTime:
                self.wait(nextTime - now)
                now = dns.currentTimeMillis()
                continue

            out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)
            out.addAnswerAtTime(dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN, ttl, info.name), 0)
            out.addAnswerAtTime(dns.DNSService(info.name, dns._TYPE_SRV, dns._CLASS_IN, ttl, info.priority, info.weight, info.port, info.server), 0)
            out.addAnswerAtTime(dns.DNSText(info.name, dns._TYPE_TXT, dns._CLASS_IN, ttl, info.text), 0)
            if info.address:
                out.addAnswerAtTime(dns.DNSAddress(info.server, dns._TYPE_A, dns._CLASS_IN, ttl, info.address), 0)
            self.send(out)
            i += 1
            nextTime += _REGISTER_TIME
            print("registerService end")
Пример #6
0
    def run(self):
        while 1:
            event = None
            now = dns.currentTimeMillis()
            if len(self.list) == 0 and self.nextTime > now:
                self.zeroconf.wait(self.nextTime - now)
            if globals()['_GLOBAL_DONE'] or self.done:
                return
            now = dns.currentTimeMillis()

            if self.nextTime <= now:
                out = dns.DNSOutgoing(dns._FLAGS_QR_QUERY)
                out.addQuestion(dns.DNSQuestion(self.type, dns._TYPE_PTR, dns._CLASS_IN))
                for record in list(self.services.values()):
                    if not record.isExpired(now):
                        out.addAnswerAtTime(record, now)
                self.zeroconf.send(out)
                self.nextTime = now + self.delay
                self.delay = min(20 * 1000, self.delay * 2)

            if len(self.list) > 0:
                event = self.list.pop(0)

            if event is not None:
                event(self.zeroconf)
Пример #7
0
 def checkService(self, info):
     """Checks the network for a unique service name, modifying the
     ServiceInfo passed in if it is not unique."""
     now = dns.currentTimeMillis()
     nextTime = now
     i = 0
     while i < 3:
         for record in self.cache.entriesWithName(info.type):
             if record.type == dns._TYPE_PTR and not record.isExpired(now) and record.alias == info.name:
                 if (info.name.find('.') < 0):
                     info.name = info.name + ".[" + info.address + ":" + info.port + "]." + info.type
                     self.checkService(info)
                     return
                 raise NonUniqueNameException
         if now < nextTime:
             self.wait(nextTime - now)
             now = dns.currentTimeMillis()
             continue
         out = dns.DNSOutgoing(dns._FLAGS_QR_QUERY | dns._FLAGS_AA)
         self.debug = out
         out.addQuestion(dns.DNSQuestion(info.type, dns._TYPE_PTR, dns._CLASS_IN))
         out.addAuthorativeAnswer(dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN, dns._DNS_TTL, info.name))
         self.send(out)
         i += 1
         nextTime += _CHECK_TIME
Пример #8
0
	def testSameName(self):
		name = "paired.local."
		generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
		question = r.DNSQuestion(name, r._TYPE_SRV, r._CLASS_IN)
		generated.addQuestion(question)
		generated.addQuestion(question)
		parsed = r.DNSIncoming(generated.packet())
Пример #9
0
 def testLongName(self):
     generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
     question = r.DNSQuestion(
         "this.is.a.very.long.name.with.lots.of.parts.in.it.local.",
         r._TYPE_SRV, r._CLASS_IN)
     generated.addQuestion(question)
     parsed = r.DNSIncoming(generated.packet())
Пример #10
0
 def unregisterAllServices(self):
     """Unregister all registered services."""
     if len(self.services) > 0:
         now = dns.currentTimeMillis()
         nextTime = now
         i = 0
         while i < 3:
             if now < nextTime:
                 self.wait(nextTime - now)
                 now = dns.currentTimeMillis()
                 continue
             out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)
             for info in self.services.values():
                 out.addAnswerAtTime(
                     dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN,
                                    0, info.name), 0)
                 out.addAnswerAtTime(
                     dns.DNSService(info.name, dns._TYPE_SRV, dns._CLASS_IN,
                                    0, info.priority, info.weight,
                                    info.port, info.server), 0)
                 out.addAnswerAtTime(
                     dns.DNSText(info.name, dns._TYPE_TXT, dns._CLASS_IN, 0,
                                 info.text), 0)
                 if info.address:
                     out.addAnswerAtTime(
                         dns.DNSAddress(info.server, dns._TYPE_A,
                                        dns._CLASS_IN, 0, info.address), 0)
             self.send(out)
             i += 1
             nextTime += _UNREGISTER_TIME
Пример #11
0
	def testMatchQuestion(self):
		generated = r.DNSOutgoing(r._FLAGS_QR_QUERY)
		question = r.DNSQuestion("testname.local.", r._TYPE_SRV, r._CLASS_IN)
		generated.addQuestion(question)
		parsed = r.DNSIncoming(generated.packet())
		self.assertEqual(len(generated.questions), 1)
		self.assertEqual(len(generated.questions), len(parsed.questions))
		self.assertEqual(question, parsed.questions[0])
Пример #12
0
 def serviceAnnouncement( cls, info, ttl=dns._DNS_TTL ):
     out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)
     out.addAnswerAtTime(dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN, ttl, info.name), 0)
     out.addAnswerAtTime(dns.DNSService(info.name, dns._TYPE_SRV, dns._CLASS_IN, ttl, info.priority, info.weight, info.port, info.server), 0)
     out.addAnswerAtTime(dns.DNSText(info.name, dns._TYPE_TXT, dns._CLASS_IN, ttl, info.text), 0)
     if info.address:
         out.addAnswerAtTime(dns.DNSAddress(info.server, dns._TYPE_A, dns._CLASS_IN, ttl, info.address), 0)
     return out
Пример #13
0
    def handleQuery(self, msg, addr, port):
        """Deal with incoming query packets.  Provides a response if
        possible."""
        out = None

        # Support unicast client responses
        #
        if port != dns._MDNS_PORT:
            out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA, 0)
            for question in msg.questions:
                out.addQuestion(question)
        log.debug('Questions...')
        for question in msg.questions:
            log.debug('Question: %s', question)
            if out is None:
                out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)
            try:
                self.responses(question, msg, out)
            except Exception, err:
                log.error('Error handling query: %s', traceback.format_exc())
Пример #14
0
	def testNumbers(self):
		generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
		bytes = generated.packet()
		numQuestions = ord(bytes[4]) << 8 | ord(bytes[5])
		numAnswers = ord(bytes[6]) << 8 | ord(bytes[7])
		numAuthorities = ord(bytes[8]) << 8 | ord(bytes[9])
		numAddtionals = ord(bytes[10]) << 8 | ord(bytes[11])
		self.assertEqual(numQuestions, 0)
		self.assertEqual(numAnswers, 0)
		self.assertEqual(numAuthorities, 0)
		self.assertEqual(numAddtionals, 0)
Пример #15
0
	def testNumbersQuestions(self):
		generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
		question = r.DNSQuestion("testname.local.", r._TYPE_SRV, r._CLASS_IN)
		for i in range(0, 10):
			generated.addQuestion(question)
		bytes = generated.packet()
		numQuestions = ord(bytes[4]) << 8 | ord(bytes[5])
		numAnswers = ord(bytes[6]) << 8 | ord(bytes[7])
		numAuthorities = ord(bytes[8]) << 8 | ord(bytes[9])
		numAddtionals = ord(bytes[10]) << 8 | ord(bytes[11])
		self.assertEqual(numQuestions, 10)
		self.assertEqual(numAnswers, 0)
		self.assertEqual(numAuthorities, 0)
		self.assertEqual(numAddtionals, 0)
Пример #16
0
	def testExceedinglyLongName(self):
		generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
		name = "%slocal." % ("part." * 1000)
		question = r.DNSQuestion(name, r._TYPE_SRV, r._CLASS_IN)
		generated.addQuestion(question)
		parsed = r.DNSIncoming(generated.packet())
Пример #17
0
	def testParseOwnPacketSimpleUnicast(self):
		generated = r.DNSOutgoing(0, 0)
		parsed = r.DNSIncoming(generated.packet())
Пример #18
0
	def testTransactionID(self):
		"""ID must be zero in a DNS-SD packet"""
		generated = r.DNSOutgoing(r._FLAGS_QR_QUERY)
		bytes = generated.packet()
		id = ord(bytes[0]) << 8 | ord(bytes[1])
		self.assertEqual(id, 0)
Пример #19
0
	def testQueryHeaderBits(self):
		generated = r.DNSOutgoing(r._FLAGS_QR_QUERY)
		bytes = generated.packet()
		flags = ord(bytes[2]) << 8 | ord(bytes[3])
		self.assertEqual(flags, 0x0)
Пример #20
0
	def testResponseHeaderBits(self):
		generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
		bytes = generated.packet()
		flags = ord(bytes[2]) << 8 | ord(bytes[3])
		self.assertEqual(flags, 0x8000)
Пример #21
0
 def test_query_header_bits(self):
     generated = r.DNSOutgoing(r._FLAGS_QR_QUERY)
     b = generated.packet().decode()
     flags = ord(b[2]) << 8 | ord(b[3])
     self.assertEqual(flags, 0x0)
Пример #22
0
 def test_transaction_id(self):
     # ID must be zero in a DNS-SD packet
     generated = r.DNSOutgoing(r._FLAGS_QR_QUERY)
     b = generated.packet().decode()
     id = ord(b[0]) << 8 | ord(b[1])
     self.assertEqual(id, 0)
Пример #23
0
 def testParseOwnPacketQuestion(self):
     generated = r.DNSOutgoing(r._FLAGS_QR_QUERY)
     generated.addQuestion(
         r.DNSQuestion("testname.local.", r._TYPE_SRV, r._CLASS_IN))
     parsed = r.DNSIncoming(generated.packet())
     print("parsed questions %s " % parsed.questions)
Пример #24
0
 def testParseOwnPacketFlags(self):
     generated = r.DNSOutgoing(r._FLAGS_QR_QUERY)
     parsed = r.DNSIncoming(generated.packet())
     print("parsed %s " % parsed)
Пример #25
0
 def testParseOwnPacketSimpleUnicast(self):
     generated = r.DNSOutgoing(0, 0)
     parsed = r.DNSIncoming(generated.packet())
     print("parsed %s " % parsed)
     self.assertEqual(type(parsed), r.DNSIncoming)
Пример #26
0
	def testExceedinglyLongNamePart(self):
		name = "%s.local." % ("a" * 1000)
		generated = r.DNSOutgoing(r._FLAGS_QR_RESPONSE)
		question = r.DNSQuestion(name, r._TYPE_SRV, r._CLASS_IN)
		generated.addQuestion(question)
		self.assertRaises(r.NamePartTooLongException, generated.packet)