def turn_on(switch_address, interface, port): print("Power_Cycle - Setting pi at port {} to ON".format(port)) logger.warning("Power_Cycle - Setting pi at port {} to ON".format(port)) errorIndication, errorStatus, errorIndex, varBinds = next( setCmd( SnmpEngine(), CommunityData("private@" + str(private_number), mpModel=0), UdpTransportTarget((switch_address, 161)), ContextData(), ObjectType( ObjectIdentity("1.3.6.1.2.1.105.1.1.1.3.{}.{}".format( interface, port)), Integer(1)), # value of 1 turns the port ON )) if errorIndication: print(errorIndication) logger.error(errorIndication) elif errorStatus: print("Power_Cycle - not found") logger.error("Power_Cycle - not found") else: print("Power_Cycle - Set pi at interface {} port {} to ON".format( interface, port)) logger.warning( "Power_Cycle - Set pi at interface {} port {} to ON".format( interface, port))
def find_port(mac_address, switch_address, vlan_number): """ source: http://snmplabs.com/pysnmp/quick-start.html#fetch-snmp-variable """ errorIndication, errorStatus, errorIndex, varBinds = next( getCmd( SnmpEngine(), CommunityData("public@{}".format(vlan_number), mpModel=0), UdpTransportTarget((switch_address, 161)), ContextData(), ObjectType( ObjectIdentity("1.3.6.1.2.1.17.4.3.1.2.{}".format( mac_in_decimal(mac_address)))), )) if errorIndication: logger.error(errorIndication) elif errorStatus: logger.error("%s at %s" % ( errorStatus.prettyPrint(), errorIndex and varBinds[int(errorIndex) - 1][0] or "?", )) else: result = varBinds[0].prettyPrint() return result.split(" = ")[1]
def broadcast(self, packet): self.configuration.debug('broadcasting:\n {}'.format(str(packet).replace('\n', '\n\t'))) try: data = packet.to_bytes() self.broadcast_socket.sendto(data, ('255.255.255.255', 68)) except: logger.error('error broadcasting') traceback.print_exc()
def run(self): while not self.closed: try: self.update(1) except KeyboardInterrupt: logger.exception("keyboard interrupt") break except: logger.error(traceback.print_exc()) traceback.print_exc()
def received_dhcp_discover(self, discovery): if self.is_done(): return self.configuration.debug('discover:\n {}'.format(str(discovery).replace('\n', '\n\t'))) should_send_offer = False for known_host in self.server.hosts.get(): if discovery.client_mac_address == known_host.to_tuple()[0]: should_send_offer = True if should_send_offer: self.send_offer(discovery) else: logger.error("unknown mac_address {}. will not assign ip.".format(discovery.client_mac_address))
def res_open(self, name): zipfile = os.path.dirname(os.path.dirname(__file__)) fd = None try: with ZipFile(zipfile) as z: fd = z.open("install/boot/" + name) except KeyError: logger.error("{}: key error - looking in filesystem next".format(name)) pass # we'll try looking in the filesystem next if not fd: fd = open("{}/{}".format(self.data_dir, name), "rb") if 'cmdline.txt' in name and fd: # we need to fixup the master address content = fd.read() fd.close() fd = io.BytesIO(content.replace(b'MASTER', self.connection_address.encode())) return fd
def __process_requests(self, client_socket, client_addr): """ This function serves the control socket's coming requests. """ reinstall_file = list() with open('reinstall.txt') as fp: reinstall_file = fp.read() try: logger.info("serving client from: {}".format(client_addr)) fd = client_socket.makefile() date = datetime.now() dt_string = date.strftime('%Y%m%d%H%M.%S') dt_string = 'busybox date -s ' + dt_string + "\n" + "EOM\n" print("Sending date command to pi:", dt_string) client_socket.send(dt_string.encode()) req = fd.readline() while req: req = req.strip() logger.info("TCP - recieved request {}".format(req)) if req == RECV_IS_UNINSTALLED: logger.info("TCT - uninstalled, sending format") # this line of code is suggested by team fire client_socket.send(SEND_FORMAT) elif req == RECV_IS_INSTALLED: if client_addr[0] in reinstall_file: logger.info("TCP - need to reinstall, sending format") client_socket.send(SEND_FORMAT) else: logger.info("TCP - installed, sending boot") client_socket.send(SEND_BOOT) elif req == RECV_IS_FORMATTED: logger.info("TCP - is formatted, sending file") break else: pass #print("TCP - not supported request") req = fd.readline() except: logger.error(traceback.print_exc()) logger.info("tcpdump") client_socket.close()
def update(self, timeout=0): try: reads = select.select([self.socket], [], [], timeout)[0] except ValueError: # ValueError: file descriptor cannot be a negative integer (-1) logger.error("Value error: file descriptor cannot be a negative integer") return for socket in reads: try: packet = ReadBootProtocolPacket(*socket.recvfrom(4096)) # print(packet) except OSError: # OSError: [WinError 10038] An operation was attempted on something that is not a socket logger.error("OSError - operation was attempted on something that is not a socket") pass else: self.received(packet) for transaction_id, transaction in list(self.transactions.items()): if transaction.is_done(): transaction.close() self.transactions.pop(transaction_id)
def __transfer_file(self, client_socket): """ This function serves the file socket's coming requests. """ logger.info("TCP - started file_transferring") try: # opens the specified file in a read only binary form transfer_file = open("{}/{}".format(self.data_dir, "rootfs.tgz"), "rb") data = transfer_file.read() logger.debug("TCP - read rootfs.tgz") if data: # send the data logger.debug("TCP - sending rootfs.tgz") client_socket.send(data) logger.debug("TCP - finished sending rootfs.tgz") except: logger.error(traceback.print_exc()) logger.info("TCP - finished file_transferring") client_socket.close() transfer_file.close()
def __create_thread_and_process_requests(self, pkt, addr): # initial block number and variable for filename block_number = 0 filename = '' # prepare the UDP socket client_dedicated_sock = socket(AF_INET, SOCK_DGRAM) # bind to 0 for an ephemeral port client_dedicated_sock.bind((self.connection_address, 0)) # set timeout for the socket client_dedicated_sock.settimeout(10) # RRQ is a series of strings, the first two being the filename # and mode but there may also be options. see RFC 2347. # # we skip the first 2 bytes (the opcode) and split on b'\0' # since the strings are null terminated. # # because b'\0' is at the end of all strings split will always # give us an extra empty string at the end, so skip it with [:-1] packet = serializeme.Deserialize(pkt, { "opcode": ("2B", 1), "filename": (serializeme.NULL_TERMINATE, serializeme.HOST), "mode": (serializeme.NULL_TERMINATE, serializeme.HOST), "ANSWERS": { "option": (serializeme.NULL_TERMINATE, serializeme.HOST), "value": (serializeme.NULL_TERMINATE, serializeme.HOST) } }) strings_in_RRQ = pkt[2:].split(b"\0")[:-1] logger.info("got {} from {}".format(strings_in_RRQ, addr)) filename = packet.get_field("filename") # opens the file once for the socket, opening multiple times causes tftp to be slow try: transfer_file = self.res_open(filename) while True: # the first two bytes of all TFTP packets is the opcode, so we can # extract that here. the '!' is for big endian, and 'H' is to say it is an integer [opcode] = packet.get_field("opcode") if opcode == TFTPServer.RRQ_OPCODE: if len(strings_in_RRQ) > 4: for index, string in enumerate(strings_in_RRQ[2:]): if string.decode() == 'tsize': temp_file = self.res_open(filename) temp_file.seek(0, 2) t_size = temp_file.tell() if string.decode() == 'blksize': block_size = int(strings_in_RRQ[index + 1]) # construct oack packet = serializeme.Serialize({ "OACK_opcode": ("2B", TFTPServer.OACK_OPCODE), "t_size_str": (serializeme.NULL_TERMINATE, "tsize"), "t_size_len": ("4B", t_size), "t_zero": "1B", "block_size_str": (serializeme.NULL_TERMINATE, "block_size"), "block_size": ("2B", block_size), "blk_zero": "1B" }) client_dedicated_sock.sendto(packet.packetize(), addr) # read up to the appropriate 512 bytes of data if len(strings_in_RRQ) > 4: data = transfer_file.read(block_size) else: data = transfer_file.read(512) # if data is received increment block number, contruct the packet, and send it if data: block_number += 1 packet_format = {"opcode": ("2B", TFTPServer.DATA_OPCODE), "blk": ("2B", block_number), "data": "TBD"} if len(strings_in_RRQ) > 4: packet_format['data'] = (str(block_size) + "B", data) else: packet_format['data'] = ("512B", data) packet = serializeme.Serialize(packet_format) client_dedicated_sock.sendto(packet.packetize(), addr) # ACK received, so we can now read the next block, if it doesn't match resend the previous block of data elif opcode == TFTPServer.ACK_OPCODE: packet = serializeme.Deserialize(pkt, { "opcode": "2B", "Block#": "2B" }) [acked_block] = packet.get_field("Block#") # block number matches, the block sent was successfully received if acked_block == block_number: data = transfer_file.read(512) # if data read, increment block number, construct packet, and send it on the socket if data: block_number += 1 # transfer_block_number = pack("!H", block_number) pkt_format = { "opcode": ("2B", TFTPServer.DATA_OPCODE), "block": ("2B", block_number), "data": ("512B", data) } packet = serializeme.Serialize(pkt_format) client_dedicated_sock.sendto(packet.packetize(), addr) # if no data was read, read returns b'', then EOF was reached and download complete else: # sending a packet of zero data - to acknowledge end of transfer block_number += 1 # transfer_block_number = pack("!H", block_number) pkt_format = { "opcode": ("2B", TFTPServer.DATA_OPCODE), "block": ("2B", block_number) } packet = serializeme.Serialize(pkt_format) client_dedicated_sock.sendto(packet.packetize(), addr) logger.warning('download complete, closing socket') client_dedicated_sock.close() break # if the block number doesn't match, means data sent was not received # here you can just resend the data you already read because, no need for seek or another read # because you already read it and it was not received, doing seek or read would slow down tftp elif block_number != acked_block: # decrement block number block_number = block_number - 1 # transfer_block_number = pack("!H", block_number) pkt_format = { "opcode": ("2B", TFTPServer.DATA_OPCODE), "block": ("2B", block_number), "data": ("512B", data) } packet = serializeme.Serialize(pkt_format) client_dedicated_sock.sendto(packet.packetize(), addr) else: # form an error packet and send it to the invalid TID # error_opcode = pack("!H", TFTPServer.ERROR_OPCODE) # error_code = pack("!H", 21) # error_message = b"incorrect TID\0" pkt_format = { "opcode": ("2B", TFTPServer.ERROR_OPCODE), "errorcode": ("2B", 21), "errormsg": (serializeme.NULL_TERMINATE, "incorrect TID") } logger.error("incorrect TID") packet = serializeme.Serialize(pkt_format) client_dedicated_sock.sendto(packet.packetize(), addr) else: # form an error packet and send it to the invalid TID # error_opcode = pack("!H", TFTPServer.ERROR_OPCODE) # error_code = pack("!H", 20) # error_message = b"illegal operation specified\0" pkt_format = { "opcode": ("2B", TFTPServer.ERROR_OPCODE), "errorcode": ("2B", 20), "errormsg": (serializeme.NULL_TERMINATE, "Illegal operation specified") } logger.error("illegal operation specified") packet = serializeme.Serialize(pkt_format) client_dedicated_sock.sendto(packet.packetize(), addr) # listen for a client response for 10 seconds # close everything and terminate if no response try: pkt, addr = client_dedicated_sock.recvfrom( self.BUFFER_SIZE) except: logger.error("Socket Timed Out") client_dedicated_sock.close() logger.error('closed socket') break except FileNotFoundError: # send an error packet to the requesting host # error_opcode = pack("!H", TFTPServer.ERROR_OPCODE) # error_code = pack("!H", 17) # error_message = b"No such file within the directory\0" pkt_format = { "opcode": ("2B", TFTPServer.ERROR_OPCODE), "errorcode": ("2B", 17), "errormsg": (serializeme.NULL_TERMINATE, "No such file within the directory") } logger.error("No such file within the directory") packet = serializeme.Serialize(pkt_format) client_dedicated_sock.sendto(packet.packetize(), addr) client_dedicated_sock.close()
def exit_piman(): logger.error("Insufficient amount of arguments") exit(1)
def unicast(self, packet): try: self.raw_sock.send(packet) except: logger.error('DCHP - error unicasting') traceback.print_exc()
def __create_thread_and_process_requests(self, pkt, addr): # initial block number and variable for filename block_number = 0 filename = '' # prepare the UDP socket client_dedicated_sock = socket(AF_INET, SOCK_DGRAM) # bind to 0 for an ephemeral port client_dedicated_sock.bind((self.connection_address, 0)) # set timeout for the socket client_dedicated_sock.settimeout(10) # RRQ is a series of strings, the first two being the filename # and mode but there may also be options. see RFC 2347. # # we skip the first 2 bytes (the opcode) and split on b'\0' # since the strings are null terminated. # # because b'\0' is at the end of all strings split will always # give us an extra empty string at the end, so skip it with [:-1] strings_in_RRQ = pkt[2:].split(b"\0")[:-1] logger.info("got {} from {}".format(strings_in_RRQ, addr)) filename = strings_in_RRQ[0] # opens the file once for the socket, opening multiple times causes tftp to be slow try: transfer_file = self.res_open(strings_in_RRQ[0].decode()) while True: # the first two bytes of all TFTP packets is the opcode, so we can # extract that here. the '!' is for big endian, and 'H' is to say it is an integer [opcode] = unpack("!H", pkt[0:2]) if opcode == TFTPServer.RRQ_OPCODE: # set the opcode for the packet we are sending transfer_opcode = pack("!H", TFTPServer.DATA_OPCODE) # read up to the appropriate 512 bytes of data data = transfer_file.read(512) # if data is received increment block number, contruct the packet, and send it if data: block_number += 1 transfer_block_number = pack("!H", block_number) packet = transfer_opcode + transfer_block_number + data client_dedicated_sock.sendto(packet, addr) # ACK received, so we can now read the next block, if it doesn't match resend the previous block of data elif opcode == TFTPServer.ACK_OPCODE: [acked_block] = unpack("!H", pkt[2:4]) # block number matches, the block sent was successfully received if acked_block == block_number: data = transfer_file.read(512) # if data read, increment block number, construct packet, and send it on the socket if data: block_number += 1 transfer_block_number = pack("!H", block_number) packet = transfer_opcode + transfer_block_number + data client_dedicated_sock.sendto(packet, addr) # if no data was read, read returns b'', then EOF was reached and download complete else: logger.warning('download complete, closing socket') client_dedicated_sock.close() break # if the block number doesn't match, means data sent was not received # here you can just resend the data you already read because, no need for seek or another read # because you already read it and it was not received, doing seek or read would slow down tftp elif block_number != acked_block: # decrement block number block_number = block_number - 1 transfer_block_number = pack("!H", block_number) packet = transfer_opcode + transfer_block_number + data client_dedicated_sock.sendto(packet, addr) else: # form an error packet and send it to the invalid TID error_opcode = pack("!H", TFTPServer.ERROR_OPCODE) error_code = pack("!H", 21) error_message = b"incorrect TID\0" logger.error("incorrect TID") packet = error_opcode + error_code + error_message client_dedicated_sock.sendto(packet, addr) else: # form an error packet and send it to the invalid TID error_opcode = pack("!H", TFTPServer.ERROR_OPCODE) error_code = pack("!H", 20) error_message = b"illegal operation specified\0" logger.error("illegal operation specified") packet = error_opcode + error_code + error_message client_dedicated_sock.sendto(packet, addr) # listen for a client response for 10 seconds # close everything and terminate if no response try: pkt, addr = client_dedicated_sock.recvfrom( self.BUFFER_SIZE) except: logger.error("Socket Timed Out") client_dedicated_sock.close() logger.error('closed socket') break except FileNotFoundError: # send an error packet to the requesting host error_opcode = pack("!H", TFTPServer.ERROR_OPCODE) error_code = pack("!H", 17) error_message = b"No such file within the directory\0" logger.error("No such file within the directory") packet = error_opcode + error_code + error_message client_dedicated_sock.sendto(packet, addr) client_dedicated_sock.close()
def __process_requests(self, client_socket, client_addr): """ This function serves the control socket's coming requests. """ reinstall_file = self.__read_reinstall_file() try: logger.info("serving client from: {}".format(client_addr)) fd = client_socket.makefile() date = datetime.now() dt_string = date.strftime('%Y%m%d%H%M.%S') dt_string = 'busybox date -s ' + dt_string + "\n" + "EOM\n" req_dict = { # this dict is used only when the received command results in logging only RECV_RECEIVED_DATE: lambda: logger.info( "TCP - pi successfully received date string"), RECV_SET_DATE: lambda: logger.info("TCP - pi successfully set local datetime" ), RECVD_MOUNTING: lambda: logger.info("TCP - pi mounting has started"), RECVD_MOUNTED: lambda: logger.info("TCP - pi successfully mounted filesystem" ), RECVD_UNMOUNTING: lambda: logger.info("TCP - pi unmounting has started"), RECVD_UNMOUNTED: lambda: logger.info( "TCP - pi successfully unmounted filesystem"), RECVD_BOOT: lambda: logger.info( "TCP - pi successfully received boot command"), RECVD_FORMAT: lambda: logger.info( "TCP - pi successfully received format command"), RECVD_REINSTALL: lambda: logger.info( "TCP - pi successfully received reinstall command") } print("Sending date command to pi:", dt_string) client_socket.send(dt_string.encode()) req = fd.readline() while req: req = req.strip() if req == RECV_IS_UNINSTALLED: logger.info("TCT - uninstalled, sending format") # this line of code is suggested by team fire client_socket.send(SEND_FORMAT) elif req == RECV_IS_INSTALLED: if client_addr[0] in reinstall_file: logger.info("TCP - need to reinstall, sending format") client_socket.send(SEND_FORMAT) #clear reinstall.txt file after sending format signal self.__clear_reinstall_file() else: logger.info("TCP - installed, sending boot") client_socket.send(SEND_BOOT) elif req == RECV_IS_FORMATTED: logger.info("TCP - is formatted, sending file") break else: if req in req_dict: req_dict[req]( ) # log changed state if command is valid and not handled above else: logger.info("TCP - unsupported request: {}".format( req)) # otherwise log unsupported command req = fd.readline() except: logger.error(traceback.print_exc()) logger.info("tcpdump") client_socket.close()