Example #1
0
    def parse_dhcp_resp(self, response):
        """
        Parse DHCP response:
        Returns endpoint server or None on error.
        """
        self.logger.log('Parsing Dhcp response')
        bytes_recv = len(response)
        endpoint = None
        gateway = None
        routes = None

        # Walk all the returned options, parsing out what we need, ignoring the
        # others. We need the custom option 245 to find the the endpoint we talk to
        # options 3 for default gateway and 249 for routes; 255 is end.

        i = 0xF0  # offset to first option
        while i < bytes_recv:
            option = dhcpUtils.str_to_ord(response[i])
            length = 0
            if (i + 1) < bytes_recv:
                length = dhcpUtils.str_to_ord(response[i + 1])
                self.logger.log(
                    "DHCP option {0} at offset:{1} with length:{2}".format(
                        hex(option), hex(i), hex(length)))
            if option == 255:
                self.logger.log("DHCP packet ended at offset:{0}".format(
                    hex(i)))
                break
            elif option == 249:
                routes = self.parse_route(response, option, i, length,
                                          bytes_recv)
            elif option == 3:
                gateway = self.parse_ip_addr(response, option, i, length,
                                             bytes_recv)
                self.logger.log("Default gateway:{0}, at {1}".format(
                    gateway, hex(i)))
            elif option == 245:
                endpoint = self.parse_ip_addr(response, option, i, length,
                                              bytes_recv)
                self.logger.log(
                    "Azure scheduled events endpoint IP:{0}, at {1}".format(
                        endpoint, hex(i)))
            else:
                self.logger.log(
                    "Skipping DHCP option:{0} at {1} with length {2}".format(
                        hex(option), hex(i), hex(length)))
            i += length + 2
        return endpoint, gateway, routes
    def parse_dhcp_resp(self, response):
        """
        Parse DHCP response:
        Returns endpoint server or None on error.
        """
        self.logger.log('Parsing Dhcp response')
        bytes_recv = len(response)
        endpoint = None
        gateway = None
        routes = None

        # Walk all the returned options, parsing out what we need, ignoring the
        # others. We need the custom option 245 to find the the endpoint we talk to
        # options 3 for default gateway and 249 for routes; 255 is end.

        i = 0xF0  # offset to first option
        while i < bytes_recv:
            option = dhcpUtils.str_to_ord(response[i])
            length = 0
            if (i + 1) < bytes_recv:
                length = dhcpUtils.str_to_ord(response[i + 1])
                self.logger.log("DHCP option {0} at offset:{1} with length:{2}".format(hex(option), hex(i), hex(length)))
            if option == 255:
                self.logger.log("DHCP packet ended at offset:{0}".format(hex(i)))
                break
            elif option == 249:
                routes = self.parse_route(response, option, i, length, bytes_recv)
            elif option == 3:
                gateway = self.parse_ip_addr(response, option, i, length, bytes_recv)
                self.logger.log("Default gateway:{0}, at {1}".format(gateway, hex(i)))
            elif option == 245:
                endpoint = self.parse_ip_addr(response, option, i, length, bytes_recv)
                self.logger.log("Azure scheduled events endpoint IP:{0}, at {1}".format(endpoint, hex(i)))
            else:
                self.logger.log("Skipping DHCP option:{0} at {1} with length {2}".format(hex(option), hex(i), hex(length)))
            i += length + 2
        return endpoint, gateway, routes
 def parse_route(self, response, option, i, length, bytes_recv):
     # http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
     self.logger.log("Routes at offset: {0} with length:{1}".format(hex(i), hex(length)))
     routes = []
     if length < 5:
         self.logger.log("Data too small for option:{0}" + str(option))
     j = i + 2
     while j < (i + length + 2):
         mask_len_bits = dhcpUtils.str_to_ord(response[j])
         mask_len_bytes = (((mask_len_bits + 7) & ~7) >> 3)
         mask = 0xFFFFFFFF & (0xFFFFFFFF << (32 - mask_len_bits))
         j += 1
         net = dhcpUtils.unpack_big_endian(response, j, mask_len_bytes)
         net <<= (32 - mask_len_bytes * 8)
         net &= mask
         j += mask_len_bytes
         gateway = dhcpUtils.unpack_big_endian(response, j, 4)
         j += 4
         routes.append((net, mask, gateway))
     if j != (i + length + 2):
         self.logger.log("Unable to parse routes")
     return routes
