Exemplo n.º 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] )
Exemplo n.º 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)
Exemplo n.º 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
Exemplo n.º 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)
Exemplo n.º 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")
Exemplo n.º 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)
Exemplo n.º 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
Exemplo n.º 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())
Exemplo n.º 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())
Exemplo n.º 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
Exemplo n.º 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])
Exemplo n.º 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
Exemplo n.º 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())
Exemplo n.º 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)
Exemplo n.º 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)
Exemplo n.º 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())
Exemplo n.º 17
0
	def testParseOwnPacketSimpleUnicast(self):
		generated = r.DNSOutgoing(0, 0)
		parsed = r.DNSIncoming(generated.packet())
Exemplo n.º 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)
Exemplo n.º 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)
Exemplo n.º 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)
Exemplo n.º 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)
Exemplo n.º 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)
Exemplo n.º 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)
Exemplo n.º 24
0
 def testParseOwnPacketFlags(self):
     generated = r.DNSOutgoing(r._FLAGS_QR_QUERY)
     parsed = r.DNSIncoming(generated.packet())
     print("parsed %s " % parsed)
Exemplo n.º 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)
Exemplo n.º 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)