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
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
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