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