def tftp_serve(menu_file_handler=None): def handler(s, addr, packet): def get_option(name, default): """ extracting the value of the option {name} from tftp packet. """ for option in packet.options: if option.name == name: return option.value return default def send(built_answer): s.sendto(built_answer, addr) if packet.opcode == 'READ_REQ': logger.info('requested: %s' % packet.source_file) if menu_file_handler: file_to_return = get_file_to_serve(packet.source_file, menu_file_handler) else: file_to_return = get_file_to_serve(packet.source_file) if not file_to_return or not os.path.exists(file_to_return): logger.error('requested file not exists: %s' % file_to_return) return logger.info('served: %s' % file_to_return) blksize = int(get_option('blksize', 512)) stream = open(file_to_return, 'rb') SESSIONS[addr] = TFTPClientSession(stream, blksize) if blksize != 512: # need to ack the block size answer = Container(opcode='OACK', options=[ Container(value=str(blksize), name='blksize')]) send(tftp_header.build(answer)) return session = SESSIONS[addr] answer = Container( opcode='DATA_PACKET', options=[] ) if packet.opcode == 'ACK': answer.block = packet.block + 1 else: answer.block = 0 block = session.get_block(answer.block) if not block: session.close() return built_answer = tftp_header.build(answer) built_answer += block send(built_answer) serve(69, handler, tftp_header.parse)
def dhcp_serve(): def handler(s, addr, parsed_packet, ip_generator=None, boot_offer_filter=default_boot_offer_filter): message_type = get_message_type(parsed_packet) client_mac = parsed_packet.client_hardware_addr offer_boot = boot_offer_filter(client_mac) if message_type == MESSAGE_TYPE_DISCOVER: if not offer_boot: # it's here, so it wont be logged many times. logger.info("Not booting client: %s" % client_mac) if ip_generator: response = build_discover_answer(parsed_packet, ip_generator, offer_boot) else: response = build_discover_answer(parsed_packet, offer_boot) if response: logger.info('Answering Discover') elif message_type == MESSAGE_TYPE_REQUEST: response = create_ack(parsed_packet, offer_boot) if response: logger.info('Answering Request') else: return if not response: return built_answer = dhcp_header.build(response) if '0.0.0.0' == addr[0]: target = '<broadcast>', addr[1] else: target = addr s.sendto(built_answer, target) def filter_func(parsed_packet): return True import threading threading.Thread(target=serve, args=(67, handler, dhcp_header.parse, filter_func)).start() # Both ports need to answer, something with handovering the # pxe responsibility from the real dhcp. serve(4011, handler, dhcp_header.parse, filter_func)