def parse_ipv4_range(range_str): # 1.2.3.4 - 5.6.7.8 if range_str.count(".") == 6 and range_str.count("-") == 1: start_ip_str, end_ip_str = map(lambda s: s.strip(), range_str.split("-", 1)) start_ip = IPv4.from_str(start_ip_str) end_ip = IPv4.from_str(end_ip_str) high_ip = IPv4(int(end_ip) - int(start_ip)) return AddressRange(start_ip, high_ip) if range_str.count(".") == 3: start_ip = IPv4(0) high_ip = IPv4(0) range_str_list = range_str.split(".", 3) for i in xrange(len(range_str_list)): if not range_str_list[i].count("-"): start_ip[i] = high_ip[i] = int(range_str_list[i]) else: start_no, end_no = range_str_list[i].split("-",1) start_ip[i], high_ip[i] = map(int, (start_no, end_no)) return AddressRange(start_ip, high_ip)
def parse_dhcp_option(option_name, _value): option_name = dhcp_option_name_by_alias.get(option_name, option_name) option_type = dhcp_option_type_by_name.get(option_name, OPTION_TYPE_STRING) if option_type == OPTION_TYPE_IP: value = list(IPv4.from_str(_value)) elif option_type == OPTION_TYPE_MULTIPLE_IP: byte_list = list() for ip_str in shlex.split(_value): ipv4 = IPv4.from_str(ip_str) byte_list.extend(ipv4) value = byte_list elif option_type == OPTION_TYPE_MAC: value = list(MAC(_value)) elif option_type == OPTION_TYPE_STRING: value = list(ByteObject.from_ascii(_value)) elif option_type == OPTION_TYPE_INT: value = list(ByteObject(4, _value)) else: raise Exception("UNKNOWN OPTION TYPE") return (option_name, value)
def HandleDhcpInform(self, packet): mac = MAC.from_list(packet.GetHardwareAddress()) logging.debug("GOT: INFORM from " + str(mac)) entry_options = self._calculate_entry_options(str(mac)) ipv4_range_collection = self._get_ipv4_range_collection(entry_options) self._set_packet_options(packet, entry_options) client_lease = self.ip_lease_manager.get_lease(mac=mac) if not client_lease: return None ip = IPv4.from_str(client_lease.ip_str) packet.SetOption('yiaddr', list(ip)) packet.TransformToDhcpAckPacket() dest_relay_or_gateway = None if sum(packet.GetOption('giaddr')): dest_relay_or_gateway = str(IP.from_list(packet.GetOption('giaddr'))) else: dest_relay_or_gateway = "255.255.255.255" logging.debug("SENT: ACK") self.SendDhcpPacketTo(packet, dest_relay_or_gateway, 68)
def HandleDhcpDiscover(self, packet): mac = MAC.from_list(packet.GetHardwareAddress()) logging.debug("DISCOVER: %s", str(mac)) entry_options = self._calculate_entry_options(str(mac)) ipv4_range_collection = self._get_ipv4_range_collection(entry_options) self._set_packet_options(packet, entry_options) backend_ip = entry_options.get('yiaddr', None) requested_ip = self._get_requested_ip_from_packet(packet) ip = None if backend_ip: ip = IPv4.from_list(backend_ip) self.ip_lease_manager.reallocate_ip_address(ip) logging.debug("DISCOVER: %s gets static ip: %s", str(mac), str(ip)) else: ip = self.ip_lease_manager.allocate_ip_address(ipv4_range_collection, mac, requested_ip=requested_ip) logging.debug("DISCOVER: %s requested ip %s, giving %s", str(mac), str(requested_ip), str(ip)) packet.SetOption('yiaddr', list(ip)) packet.TransformToDhcpOfferPacket() logging.debug("DISCOVER: Sent OFFER to %s", str(mac)) self.SendDhcpPacketTo(packet, "255.255.255.255", 68)
def allocate_ip_address(self, address_range_collection, mac, requested_ip=None, use_existing_if_able=True): """ """ ip = None old_lease_ip = None old_mac_lease = self.get_lease(mac=mac) if old_mac_lease: old_lease_ip = IPv4.from_str(old_mac_lease.ip_str) # If the host requested a specific IP and it is available and within the network range, # allow it if requested_ip and requested_ip in address_range_collection and \ (not self._is_active_lease(requested_ip) or self.was_last_leased_to(requested_ip, mac)): ip = requested_ip # If this MAC had a lease, and the lease is allowed within the given range, give that ip elif use_existing_if_able and old_lease_ip and old_lease_ip in address_range_collection: ip = old_lease_ip # If all else fails, allocate a new IP else: ip = self._find_available_ip(address_range_collection,) # We temporarily lease the IP, so we're sure not to give it to anyone else self._lease_ip_address(ip, mac, self.wait_ack_lease_time) return ip
def _get_requested_ip_from_packet(self, packet): for attr in ('ciaddr', 'request_ip_address'): if sum(packet.GetOption(attr)): requested_ip = IPv4.from_list(packet.GetOption(attr)) return requested_ip return None