Ejemplo n.º 1
0
    def build(self, transaction=None, **kwargs):
        # dummy empty defaults
        response_string_part = ''
        options_answer_part = None

        # build client if not done yet
        if transaction.client is None:
            transaction.client = Client(transaction)

        bootfiles = transaction.client.bootfiles
        if len(bootfiles) > 0:
            # TODO add preference logic
            bootfile_url = bootfiles[0].BOOTFILE_URL
            transaction.client.chosen_boot_file = bootfile_url
            bootfile_options = hexlify(bootfile_url).decode()
            response_string_part += build_option(self.number, bootfile_options)
            # options in answer to be logged
            options_answer_part = self.number

        return response_string_part, options_answer_part
Ejemplo n.º 2
0
    def build(self, transaction=None, **kwargs):
        # dummy empty defaults
        response_string_part = ''
        options_answer_part = None

        # check if MAC of LLIP is really known
        if transaction.client_llip in collected_macs or cfg.IGNORE_MAC:
            # collect client information
            if transaction.client is None:
                transaction.client = Client(transaction)

            # Only if prefixes are provided
            if 'prefixes' in cfg.CLASSES[transaction.client.client_class].ADVERTISE:
                # check if only a short NoPrefixAvail answer or none at all is to be returned
                if not transaction.answer == 'normal':
                    if transaction.answer == 'noprefix':
                        # Option 13 Status Code Option - statuscode is 6: 'No Prefix available'
                        response_string_part = self.convert_to_string(CONST.OPTION.STATUS_CODE,
                                                                      f'{CONST.STATUS.NO_PREFIX_AVAILABLE:04x}')
                        # clean client prefixes which not be deployed anyway
                        transaction.client.prefixes[:] = []
                        # options in answer to be logged
                        options_answer_part = self.number
                else:
                    # if client could not be built because of database problems send
                    # status message back
                    if transaction.client:
                        # embed option 26 into option 25 - several if necessary
                        ia_prefixes = ''
                        try:
                            for prefix in transaction.client.prefixes:
                                ipv6_prefix = hexlify(inet_pton(AF_INET6, colonify_ip6(prefix.PREFIX))).decode()
                                if prefix.VALID:
                                    preferred_lifetime = f'{int(prefix.PREFERRED_LIFETIME):08x}'
                                    valid_lifetime = f'{int(prefix.VALID_LIFETIME):08x}'
                                else:
                                    preferred_lifetime = f'{0:08x}'
                                    valid_lifetime = f'{0:08x}'
                                length = f'{int(prefix.LENGTH):02x}'
                                ia_prefixes += self.convert_to_string(CONST.OPTION.IAPREFIX,
                                                                      preferred_lifetime +
                                                                      valid_lifetime +
                                                                      length +
                                                                      ipv6_prefix)

                            if transaction.client.client_class != '':
                                t1 = f'{int(cfg.CLASSES[transaction.client.client_class].T1):08x}'
                                t2 = f'{int(cfg.CLASSES[transaction.client.client_class].T2):08x}'
                            else:
                                t1 = f'{int(cfg.T1):08x}'
                                t2 = f'{int(cfg.T2):08x}'

                            # even if there are no prefixes server has to deliver an empty PD
                            response_string_part = self.convert_to_string(self.number,
                                                                          transaction.iaid +
                                                                          t1 +
                                                                          t2 +
                                                                          ia_prefixes)
                            # if no prefixes available a NoPrefixAvail status code has to be sent
                            if ia_prefixes == '':
                                # REBIND not possible
                                if transaction.last_message_received_type == CONST.MESSAGE.REBIND:
                                    # Option 13 Status Code Option - statuscode is 3: 'NoBinding'
                                    response_string_part += self.convert_to_string(CONST.OPTION.STATUS_CODE,
                                                                                   f'{CONST.STATUS.NO_BINDING:04x}')
                                else:
                                    # Option 13 Status Code Option - statuscode is 6: 'No Prefix available'
                                    response_string_part += self.convert_to_string(  # break because line too long
                                                                              CONST.OPTION.STATUS_CODE,
                                                                              f'{CONST.STATUS.NO_PREFIX_AVAILABLE:04x}')
                            # options in answer to be logged
                            options_answer_part = self.number

                        except Exception as err:
                            print(err)
                            # Option 13 Status Code Option - statuscode is 6: 'No Prefix available'
                            response_string_part = self.convert_to_string(CONST.OPTION.STATUS_CODE,
                                                                          f'{CONST.STATUS.NO_PREFIX_AVAILABLE:04x}')
                            # options in answer to be logged
                            options_answer_part = self.number
                    else:
                        # Option 13 Status Code Option - statuscode is 6: 'No Prefix available'
                        response_string_part = self.convert_to_string(CONST.OPTION.STATUS_CODE,
                                                                      f'{CONST.STATUS.NO_PREFIX_AVAILABLE:04x}')
                        # options in answer to be logged
                        options_answer_part = self.number

        return response_string_part, options_answer_part
