Example #1
0
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))
Example #2
0
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]
Example #3
0
 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()
Example #4
0
 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()
Example #5
0
 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))
Example #6
0
 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
Example #7
0
 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()
Example #8
0
 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)
Example #9
0
    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()
Example #10
0
    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()
Example #11
0
def exit_piman():
    logger.error("Insufficient amount of arguments")
    exit(1)
Example #12
0
 def unicast(self, packet):
     try:
         self.raw_sock.send(packet)
     except:
         logger.error('DCHP - error unicasting')
         traceback.print_exc()
Example #13
0
    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()
Example #14
0
    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()