예제 #1
0
def handle(server, raddress, message):
    try:
        message = dns.message.from_wire(message)
    except:
        print "Error decoding DNS message"
        return

    if message.edns < 0:
        print "Received non-EDNS message, ignoring"
        return

    if not (message.opcode() == 5 and message.authority):
        print "Received non-UPDATE message, ignoring"
        return

    info = {'records': [], 'addresses': []}

    # Try to guess the interface this came in on
    for iface in netifaces.interfaces():
        ifaddresses = netifaces.ifaddresses(iface)
        for af, addresses in ifaddresses.items():
            if af != 2:  # AF_INET
                continue
            for address in addresses:
                net = IPy.IP(address['addr']).make_net(address['netmask'])
                if IPy.IP(raddress[0]) in net:
                    info['mymac'] = ifaddresses[17][0]['addr']
                    info['myif'] = iface

    for rrset in message.authority:
        info['records'].append(rrset)
        _add_addresses(info, rrset)

    for option in message.options:
        if option.otype == 2:
            info['ttl'] = struct.unpack("!L", option.data)
        if option.otype == 4:
            info['othermac'] = option.data.encode('hex_codec')[4:]

    # TODO: endsflags seems to indicate some other TTL

    # TODO: Better composability
    manage_host(info)

    _answer(server.socket, raddress, message)
예제 #2
0
def handle(server, raddress, message):
    try:
        message = dns.message.from_wire(message)
    except:
        print "Error decoding DNS message"
        return

    if message.edns < 0:
        print "Received non-EDNS message, ignoring"
        return

    if not (message.opcode() == 5 and message.authority):
        print "Received non-UPDATE message, ignoring"
        return

    info = {'records': [], 'addresses': []}

    # Try to guess the interface this came in on
    for iface in netifaces.interfaces():
        ifaddresses = netifaces.ifaddresses(iface)
        for af, addresses in ifaddresses.items():
            if af != 2:  # AF_INET
                continue
            for address in addresses:
                net = IPy.IP(address['addr']).make_net(address['netmask'])
                if IPy.IP(raddress[0]) in net:
                    info['mymac'] = ifaddresses[17][0]['addr']
                    info['myif'] = iface

    for rrset in message.authority:
        info['records'].append(rrset)
        _add_addresses(info, rrset)

    for option in message.options:
        if option.otype == 2:
            info['ttl'] = struct.unpack("!L", option.data)
        if option.otype == 4:
            info['othermac'] = option.data.encode('hex_codec')[4:]

    # TODO: endsflags seems to indicate some other TTL

    # TODO: Better composability
    manage_host(info)

    _answer(server.socket, raddress, message)
예제 #3
0
    def handle(self, message, raddress):
        try:
            #with ignored(dns.message.BadEDNS):
            message = dns.message.from_wire(message, ignore_trailing=True)
        except dns.message.BadEDNS:
            #yosemite's discoveryd sends an OPT record per active NIC, dnspython doesn't like more than 1 OPT record
            #  https://github.com/rthalley/dnspython/blob/master/dns/message.py#L642
            #  so turn off Wi-Fi for ethernet-connected clients
            pass  #or send back an nxdomain or servfail
        except:  #no way to just catch dns.exceptions.*
            logging.warning("Error decoding DNS message from {}".format(
                raddress[0]))
            logging.debug(traceback.format_exc())
            return

        if message.edns < 0:
            logging.warning(
                "Received non-EDNS message from {}, ignoring".format(
                    raddress[0]))
            return

        if not (message.opcode() == 5 and message.authority):
            logging.warning(
                "Received non-UPDATE message from {}, ignoring".format(
                    raddress[0]))
            return

        logging.debug("Received SPS registration from {}, parsing".format(
            raddress[0]))

        info = {'records': [], 'addresses': []}

        # Try to guess the interface this came in on
        #   todo - precompute this table on new()?
        for iface in netifaces.interfaces():
            ifaddresses = netifaces.ifaddresses(iface)
            for af, addresses in ifaddresses.items():
                if af not in (netifaces.AF_INET, netifaces.AF_INET6): continue
                for address in addresses:
                    mask = address['netmask']
                    if af == netifaces.AF_INET6:
                        mask = (
                            mask.count('f') * 4
                        )  # convert linux masks to prefix length...gooney
                    if address['addr'].find('%') > -1:
                        continue  #more linux ipv6 stupidity
                    iface_net = ipaddress.ip_interface('{}/{}'.format(
                        address['addr'], mask)).network
                    if ipaddress.ip_address(raddress[0]) in iface_net:
                        info['mymac'] = ifaddresses[
                            netifaces.AF_LINK][0]['addr']
                        info['myif'] = iface

        for rrset in message.authority:
            rrset.rdclass %= dns.rdataclass.UNIQUE  #remove cache-flush bit
            #rrset.rdata = rrset.rdata.decode(utf-8)
            info['records'].append(rrset)
            self._add_addresses(info, rrset)

        logging.debug('NSUPDATE START--\n\n{}\n\n{}\n\n--NSUPDATE END'.format(
            message, message.options))

        for option in message.options:
            if option.otype == dns.edns.UL:
                info['ttl'] = option.lease  #send-WOL-no-later-than timer TTL
            if option.otype == dns.edns.OWNER:
                info['othermac'] = option.pmac  #WOL target mac
                #if option.passwd: # password required in wakeup packet
                #  mDNS.c:SendSPSRegistrationForOwner() doesn't seem to add a password

        self._answer(raddress, message)

        if len(message.options) == 2:
            # need both an owner and an update-lease option, else its just a post-wake notification (incremented seq number)
            manage_host(info)