Ejemplo n.º 3
0
    def build(self, transaction=None, **kwargs):
        # dummy empty defaults
        response_string_part = ''
        options_answer_part = None

        # check if MAC of LLIP is really known
        if transaction.client_llip in collected_macs or cfg.IGNORE_MAC:
            # collect client information
            if transaction.client is None:
                transaction.client = Client(transaction)

            if 'addresses' in cfg.CLASSES[transaction.client.client_class].ADVERTISE and \
                    CONST.OPTION.IA_NA in transaction.ia_options:
                # check if only a short NoAddrAvail answer or none at all is to be returned
                if not transaction.answer == 'normal':
                    if transaction.answer == 'noaddress':
                        # Option 13 Status Code Option - statuscode is 2: 'No Addresses available'
                        response_string_part = self.convert_to_string(CONST.OPTION.STATUS_CODE,
                                                                      f'{CONST.STATUS.NO_ADDRESSES_AVAILABLE:04x}')
                        # clean client addresses which not be deployed anyway
                        transaction.client.addresses[:] = []
                        # options in answer to be logged
                        options_answer_part = CONST.OPTION.STATUS_CODE
                else:
                    # if client could not be built because of database problems send
                    # status message back
                    if transaction.client:
                        # embed option 5 into option 3 - several if necessary
                        ia_addresses = ''
                        try:
                            for address in transaction.client.addresses:
                                if address.IA_TYPE == 'na':
                                    ipv6_address = hexlify(inet_pton(AF_INET6, colonify_ip6(address.ADDRESS))).decode()
                                    # if a transaction consists of too many requests from client -
                                    # - might be caused by going wild Windows clients -
                                    # reset all addresses with lifetime 0
                                    # lets start with maximal transaction count of 10
                                    if transaction.counter < 10:
                                        preferred_lifetime = f'{int(address.PREFERRED_LIFETIME):08x}'
                                        valid_lifetime = f'{int(address.VALID_LIFETIME):08x}'
                                    else:
                                        preferred_lifetime = '00000000'
                                        valid_lifetime = '00000000'
                                    ia_addresses += self.convert_to_string(CONST.OPTION.IAADDR,
                                                                           ipv6_address +
                                                                           preferred_lifetime +
                                                                           valid_lifetime)
                            if ia_addresses != '':
                                #
                                # todo: default clients sometimes seem to have class ''
                                #
                                if transaction.client.client_class != '':
                                    t1 = f'{int(cfg.CLASSES[transaction.client.client_class].T1):08x}'
                                    t2 = f'{int(cfg.CLASSES[transaction.client.client_class].T2):08x}'
                                else:
                                    t1 = f'{int(cfg.T1):08x}'
                                    t2 = f'{int(cfg.T2):08x}'

                                response_string_part = self.convert_to_string(CONST.OPTION.IA_NA,
                                                                              transaction.iaid +
                                                                              t1 +
                                                                              t2 +
                                                                              ia_addresses)
                            # options in answer to be logged
                            options_answer_part = CONST.OPTION.IA_NA
                        except:
                            # Option 13 Status Code Option - statuscode is 2: 'No Addresses available'
                            response_string_part = self.convert_to_string(CONST.OPTION.STATUS_CODE,
                                                                          f'{CONST.STATUS.NO_ADDRESSES_AVAILABLE:04x}')
                            # options in answer to be logged
                            options_answer_part = CONST.OPTION.STATUS_CODE
                    else:
                        # Option 13 Status Code Option - statuscode is 2: 'No Addresses available'
                        response_string_part = self.convert_to_string(CONST.OPTION.STATUS_CODE,
                                                                      f'{CONST.STATUS.NO_ADDRESSES_AVAILABLE:04x}')
                        # options in answer to be logged
                        options_answer_part = CONST.OPTION.STATUS_CODE

        return response_string_part, options_answer_part