Example #4
0
 def parse_route(self, response, option, i, length, bytes_recv):
     # http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
     self.logger.log("Routes at offset: {0} with length:{1}".format(
         hex(i), hex(length)))
     routes = []
     if length < 5:
         self.logger.log("Data too small for option:{0}" + str(option))
     j = i + 2
     while j < (i + length + 2):
         mask_len_bits = dhcpUtils.str_to_ord(response[j])
         mask_len_bytes = (((mask_len_bits + 7) & ~7) >> 3)
         mask = 0xFFFFFFFF & (0xFFFFFFFF << (32 - mask_len_bits))
         j += 1
         net = dhcpUtils.unpack_big_endian(response, j, mask_len_bytes)
         net <<= (32 - mask_len_bytes * 8)
         net &= mask
         j += mask_len_bytes
         gateway = dhcpUtils.unpack_big_endian(response, j, 4)
         j += 4
         routes.append((net, mask, gateway))
     if j != (i + length + 2):
         self.logger.log("Unable to parse routes")
     return routes
Example #5
0
    def build_dhcp_request(self, mac_addr, request_broadcast):
        """
        Build DHCP request string.
        """
        #
        # typedef struct _DHCP {
        #  UINT8   Opcode;                    /* op:    BOOTREQUEST or BOOTREPLY */
        #  UINT8   HardwareAddressType;       /* htype: ethernet */
        #  UINT8   HardwareAddressLength;     /* hlen:  6 (48 bit mac address) */
        #  UINT8   Hops;                      /* hops:  0 */
        #  UINT8   TransactionID[4];          /* xid:   random */
        #  UINT8   Seconds[2];                /* secs:  0 */
        #  UINT8   Flags[2];                  /* flags: 0 or 0x8000 for broadcast*/
        #  UINT8   ClientIpAddress[4];        /* ciaddr: 0 */
        #  UINT8   YourIpAddress[4];          /* yiaddr: 0 */
        #  UINT8   ServerIpAddress[4];        /* siaddr: 0 */
        #  UINT8   RelayAgentIpAddress[4];    /* giaddr: 0 */
        #  UINT8   ClientHardwareAddress[16]; /* chaddr: 6 byte eth MAC address */
        #  UINT8   ServerName[64];            /* sname:  0 */
        #  UINT8   BootFileName[128];         /* file:   0  */
        #  UINT8   MagicCookie[4];            /*   99  130   83   99 */
        #                                        /* 0x63 0x82 0x53 0x63 */
        #     /* options -- hard code ours */
        #
        #     UINT8 MessageTypeCode;              /* 53 */
        #     UINT8 MessageTypeLength;            /* 1 */
        #     UINT8 MessageType;                  /* 1 for DISCOVER */
        #     UINT8 End;                          /* 255 */
        # } DHCP;
        #

        # tuple of 244 zeros
        # (struct.pack_into would be good here, but requires Python 2.5)
        request = [0] * 244

        trans_id = self.gen_trans_id()

        # Opcode = 1
        # HardwareAddressType = 1 (ethernet/MAC)
        # HardwareAddressLength = 6 (ethernet/MAC/48 bits)
        for a in range(0, 3):
            request[a] = [1, 1, 6][a]

        # fill in transaction id (random number to ensure response matches request)
        for a in range(0, 4):
            request[4 + a] = dhcpUtils.str_to_ord(trans_id[a])

        self.logger.log("BuildDhcpRequest: transactionId:{0},{1:04x}".format(
            dhcpUtils.hex_dump2(trans_id),
            dhcpUtils.unpack_big_endian(request, 4, 4)))

        if request_broadcast:
            # set broadcast flag to true to request the dhcp sever
            # to respond to a boradcast address,
            # this is useful when user dhclient fails.
            request[0x0A] = 0x80

        # fill in ClientHardwareAddress
        for a in range(0, 6):
            request[0x1C + a] = dhcpUtils.str_to_ord(mac_addr[a])

        # DHCP Magic Cookie: 99, 130, 83, 99
        # MessageTypeCode = 53 DHCP Message Type
        # MessageTypeLength = 1
        # MessageType = DHCPDISCOVER
        # End = 255 DHCP_END
        for a in range(0, 8):
            request[0xEC + a] = [99, 130, 83, 99, 53, 1, 1, 255][a]
        return array.array("B", request)
    def build_dhcp_request(self, mac_addr, request_broadcast):
        """
        Build DHCP request string.
        """
        #
        # typedef struct _DHCP {
        #  UINT8   Opcode;                    /* op:    BOOTREQUEST or BOOTREPLY */
        #  UINT8   HardwareAddressType;       /* htype: ethernet */
        #  UINT8   HardwareAddressLength;     /* hlen:  6 (48 bit mac address) */
        #  UINT8   Hops;                      /* hops:  0 */
        #  UINT8   TransactionID[4];          /* xid:   random */
        #  UINT8   Seconds[2];                /* secs:  0 */
        #  UINT8   Flags[2];                  /* flags: 0 or 0x8000 for broadcast*/
        #  UINT8   ClientIpAddress[4];        /* ciaddr: 0 */
        #  UINT8   YourIpAddress[4];          /* yiaddr: 0 */
        #  UINT8   ServerIpAddress[4];        /* siaddr: 0 */
        #  UINT8   RelayAgentIpAddress[4];    /* giaddr: 0 */
        #  UINT8   ClientHardwareAddress[16]; /* chaddr: 6 byte eth MAC address */
        #  UINT8   ServerName[64];            /* sname:  0 */
        #  UINT8   BootFileName[128];         /* file:   0  */
        #  UINT8   MagicCookie[4];            /*   99  130   83   99 */
        #                                        /* 0x63 0x82 0x53 0x63 */
        #     /* options -- hard code ours */
        #
        #     UINT8 MessageTypeCode;              /* 53 */
        #     UINT8 MessageTypeLength;            /* 1 */
        #     UINT8 MessageType;                  /* 1 for DISCOVER */
        #     UINT8 End;                          /* 255 */
        # } DHCP;
        #

        # tuple of 244 zeros
        # (struct.pack_into would be good here, but requires Python 2.5)
        request = [0] * 244

        trans_id = self.gen_trans_id()

        # Opcode = 1
        # HardwareAddressType = 1 (ethernet/MAC)
        # HardwareAddressLength = 6 (ethernet/MAC/48 bits)
        for a in range(0, 3):
            request[a] = [1, 1, 6][a]

        # fill in transaction id (random number to ensure response matches request)
        for a in range(0, 4):
            request[4 + a] = dhcpUtils.str_to_ord(trans_id[a])

        self.logger.log("BuildDhcpRequest: transactionId:{0},{1:04x}".format(dhcpUtils.hex_dump2(trans_id), dhcpUtils.unpack_big_endian(request, 4, 4)))

        if request_broadcast:
            # set broadcast flag to true to request the dhcp sever
            # to respond to a boradcast address,
            # this is useful when user dhclient fails.
            request[0x0A] = 0x80;

        # fill in ClientHardwareAddress
        for a in range(0, 6):
            request[0x1C + a] = dhcpUtils.str_to_ord(mac_addr[a])

        # DHCP Magic Cookie: 99, 130, 83, 99
        # MessageTypeCode = 53 DHCP Message Type
        # MessageTypeLength = 1
        # MessageType = DHCPDISCOVER
        # End = 255 DHCP_END
        for a in range(0, 8):
            request[0xEC + a] = [99, 130, 83, 99, 53, 1, 1, 255][a]
        return array.array("B", request)